关于多表查询性能的问题

Posted

技术标签:

【中文标题】关于多表查询性能的问题【英文标题】:Questions about multi-table query performance 【发布时间】:2012-12-11 09:36:25 【问题描述】:

多表查询有两种方式:

查询 1:

select t1.a, t2.b from t1, t2 where t1.a = t2.a

查询 2:

对于每一行:

select t1.a from t1

做另一个查询:

select t2.b from t2 where t2.a = '??'

当表很大时,哪个性能更好?

【问题讨论】:

执行 1 个查询比执行许多查询要快。如果没有,那么您需要向表中添加索引。 查询 2 是什么意思?它是一个子选择还是您打算使用游标来循环“每一行”? 如果您唯一的考虑是在您的数据库上运行一个查询,那么第一个会运行得更快,但是,如果这是一个多用户环境并且表非常大,那么第一个会运行得更快可能会导致更长的锁,并可能与其他用户发生死锁,您需要确保指定相关的表提示来管理锁。 在不相关的注释上,关于使用from t1, t2 WHERE t1.a = t2.a 而不是from t1 inner join t2 on t1.a = t2.a 可能值得一读this。 【参考方案1】:

您应该始终让 DBMS 在单个查询中完成尽可能多的工作。

DBMS 知道每个数据库中有多少元组,并且有办法估计结果将具有的元组数量。现代 DBMS 具有非常复杂的算法,负责找到执行任何查询的最有效方法(计划器)。

除非您知道自己在做什么以及为什么要这样做(即您知道您的算法将比 DBMS 运行得更快,更重要的是,为什么)您应该让 DMBS 完成它的工作。

更准确地回答您的问题:

您的查询 #1 可以用各种方法回答,具体取决于表的大小。让我们假设两者都是巨大的。一种解决方法是使用基于排序的连接:根据连接属性对两个表进行排序,然后合并它们。这基本上相当于对每个表进行合并排序所需的时间。每个表的每一页都将被读取和写入几次(取决于您在 DMBS 中有多少可用的缓冲区空间)。所以 T1 和 T2 中的每个元组都会被读/写十几次。

如果我们实现您的方法,那么查询的数量将与 T1 大小的元组一样多。让我们假设 T2 没有索引,因此查询将读取 T2 中的每个元组 T1 次。

如果您在 T2 上有一个索引,您可以期望为 T1 中的每个元组读取几页。因此,查询的成本是读取 T1 的成本,然后对于 T1 中的每个元组,您需要阅读几页(2-5)以在 T2 中找到匹配的元组。

如果 T1 非常小而 T2 非常大,查询 2 会更快!但是,DBMS 会发现这一点,并将完全执行您的算法来回答 Q1(它被称为基于循环的连接)。此外,您发送到 DBMS 的每个查询都需要时间来处理(方法 1 没有的开销)。

这是一个常见的天真的 DBMS 程序员的错误:让 DB 做一些工作,然后为每个元组做更多的工作。

相反,您应该考虑让 DBMS 在尽可能少的查询中完成所有处理。它会在性能上得到回报。

最后,如果您真的对性能感兴趣,请获取您最喜欢的 DMBS 的文档并阅读它如何进行查询评估,以及如何改进它。

--dmg

【讨论】:

以上是关于关于多表查询性能的问题的主要内容,如果未能解决你的问题,请参考以下文章

查询性能:多表查询对比。复合查询

多表查询在数据量非常大的时候性能不好,慎用!

MySQL数据库多表查询

MySQL数据库多表查询

5MySQL多表查询

关于mysql的多表联合模糊查询问题