希望用减去优化查询来节省太多时间...如果他们能给予感谢帮助。
我有两张桌子A和B,
表A:ID,值
表B:ID
我想要表B中没有的所有表A记录。显示值。 因为它是这样的:
Select ID, value
FROM A
WHERE value> 70
MINUS
Select ID
FROM B;
只有这个查询花了太长时间...任何提示这个简单查询的最佳方法是什么?
感谢您的关注
答案 0 :(得分:4)
ID和值是否已编入索引?
减号和不存在的表现取决于:
这实际上取决于一系列因素。
除非有一些,否则MINUS将对两个表进行全表扫描 允许索引的两个查询的where子句中的条件 范围扫描。 A MINUS还要求两个查询都相同 列数,每列与数据类型相同 另一个查询中的相应列(或者一个可转换为 相同类型)。一个MINUS将返回第一个查询中的所有行 第二个查询的列没有完全匹配列。一个 MINUS还需要隐式排序两种查询
NOT EXISTS将为外部的每一行读取一次子查询 查询。如果是相关字段(您正在运行相关的 子查询?)是一个索引字段,然后只进行索引扫描。
选择使用哪种构造取决于您的数据类型 想要返回,还有两个表/查询的相对大小。 如果外表相对于内表和内表较小 表被索引(优先选择唯一索引但不是必需的) 相关字段,然后NOT EXISTS可能会更快,因为 索引查找将非常快,并且只执行相对较少的 倍。如果两个表的大小大致相同,那么MINUS可能是 更快,特别是如果你只能看到你的领域 正在比较。
Minus operator versus 'not exists' for faster SQL query - Oracle Community Forums
你可以这样使用NOT EXISTS
:
SELECT a.ID, a.Value
From a
where a.value > 70
and not exists(
Select b.ID
From B
Where b.ID = a.ID)
编辑:我已经制作了一些虚拟数据和两个数据集用于测试,以证明索引的性能提升。注意:我在MySQL中这样做,因为我的Macbook上没有Oracle。
表A 有2600条记录,包含2列:ID,val。 ID是自动增量整数 Val varchar(255)
表b 有一列,但记录多于表A.自动增量(间隙为3)
如果您愿意,可以重现这一点:Pastebin - SQL Dummy Data
以下是我将要使用的查询:
select a.id, a.val from tablea a
where length(a.val) > 3
and not exists(
select b.id from tableb b where b.id = a.id
);
没有索引,运行时 986ms ,有1685行。
现在我们添加索引:
ALTER TABLE `tablea` ADD INDEX `id` (`id`);
ALTER TABLE `tableb` ADD INDEX `id` (`id`);
使用索引,运行时 14ms ,有1685行。没有索引的时间是 1.42%!