我有两张桌子。第一个表(用户)是一个简单的" id,用户名" 100,00行,第二个(统计数据)是" id,date,stat"有20M行。
我试图弄清楚哪个用户名在统计信息中上升最多,这是我的查询。在功能强大的计算机上,此查询需要几分钟才能完成。是否有更好的方法来编写它以加快速度?
SELECT a.id, a.username, b.stat, c.stat, (b.stat - c.stat) AS stat_diff
FROM users AS a
INNER JOIN stats AS b ON (b.id=a.id)
INNER JOIN stats AS c ON (c.id=a.id)
WHERE b.date = '2016-01-10'
AND c.date = '2016-01-13'
GROUP BY a.id
ORDER BY stat_diff DESC
LIMIT 100
我试过的另一种方式,但它似乎并不是最佳的
SELECT a.id, a.username,
(SELECT b.stat FROM stats AS b ON (b.id=a.id) AND b.date = '2016-01-10') AS start,
(SELECT c.stat FROM stats AS c ON (c.id=a.id) AND c.date = '2016-01-14') AS end,
((SELECT b.stat FROM stats AS b ON (b.id=a.id) AND b.date = '2016-01-10') -
(SELECT c.stat FROM stats AS c ON (c.id=a.id) AND c.date = '2016-01-14')) AS stat_diff
FROM users AS a
GROUP BY a.id
ORDER BY stat_diff DESC
LIMIT 100
答案 0 :(得分:0)
查询似乎没问题,验证您的索引..
或者 试试这个查询
SELECT a.id, a.username, b.stat, c.stat, (b.stat - c.stat) AS stat_diff
FROM users AS a
INNER JOIN (select id,stat from stats where date = '2016-01-10') AS b ON (b.id=a.id)
INNER JOIN (select id,stat from stats where date = '2016-01-13') AS c ON (c.id=a.id)
GROUP BY a.id
ORDER BY stat_diff DESC
LIMIT 100
答案 1 :(得分:0)
您需要做的就是帮助优化器。最低限度。有一个如下所示的检查清单
1.我的连接列是否已编入索引?
2.在哪里条款Sargable
3.是否存在任何隐含的,明确的转换
4.我看到任何统计问题
另一个有趣的方面是你的数据是如何分配的,一旦你理解了数据,你就能够代表执行计划并根据你的需要改变它
<强> EX:强> 想想我有100个客户表,每个至少有10个订单(总计高达10000个订单)。现在如果你只需要按日期查找前三个订单,你不希望扫描发生订单表
现在在你的情况下,我可能不会选择第二个选项,即使优化器也可以为这个选择一个好的计划,我会先进入并尝试查看执行时间是否可接受。如果不是我将通过我的检查清单并尝试进一步调整
答案 2 :(得分:0)
<强>简介强>
让我们假设我们重写这样的句子:
SELECT a.id, a.username, b.stat, c.stat, (b.stat - c.stat) AS stat_diff
FROM users AS a
INNER JOIN stats AS b ON
b.date = STR_TO_DATE('2016-01-10', '%Y-%m-%d' ) and b.id=a.id
INNER JOIN stats AS c ON
c.date = STR_TO_DATE('2016-01-13', '%Y-%m-%d' ) and c.id=a.id
GROUP BY a.id
ORDER BY stat_diff DESC
LIMIT 100
我们确保:
users
表在字段id
上有索引:stats
包含复合字段date
的索引,id
:create index stats_idx_d_i on stats ( date, id );
,然后强>
数据库优化器可以使用索引来选择受限制的日期集('RSD'),这意味着匹配已过滤日期的行。这很快。
<强>但是强>
您按计算字段排序:
(b.stat - c.stat) AS stat_diff #<-- calculated
ORDER BY stat_diff DESC #<-- this forces to calculate it
这种类型无法进行优化,因为您应该逐一计算'RSD'(受限制的数据集)的所有结果。
<强>结论强>
问题是,'RSD'上的行数怎么样?如果它们只有几百行,那么查询可能会快速运行,否则,您的查询将会很慢。
无论如何,你应该确保查询的第一步(没有排序)是由索引而不是全扫描。使用Explain
命令确保。