【发布时间】:2011-11-15 11:48:58
【问题描述】:
在我来工作的公司,他们运行一个 PHP/MySQL 关系数据库。我一直认为,如果我需要从不同的表中提取不同的信息,我可以做一个简单的连接来提取数据,例如......
SELECT table_1.id, table_2.id FROM table_1 LEFT JOIN table_2 ON table_1.sub_id = table_2.id
当我到达我目前工作的地方时,他们就是这样做的。
<?php $query = mysql_query("SELECT sub_id FROM table_1");
while($rs = mysql_fetch_assoc($query)) {
$query_2 = mysql_fetch_assoc(mysql_query("SELECT * FROM table_2 WHERE id = '{$rs['sub_id']}'"));
//blah blah blah more queries
?>
当我问为什么采用第二种方式时,他们说它实际上比连接运行得更快。他们管理的数据库在不同的表上有数百万条记录,其中一些表有点宽(按行)。他们说他们希望避免在执行不佳的查询可能锁定一个表(或其中几个)的情况下进行连接。要记住的另一件事是,此数据库附带一个庞大的报表生成器,客户可以使用它来构建自己的报表,如果他们发疯并构建大型报表,可能会造成严重破坏。
我很困惑,所以我想我会把它扔给普通的编程公众。这可能是一个见仁见智的问题,但是执行 while 语句(一个更大的查询来拉出很多行,如果你愿意的话,接着是很多小的小子查询)或进行连接(拉一次更大的查询以获取您需要的所有数据)。只要索引做得正确,这有关系吗?要考虑的另一件事是当前数据库是 InnoDB 格式。
谢谢!
2014 年 8 月 28 日更新
所以我想我会对此进行更新,以及更长期有效的方法。经过这次讨论,我决定在工作中重建报告生成器。我没有确切的结果数字,但我想我会分享结果。
我认为这有点矫枉过正,因为我将整个报告(就返回的数据而言,它是非常动态的)变成了一个大规模的加入盛宴。大多数连接(如果不是全部连接)都将值连接到主键,因此它们都运行得非常快。如果报表有 30 列数据要提取并且它提取了 2000 条记录,那么每个字段都在运行查询以获取数据(因为该数据可能位于不同的字段中)。 30 x 2000 = 60000,即使在每次查询 0.0003 秒的甜蜜查询时间下,这仍然是 18 秒的查询时间(这几乎是我记得的时间)。现在我将查询重建为一堆主键上的大规模连接(如果可能),相同的报告在大约 2-3 秒内加载,大部分时间都在下载 html。根据所需数据,返回的每条记录都会运行 0-4 个额外查询(如果它可以在连接中获取数据,则可能不需要任何数据,这种情况发生在 75% 的时间)。因此,同样的 2000 条记录将返回额外的 0-8000 条查询(比 60000 条要好得多)。
我会说 while 语句在某些情况下很有用,但正如下面在 cmets 中所述,基准测试就是它的全部意义所在。就我而言,join 是更好的选择,但在我网站的其他区域,while 语句更有用。在一个例子中,我有一份报告,其中客户可以请求几个类别来拉取并且只返回这些类别的数据。发生的事情是我有一个带有 50-500 个 ID 的 category_id IN(...,...,..,.., etc etc etc),当我在最后时刻拿着它时,索引会窒息并死在我的怀里。所以我所做的是将 id 分成 10 个一组展开,并运行相同的查询 x / 10 次,我的结果比以前更快地获取 方式,因为索引喜欢处理 10 个 ID,而不是 500 个,所以我看到我的查询有了很大的改进,因为执行了 while 语句。
【问题讨论】:
-
对其进行基准测试。你的同事不会因为网上有人说他们错了而改变主意。想出一个像样的测试用例,并尝试两种方式。但是,如果您可以向他们展示确切的数字,他们怎么能反对呢?
标签: php mysql join while-loop