简体   繁体   English

在循环中运行SQL count(*)查询或尝试将其合并到父查询中是否更快?

[英]Is it faster to run an SQL count(*) query in a loop, or try to merge it into the parent query?

I have an SQL query. 我有一个SQL查询。

SELECT `shifts`.*, `races`.`race_attrition_rate`
FROM `shifts`
JOIN `races` ON `races`.`race_id` = `shifts`.`race_id`
WHERE `shifts`.`race_id` = 'X'
AND `shift_deleted` =0
ORDER BY `shift_name` ASC, `shift_id` ASC

That query pulls a list of volunteer shifts from a database. 该查询从数据库中提取了志愿者轮班列表。 Then I have a PHP loop that, for each shift that was pulled in the above query, runs this SQL query. 然后,我有一个PHP循环,对于上述查询中拉出的每个班次,都将运行此SQL查询。

SELECT COUNT(*) AS `numrows`
FROM `volunteer_shifts`
WHERE `shift_id` = 'Y'
AND `shift_deleted` =0

So if there are 5 shifts pulled in the first query, the second query is run 5 times, one time for each shift. 因此,如果在第一个查询中提取了5个班次,则第二个查询将运行5次,每次查询一次。

1) Can these two queries be merged together? 1)这两个查询可以合并在一起吗? What would the combined code look like? 合并后的代码是什么样的?

2) Is merging these two queries together faster? 2)将这两个查询合并在一起的速度更快吗?

3) Merging them together would probably make the code less readable. 3)将它们合并在一起可能会使代码的可读性降低。 So what is best practice? 那么什么是最佳实践? Two readable queries or one hard to read but fast query? 两个可读查询还是一个难以理解但快速的查询?

We don't know which one would run faster unless you post your table schema. 除非您发布表架构,否则我们不知道哪个会运行得更快。 If I were you I would probably run query 1, collect all of the shift_id s then run 1 more query that pulls the counts for the list of shift_id using IN . 如果您是我,我可能会运行查询1,收集所有shift_id然后再运行1个查询,使用INshift_id列表的计数。

Something like this. 这样的事情。

SELECT COUNT(*) AS `numrows`, `shift_id`
FROM `volunteer_shifts`
WHERE `shift_id` IN ('42','other number', 'more numbers'...)
AND `shift_deleted` =0
GROUP BY `shift_id`

In this case, pure SQL would be more maintainable, readable, and efficient than looping at application layer (ie, PHP). 在这种情况下,纯SQL比在应用程序层(即PHP)循环更易于维护,可读性和效率更高。 Hence, consider joining the aggregate query as a derived table (notice shift_id is now a grouping). 因此,考虑将聚合查询作为派生表加入(注意shift_id现在是一个分组)。 Now, the count will appear inline with other fields in one query: 现在,该计数将在一个查询中与其他字段内联显示:

SELECT s.*, r.`race_attrition_rate`, agg.`numrows`
FROM `shifts` s
JOIN `races` r ON r.`race_id` = s.`race_id`

JOIN (
      SELECT `shift_id`, COUNT(*) AS `numrows`
      FROM `volunteer_shifts`
      WHERE `shift_deleted` = 0
      GROUP BY `shift_id`
     ) AS agg

ON agg.shift_id = s.shift_id

WHERE r.`race_id` = '17'
AND s.`shift_deleted` = 0
ORDER BY s.`shift_name` ASC, s.`shift_id` ASC

2) Is merging these two queries together faster? 2)将这两个查询合并在一起的速度更快吗?

Single query will be definetely faster, as there is no time spent on network activity (just imagine that DB is located at another server, that is quite usual case) 单个查询的速度将大大提高,因为无需花费任何时间进行网络活动(假设数据库位于另一台服务器上,这是很常见的情况)

Also separate-queries approach doesn't allow built-in DB query optimizer to do its work 另外,单独查询方法不允许内置的数据库查询优化器执行其工作

1) Can these two queries be merged together? 1)这两个查询可以合并在一起吗? What would the combined code look like? 合并后的代码是什么样的?

Following query may work for you: 以下查询可能适合您:

SELECT 
  `shifts`.*,
  `races`.`race_attrition_rate`,
  (SELECT 
      COUNT(*) AS `numrows`
    FROM 
      `volunteer_shifts`
    WHERE
      `volunteer_shifts`.`shift_id` = `shifts`.`shift_id`
    AND 
      `shift_deleted` = 0) AS `volunteer_shifts`
FROM 
  `shifts`
  JOIN `races` ON `races`.`race_id` = `shifts`.`race_id`
WHERE 
  `shifts`.`race_id` = 'X'
AND 
  `shift_deleted` = 0
ORDER BY 
  `shift_name` ASC, `shift_id` ASC

3) So what is best practice? 3)那么什么是最佳实践? Two readable queries or one hard to read but fast query? 两个可读查询还是一个难以理解但快速的查询?

General rule is "Readability is the main point until you get problems with performance". 一般规则是“在性能出现问题之前,可读性才是重点”。 Just because Computing resources are cheaper than Human resources 仅仅因为计算资源比人力资源便宜

If all you want is the count that the second SQL produces, then it would be more readable, and it would be way shorter. 如果您想要的只是第二条SQL产生的计数,那么它将更具可读性,并且会更短。

SELECT COUNT(*) numrows
FROM shifts
Where shift_id = 42 
   and race_id = '17'
   and shift_deleted = 0

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM