我应该将复杂查询拆分为一个来过滤结果,还是一个来收集数据?

时间:2013-03-25 10:31:24

标签: mysql sql performance

我正在PHP Web应用程序中设计一个中心搜索功能。它集中在一个表中,每个结果只是该表中的一个唯一ID。不幸的是,有几十个与这个中心表相关的表,其中大多数是1:n关系。更不幸的是,我需要加入其中的一些。一对夫妇收集显示结果的必要数据,一对夫妇根据搜索标准过滤。

我一直主要依靠单个查询来执行此操作。它有很多连接,因为每个ID应该只显示一个结果,它也适用于相当复杂的子查询和按用途分组。它也可以根据用户设置的排序方法进行排序,并且使用LIMIT也可以进行分页。

无论如何,这个查询变得非常复杂,而我很好地在PHP中构建它是一个PITA来改变或调试。因此我一直在考虑另一种方法,我想知道在实际开发之前这对于性能有多糟糕(或不是?)。这个想法如下:

  • 运行一个不太复杂的查询,只根据搜索参数进行过滤。这意味着更少的连接,我可以完全忽略分组和类似的结构,我将只是“SELECT DISTINCT item_id”,并得到一个ID列表

  • 然后运行另一个查询,这次只加入我需要显示结果的表(只有当前总连接数的1/4),使用... WHERE item_id IN(....),传递第一个查询中收集的“有效”ID列表。

注意:显然IN()实际上可以包含完整的第一个查询,而不是依赖于PHP来构建以逗号分隔的列表。)

IN在性能方面有多糟糕?我不能限制第一个查询,这可能会对我造成多大伤害?我也想知道这是否是一种常见的方法,或者是否有更聪明的方法来做到这一点。我要感谢任何关于此的意见:)

请注意澄清:我们不是在谈论一些简单的连接。在那里甚至有(简单的)分层数据,我需要将搜索参数与项目自己的数据进行比较,而不是与父项的数据进行比较。在我曾经做过的其他项目中,我遇到了接近这种复杂性的查询。在您说之前,是的,数据本身具有这种固有的复杂性,这也是数据模型复杂的原因。

1 个答案:

答案 0 :(得分:0)

我的经验表明,使用WHERE IN(...)方法往往会变慢。我会选择连接,但请确保您首先加入最小的数据集。减少简单的主表,然后加入到它。确保将最复杂的连接保存到最后,以最大限度地减少搜索所需的行。尝试尽可能地加入索引以提高速度,并尽可能在JOINS中抛弃通配符。

但我同意Andomar,如果你有时间构建并测量。