JOINS与while语句

时间:2011-09-12 16:13:39

标签: php mysql join while-loop

在我上班的公司,他们运行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语句在某些情况下很有用,但正如下面评论中所述,基准测试就是它的全部内容。在我的例子中,连接是更好的选择,但在我的网站的其他区域,while语句更有用。在一个实例中,我有一个报告,其中客户端可以请求多个类别,并仅返回这些类别的数据。发生的事情是我有一个category_id IN(...,...,..,.., etc etc etc)有50-500个ID,索引会在我的怀抱中窒息而死,因为我在最后时刻拿着它。所以我所做的是以10个为一组分散ID并运行相同的查询x / 10次,我的结果比以前更快地获取 way 因为索引喜欢处理10个ID,而不是500个,所以我看到我的查询有了很大的改进,因为做了while语句。

5 个答案:

答案 0 :(得分:4)

如果正确使用了索引,那么使用JOIN几乎总是更高效。增加重点是因为最佳效率并不总是等于最佳性能。

但实际上并没有一个适合所有人的答案;您应该使用EXPLAIN分析查询以确保正在使用索引,没有不必要的临时表使用等。在某些情况下,条件合谋创建一个查询只是不能使用索引。在这些情况下,可能可以更快地将查询分成您指定的方式。

如果我在现有项目中遇到此类代码,我会质疑它:检查查询,考虑执行查询的不同方法,确保已考虑这些事项,构建科学的,事实支持的案例或反对这种做法。确保原始开发人员尽职尽责,因为不使用JOIN表面上指的是糟糕的数据库或查询设计。但最后,结果大声说话,如果所有优化和更正仍然导致比使用查询片段提供的连接速度慢,则更快的解决方案占优势。对基准测试结果进行基准测试并采取行动;软件设计中没有任何情况下你应该交易性能差,以便遵守关于你应该或不应该做什么的任意规则。表现最好的方法是最好的方法。

答案 1 :(得分:2)

如果索引放置得很好,那么做大查询应该会更好。

背后的逻辑:

  • 1 query = 1调用DB服务器,然后处理查询(优化器和所有),最后返回结果。 N个查询意味着对数据库的N次调用,包括对优化器的N次调用,以及坏的情况下的I / O.
  • MySQL具有对JOIN有效的优化。如果你做一段时间,那些优化就无法奏效。

如前面的答案中所述,如果您使用JOIN,请检查EXPLAIN是否存在未使用索引的内容。此外,您应该检查InnoDB缓存的内存,以及MySQL解析给定查询的内存。也许是因为这些参数在执行JOIN时数据库变慢了。

答案 2 :(得分:1)

我会说答案是,这取决于。通常,我会说连接是答案,在循环中进行多个查询是不好的做法,但是,它完全取决于正在做什么。

是你的情况吗?如果没有详细的表结构和索引信息以及外键等的使用,我们不能肯定地说。如果你想检查,最好的想法是试试看。获取他们的查询,解析他们,编写自己的查询,然后对其进行解析,看看哪个更有效。

答案 3 :(得分:1)

我不确定大型数据库,但在我的项目中,我总是尽量将查询保持在最低限度。查询使用硬盘访问和(如果不在同一主机上)网络访问,这很慢。如果第一个查询中有许多条目,那么每页运行数千个查询就会很慢。

答案 4 :(得分:1)

找出实际答案的基准。

使用您提供的示例,数据库的连接(使用等效数据)与设置新连接和执行完全相同的操作(使用完毕:您仍在连接数据的方式与连接相同,即使是外部完成的):如果是,则可以简单地重写引擎以使用该外部路由来提高性能。

当连接使用更多资源时(除了索引问题),它主要来自检索每行数据的缺点,这意味着父表的信息将在每一行中重复,即使这是多余的。

这可能会导致性能问题,如果出现以下情况,可以通过拆分查询来解决这些问题:

  1. 一个父母有很多孩子和
  2. 您从父级(许多列或大字段)中获取大量数据
  3. 根据我的经验,减少查询的数量几乎总能带来性能(我通过组合查询进行优化而不是挑选它们)。

    正确使用指数当然是一个很好的建议,但乍一看我认为它不会解释这两种情景之间的差异,因为相同的指数(或缺乏指数)将适用于这两种情况。