【问题标题】:Join takes too long加入时间太长
【发布时间】:2011-07-03 17:52:14
【问题描述】:

我有这个在 Oracle 中运行大约需要 5 分钟的查询:

select t1.A,t2.B,t2.C,t2.D,t2.E 
from TABLE1 t1 join TABLE2 t2 
on t2.X = t1.Y 
where t1.F = <integer> 
and t2.G = <integer> 
and t1.H = <integer> 

t1 有 170 万行,t2 有 3100 万行。我在 t2.X 和 t1.F 上有索引。尝试在 t1.Y、t2.G 和 t1.H 上添加索引,但它们没有帮助。有什么想法可以提高此联接的性能吗?

【问题讨论】:

  • 可以发布查询计划吗?查询返回多少行?各种条件的选择性如何?
  • t2.G 和 t1.H 返回几乎整个表,t1.F 仅返回 2 行
  • 如果对于任何给定的 F 值,T1 中只有 2 行,并且如果 T2 中 T1 中的每一行都有 10 行,那么您的对象统计信息似乎不正常。使用 T1.F 上的索引和 T2.X 上的索引的简单嵌套循环连接应该花费不到一秒的时间。即使查询计划恰好是 70 行,查看查询计划也会非常有用。
  • 选择声明;按索引 ROWID (t1) 访问表;嵌套循环;表访问完全(t1); INDEX RANGE SCAN(t1.F 上的索引)
  • 在下面的答案中创建索引后:SELECT STATEMENT;哈希连接;表访问完全(t2);按索引 ROWID (t1)、索引范围扫描(t1 上的索引(H、F、Y))的表访问

标签: sql database performance oracle join


【解决方案1】:

查看所有涉及的字段,每个表上的覆盖索引将涉及可能的列

t1: Y, F, H, A
t2: X, G, C, D, E

任何标准的选择性如何:t2.X、t2.G 或 t1.Y、t1.F、t1.H?

如果没有一个单独的列具有足够的选择性(理想情况下为 0.5% 或更少),您可能需要创建一个或多个涉及多个列的覆盖索引,例如

t2 (G, X)
t1 (H, F, Y)

注意:索引中列的顺序非常重要 - 始终将最有选择性的(将列数据划分为最不同的集合)放在首位。

以存储为代价,您可以通过在索引本身中提供所有必要的列来使索引覆盖查询。这意味着查询根本不需要返回表数据。

create index ix_t2 on t2 (G,X) INCLUDE (C,D,E)
create index ix_t1 on t1 (H,F,Y) INCLUDE (A)

编辑

看起来我在其中插入了一个 SQL Server DDL。在 Oracle 中,您必须将索引扩展为 t2 (G,X, C,D,E) - 但由于索引键变得非常长,这增加了对索引使用的选择性要求。

【讨论】:

  • 太棒了,这两个索引将时间缩短到 45 秒
  • 还有其他可以提高性能的指标吗?我可以在运行此查询之前创建它们(实际上我需要为不同的 t1.F 值运行多次)并在完成后删除它们。
  • 谢谢!知道甲骨文中是否有任何等价的东西吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-17
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 2011-07-03
  • 1970-01-01
相关资源
最近更新 更多