如何降低此查询的成本?

问题描述 投票:0回答:1

我有两张桌子,table1table2table2包含table1记录的权限,i。即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

如何降低此查询的成本?

oracle oracle11g sql-execution-plan
1个回答
1
投票

您在exists子句上有一个相关子查询作为谓词,它对每个已过滤的父行执行。试试这个。 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
);
© www.soinside.com 2019 - 2024. All rights reserved.