SQL 联合优化为左连接,速度更快,但查询计划表示 I/O 成本更高

Posted

技术标签:

【中文标题】SQL 联合优化为左连接,速度更快,但查询计划表示 I/O 成本更高【英文标题】:SQL union optimized into a left join, faster but Query Plan says cost more I/O 【发布时间】:2012-02-08 02:55:56 【问题描述】:
select id, c.name as name
from a join b on a.id=b.id
join c on a.id=c.id
union
select id, d.name as name
from a join b on a.id=b.id
join d on a.id=d.id

优化到

select id, 
       case when c.name is not null or c.name <> '' then c.name 
       else d.name end as name
from a join b on a.id=b.id
left join c on a.id=c.id
left join d on a.id=d.id
where c.name is not null or d.name is not null

查询响应时间从 30 秒提高到 13 秒。

sql 联合 = 30 秒 sql 左连接 = 13 秒

但是在检查查询计划时,sql union 的 I/O 成本较低,如下所示:

sql union = 语句 1(第 1 行)的总估计 I/O 成本:6277566。 sql left join= 语句 1(第 1 行)的总估计 I/O 成本:10481124。

我使用的是 Sybase 12.5 ASE,查询计划来自 DBArtisan 8.5;让我知道是否需要上传整个查询计划。我对查询计划还不是很熟悉,但我在这里和那里进行 sql 优化,通常我只是基于时间改进。我还检查了两个查询的结果集是否相同(27949 行)。我还掩盖并简化了表名。

我的问题是,这是否意味着 sql left join 更快但更占用资源?如果是这样,我还应该选择更快的替代方案吗?

【问题讨论】:

查询计划通常基于统计数据,而实际查询执行将取决于实际数据。你的统计数据是最新的吗? 统计数据是最新的是什么意思?我刚刚执行了查询计划,我在这里发布的 I/O 编号是最近的。 数据库定期收集有关表的统计信息(记录数等)并使用这些统计信息来确定查询计划。如果您的统计数据已过时,则该计划可能不是最佳的。例如,如果您创建一个新表并插入大量数据并且未收集统计信息,则数据库将执行查询,就好像该表为空一样。这可能会导致一个糟糕的计划。 【参考方案1】:

数据库将在内部进行一些缓存,因此执行时间并不总是最好的指标。如果您运行第一个查询,然后立即运行第二个查询,那么第二个查询将处于不公平的优势,因为某些数据可能会被缓存。

就像所有数据库调优问题一样,没有什么是一成不变的。我个人喜欢联合,因为我认为它更具可读性,但严格从性能角度来看,我会在更长的时间内进行一些扩展测试(以尽量减少缓存的影响)并看看它们的性能。

这些表中有多少数据?四个表中的 id 列是否有索引?如果没有,那将加快您的查询速度,以加快对 sql 的任何更改。

【讨论】:

以上是关于SQL 联合优化为左连接,速度更快,但查询计划表示 I/O 成本更高的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server调优系列基础篇(联合运算符总结)

SQL Server调优系列基础篇(并行运算总结)

具有三个未索引联合表和左连接的 MySQL 查询使数据库负担过重

SQL Server:在左连接查询的执行计划中插入隐藏的“排序”

简述mysql最左原则

SQL Server 2008 - 连接导致性能下降