【问题标题】:optimize query with minus oracle使用减号 oracle 优化查询
【发布时间】:2015-05-01 08:08:24
【问题描述】:

想要优化一个查询,减去它需要太多时间......如果他们可以提供感谢帮助。

我有两张桌子 A 和 B,

表 A:ID、值

表 B:ID

我想要所有不在表 B 中的表 A 记录。显示值。 因为它是这样的:

Select ID, value
FROM A
WHERE value> 70
MINUS
Select ID
FROM B;

只有这个查询花费的时间太长......任何提示如何最好这个简单的查询?

感谢关注

【问题讨论】:

  • 查询时间过长时:community.oracle.com/message/1814597
  • 回复您删除的答案:CREATE INDEX tablea_id ON a (id);CREATE INDEX tablea_value ON a (value(10));CREATE INDEX tableb_value ON b (id);docs.oracle.com/cd/E17952_01/refman-5.0-en/create-index.html可见
  • 问题是据说不能在表上创建索引....逃脱我的控制...
  • 您好,请查看我的更新答案。您可以使用索引显着提高查询的性能。您的查询或 MINUS 或 NOT EXISTS 都没有问题,没有任何魔法发生。需要这么长时间的原因是因为您在没有索引的情况下完成了这一切。我希望这有帮助。如果您无法创建索引,那么您将陷入性能不佳的困境。谁负责数据库。告诉他们,他们需要把头从背后拉出来并索引桌子!
  • 我刚刚想到的另一个想法是您可以生成物化视图。如果我记得的话,物化视图会按照您指定的时间间隔(每天一次或每小时一次)将数据加载到内存中。因此,当您查询该视图时,它应该是即时的。如果您愿意,您可以尝试创建每个表的物化视图,这可能有助于提高性能。我与 Oracle 合作已经有 6 个月了,所以我不太确定具体情况。

标签: oracle optimization


【解决方案1】:

ID 和 Value 是否已编入索引?

Minus 和 Not Exists 的表现取决于:

这真的取决于很多因素。

一个 MINUS 将对两个表进行全表扫描,除非有一些 允许索引的两个查询的 where 子句中的条件 范围扫描。减号还要求两个查询具有相同的 列数,并且每列具有与 另一个查询中的对应列(或可转换为 同类型)。一个 MINUS 将返回第一个查询中的所有行,其中 与第二个查询的列没有完全匹配的列。一种 MINUS 还需要对两个查询进行隐式排序

NOT EXISTS 将为外部中的每一行读取一次子查询 询问。如果相关字段(您正在运行相关的 sub-query?) 是索引字段,则只进行索引扫描。

选择使用哪种构造取决于您的数据类型 想要返回,以及两个表/查询的相对大小。 如果外部表相对于内部表小,则内部表 表被索引(最好是唯一索引,但不是必需的) 相关字段,那么 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`);

使用索引,运行时间为 14 毫秒,有 1685 行。这是在没有索引的情况下所花费的 1.42%

【讨论】:

  • 感谢您的帮助。字段未编入索引。而且我认为表 B 大于 A。但是有一个子句,我注意到速度有很大差异。问题甚至是检查整个表 B。我想要表 A 中但不在表 B 中的所有值(数字)。对于这两个表,合金有一个 ID(数字)。老实说,看不到有很大的改进..我认为在这种情况下,我不会从不存在中获得太多好处...可以在此查询中使用 pl / sql。使用pl / sql将数据加载到内存中似乎是不错的选择?
猜你喜欢
  • 1970-01-01
  • 2014-05-27
  • 2015-02-26
  • 2011-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多