mysql - 使用 order by 的 SQL 查询运行速度非常慢

标签 mysql sql performance select sql-order-by

我有两张 table 。 上传利润

上传:

╔════╦══════════════╦══════════════════╗
║ id ║  name        ║ more columns...  ║
╠════╬══════════════╬══════════════════╣
║  1 ║ Jeff Atwood  ║ ................ ║
║  2 ║ Geoff Dalgas ║ ................ ║
║  3 ║ Jarrod Dixon ║ ................ ║
║  4 ║ Joel Spolsky ║ ................ ║
╚════╩══════════════╩══════════════════╝

利润:

╔══════════╦══════════════╦══════════════════╗
║ uploadid ║    amount    ║ more columns...  ║
╠══════════╬══════════════╬══════════════════╣
║    1     ║     4.0      ║ ................ ║
║    1     ║     7.2      ║ ................ ║
║    3     ║     6.3      ║ ................ ║
║    4     ║     2.5      ║ ................ ║
╚══════════╩══════════════╩══════════════════╝

如您所见,uploads.id => profits.uploadid

我想显示 uploads 表中的一些行,再显示一列,告诉我有多少“利润”。

结果示例:

╔════╦══════════════╦════════════════╦══════════════════╗
║ id ║  name        ║  profitsCount  ║ more columns...  ║
╠════╬══════════════╬════════════════╬══════════════════╣
║  1 ║ Jeff Atwood  ║       2        ║ ................ ║
║  2 ║ Geoff Dalgas ║       0        ║ ................ ║
║  3 ║ Jarrod Dixon ║       1        ║ ................ ║
║  4 ║ Joel Spolsky ║       1        ║ ................ ║
╚════╩══════════════╩════════════════╩══════════════════╝

注意:在真实表中,uploads.idprofits.uploadid 列是 varchar 而不是 int,我在这里使用 int 是为了更清楚。

问题是,当我使用大型表(数千行)运行查询时,它会花费很多时间

我的查询:

SELECT          `uploads`.* ,COUNT(`profits`.`uploadid`) AS `numProfits`
FROM            `uploads`
LEFT JOIN       `profits`
ON              `uploads`.`id` = `profits`.`uploadid`
GROUP BY        `uploads`.`id`
ORDER BY        `numProfits`
DESC
LIMIT           30

最佳答案

这是您的查询:

SELECT u.* ,COUNT(p.uploadid) AS numProfits
FROM uploads LEFT JOIN
     profits p
     ON u.id = p.uploadid
GROUP BY u.id
ORDER BY numProfits DESC
LIMIT 30;

第一个改进:在 profits(uploadid) 上创建一个索引。这可能会解决您的问题。您可能能够通过以下方式获得更好的性能:

select u.*,
       (select count(*) from profits p where u.id = p.uploadid) as numProfits
from uploads u
order by numProfits desc
limit 30;

这消除了对文件排序聚合的需要。我更喜欢带有显式聚合的第一个版本,但子查询可以更好地工作。

您还可以在子查询中尝试聚合:

select u.*, numProfits
from uploads u join
     (select uploadid, count(*) as numProfits
      from profits p
      group by uploadid
      order by numProfits desc
      limit 30
     ) p
     on u.id = p.uploadid;
order by numProfits desc;

编辑:

对于最后一个解决方案,要选择没有利润的行,请使用 left joincoalesce():

select u.*, coalesce(numProfits, 0) as numProfits
from uploads u left join
     (select uploadid, count(*) as numProfits
      from profits p
      group by uploadid
      order by numProfits desc
      limit 30
     ) p
     on u.id = p.uploadid;
order by numProfits desc;

关于mysql - 使用 order by 的 SQL 查询运行速度非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24283461/

相关文章:

mysql - 在给定登机和下机时间的情况下查找每小时载客量

java - 如何调整 wicket 应用程序的性能

Javascript 没有在 <script> 中触发,但在 PhoneGap 函数 onBodyLoad() 中工作,这是为什么?

algorithm - 该算法的大 O 表示法是什么

mysql - 在InnoDB中,所有的sql都在事务中吗?

mysql - 同时进行 SQL 连接和分组

php - 我无法将 PHP 变量传递给 SQL 查询

mysql - 在 HP ALM 的合并两个查询中需要帮助

sql - 如何解决 raster_columns 问题?

mysql - Rails 3 - 列名(遗留数据库)