如何降低查询费用?

时间:2019-03-25 10:06:14

标签: oracle oracle11g sql-execution-plan

我有两个表table1table2table2包含table1中记录的权限,即e。 table1中的一行可以在table2中具有多个对应的行。

现在,我需要编写一条SQL语句来检索这些table1记录,

  1. 具有特定的主键(table1.ID)和
  2. 没有任何指定的权限。

我想到了这个查询:

SELECT table1.id
FROM TABLE1 table1
WHERE table1.ID IN (<ID_List>) AND
(<Excluded_permission_List>) NOT IN (
    Select PERMISSION_NAME
    from TABLE2 table2 
    where table2.perm_owner_id = table1.id
);

其中

  • <ID_List>是要搜索的所有table1主键的列表,并且
  • <Excluded_permission_List>所有排除的权限的列表(即,如果table1记录具有<Excluded_permission_List>中包含的任何权限,则它不应出现在结果中)。

示例:

SELECT table1.id
FROM TABLE1 table1
WHERE table1.ID IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) AND
('SUPERUSER-1', 'MODERATOR-2') NOT IN (
    Select PERMISSION_NAME
    from TABLE2 table2 
    where table2.perm_owner_id = table1.id
);

该查询应该返回那些table1记录,

  • 具有ID 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
  • 既没有SUPERUSER-1的权限,也没有MODERATOR-2的权限。

此查询有效,但根据EXPLAIN PLAN,费用为38(请参见下文)。

EXPLAIN PLAN output

如何减少此查询的费用?

1 个答案:

答案 0 :(得分:1)

您在存在子句上有一个相关子查询作为谓词,该子查询针对每个过滤的父行执行。尝试这个。 CBO可能会将谓词重写为反联接(哈希联接或嵌套循环)

SELECT table1.id
FROM TABLE1 table1
WHERE table1.ID IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) AND
(('SUPERUSER-1', table1.id), ('MODERATOR-2', table1.id)) NOT IN (
    select table2.permission_name, table2.perm_owner_id
    from TABLE2 table2 
    where table2.perm_owner_id is not null and table2.permission_name is not null
);