2016-04-26 60 views
1

我在为Oracle 12c编写的查询中遇到性能很差的问题。这可能与我对连接的低效使用有关,并希望有人能帮我解决我出错的地方。我的查询目前有需要一分钟时间才能运行加入性能较差的SQL查询

我正在尝试在表和列名返回:

  • 列属于主键
  • 列类型是数字
  • 表的所有者是MY_OWNER
  • 的主键是一列约束

真正水流我的查询看起来如下

SELECT consCols.table_name, consCols.column_name 
FROM all_cons_columns consCols 
INNER JOIN all_constraints cons 
    ON cons.constraint_name = consCols.constraint_name 
INNER JOIN all_tab_columns cols 
    ON consCols.table_name = cols.table_name AND consCols.column_name = cols.column_name 
WHERE cons.constraint_type = 'P' 
AND cons.owner = 'MY_OWNER' 
AND cols.data_type = 'NUMBER' 
AND consCols.table_name IN(
    SELECT consCols2.table_name 
    FROM all_cons_columns consCols2 
    INNER JOIN all_constraints cons2 
    ON cons2.constraint_name = consCols2.constraint_name 
    WHERE cons2.constraint_type = 'P' 
    AND cons2.owner = 'MY_OWNER' 
    GROUP BY consCols2.table_name 
    HAVING COUNT(consCols2.table_name) = 1 
); 

谢谢你给我的任何帮助。

+1

请运行查询和发布结果的解释计划。 – OldProgrammer

回答

3

将使用分析函数加快查询?

SELECT table_name, column_name 
FROM (SELECT consCols.table_name, consCols.column_name, cols.data_type, 
      COUNT(*) OVER (PARTITION BY consCols.table_name) as cnt 
     FROM all_cons_columns consCols INNER JOIN 
      all_constraints cons 
      ON cons.constraint_name = consCols.constraint_name INNER JOIN 
      all_tab_columns cols 
      ON consCols.table_name = cols.table_name AND consCols.column_name = cols.column_name 
     WHERE cons.constraint_type = 'P' AND 
      cons.owner = 'MY_OWNER' 
    ) tc    
WHERE data_type = 'NUMBER' AND cnt = 1; 

甚至聚合?

SELECT consCols.table_name, consCols.column_name 
    FROM all_cons_columns consCols INNER JOIN 
     all_constraints cons 
     ON cons.constraint_name = consCols.constraint_name INNER JOIN 
     all_tab_columns cols 
     ON consCols.table_name = cols.table_name AND consCols.column_name = cols.column_name 
    WHERE cons.constraint_type = 'P' AND 
     cons.owner = 'MY_OWNER' 
    GROUP BY consCols.table_name, consCols.column_name 
    HAVING COUNT(*) = 1 AND 
     MAX(cols.data_type) = 'NUMBER'; 

这是第三个选项:

SELECT consCols.table_name, consCols.column_name 
    FROM all_cons_columns consCols INNER JOIN 
     all_constraints cons 
     ON cons.constraint_name = consCols.constraint_name INNER JOIN 
     all_tab_columns cols 
     ON consCols.table_name = cols.table_name AND consCols.column_name = cols.column_name 
    WHERE cons.constraint_type = 'P' AND 
     cons.owner = 'MY_OWNER' AND 
     cols.data_type = 'NUMBER' AND 
     NOT EXISTS (SELECT 1 
        FROM all_cons_columns acc 
        WHERE acc.constraint_name = consCols.constraint_name AND 
          acc.table_name = consCols.table_name AND 
          acc.column_name <> consCols.column_name 
        ); 

这消除了汇总和查询应该是比较快的。

+0

谢谢@Gordon。你的答案大概需要20秒才能获胜。虽然我希望不到5秒钟,但这仍然是一个重大进步,对我有很大的帮助。 – Venick

+0

不错的答案。在聚合SQL中有一个小错误 - 删除倒数第三行的AND。我发现从10g升级到12c后,数据字典查询确实需要更长的时间。 –

+0

更正,答案编号大约在20秒左右,但回答2实际上返回的行数太多。没关系,虽然我可以坚持#1。 同样的答案#3不适合我,因为all_constraints没有column_name列:( – Venick