Oracle Statement性能:检索排除组合外键的主键

时间:2013-08-08 15:12:21

标签: sql performance oracle

对于我的应用程序,我需要检索某个数据库模式的所有表的主键列,不包括那些也是外键的列。
换句话说,如果M:N关系表不使用自己的主键,而是使用两个外键的组合作为主键,则应排除这些列。

现在可以使用以下语句轻松完成第一部分:

SELECT   ac.table_name,
         acc.column_name
FROM     all_constraints ac,
         all_cons_columns acc
WHERE    ac.constraint_name = acc.constraint_name
  AND    ac.constraint_type = 'P'
  AND    ac.owner = UPPER('MY_SCHEMA')
ORDER BY ac.table_name, acc.position

对我的情况执行此操作大约需要0.2秒。 现在我尝试使用以下添加来排除组合外键:

  AND    NOT EXISTS(
   SELECT 1
   FROM   all_constraints ac1, all_cons_columns acc1
   WHERE  ac1.constraint_name = acc1.constraint_name
     AND  ac1.owner = ac.owner
     AND  ac1.table_name = ac.table_name
     AND  acc1.column_name = acc.column_name
     AND  ac1.constraint_type = 'R'
  )

现在执行整个语句大约需要2.5秒。

是否有更有效的方法来获得相同的结果?

我总是可以执行两个单独的查询,将结果放入列表中,并从代码中的列表1中删除列表2的条目,但我更愿意使用单个语句解决方案。

为了使这个问题不那么主观,我会有这些规则:

  • 我会赞成任何我认为有帮助的答案(我总是这样做)
  • 我会接受第一个让执行时间低于一秒的答案

PS:我正在使用Oracle 10g并且语句是使用.NETOracle.DataAccess.dll应用程序执行的,但我从SqlDeveloper获得的执行时间几乎相同。< / p>


解决方案:

根据Don Bracuk的回答,我使用以下声明设法将执行时间缩短到120毫秒左右:

SELECT   table_name, column_name
FROM
(
  SELECT ac.table_name, acc.column_name
  FROM   all_constraints ac, all_cons_columns acc
  WHERE  ac.constraint_type = 'P'
    AND  ac.owner = UPPER('my_schema')
    -- if you wondered, "UPPER" is used as 'my_schema' is inserted at runtime
  MINUS  
  SELECT ac1.table_name, acc1.column_name
  FROM   all_constraints ac1, all_cons_columns acc1
  WHERE  ac1.constraint_type = 'P'
    AND  ac1.owner = UPPER('my_schema')
)
ORDER BY table_name;

2 个答案:

答案 0 :(得分:3)

你可以试试这个结构:

select yourfields
from yourtables
where whatever
and somefield in 
(select somefield
 fromyourtables
 where the conditions are the same as above
 minus
 select the same field
 from whereever
 where you want to exclude it)

如果这是我的问题,我认为值得尝试。

答案 1 :(得分:2)

在一个相当大的生产数据库上运行了285毫秒。

SELECT  AC.TABLE_NAME
        ,ACC.COLUMN_NAME
FROM    ALL_CONSTRAINTS AC
INNER JOIN
        ALL_CONS_COLUMNS ACC
ON      AC.CONSTRAINT_NAME = ACC.CONSTRAINT_NAME
LEFT OUTER JOIN
        (   ALL_CONSTRAINTS AC1
        INNER JOIN
            ALL_CONS_COLUMNS ACC1
        ON  AC1.CONSTRAINT_NAME = ACC1.CONSTRAINT_NAME        
        )
ON      AC1.TABLE_NAME = AC.TABLE_NAME
AND     ACC1.COLUMN_NAME = ACC.COLUMN_NAME
AND     ACC1.OWNER = AC.OWNER
AND     AC1.CONSTRAINT_TYPE = 'R'          
WHERE   AC.CONSTRAINT_TYPE = 'P'
AND     AC.OWNER = UPPER('APP_NIKU')
AND     AC1.TABLE_NAME IS NULL
ORDER BY AC.TABLE_NAME, ACC.POSITION
;