使用order by,SQL查询运行速度非常慢

时间:2014-06-18 10:41:03

标签: mysql sql performance select sql-order-by

我有两张桌子。 uploadsprofits

上传:

╔════╦══════════════╦══════════════════╗
║ 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      ║ ................ ║
╚══════════╩══════════════╩══════════════════╝

如您所见,uploadsid => profitsuploadid

我想显示uploads表中的一些行,还有一列可以告诉我有多少"利润"有。。

结果示例:

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

注意:在实际表中,uploadsidprofitsuploadid列为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

2 个答案:

答案 0 :(得分:2)

这是您的查询:

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;

答案 1 :(得分:-2)

您可以通过按字段索引顺序来最小化SQL选择查询时间,这可能(并且将会)影响您的插入时间(并且只要索引列受到影响就会更新)