我担心性能。
可以优化以下mysql查询吗?
SELECT u.name, t2.transactions, o2.orders FROM users AS u
LEFT JOIN (
SELECT t.aid AS tuid, SUM( IF( t.status = 1, t.amount, 0 ) ) AS transactions
FROM transactions AS t
WHERE ( t.datetime BETWEEN ('2018-01-01 00:00:00') AND ( '2020-01-01 23:59:59' ) ) GROUP BY t.aid
) AS t2 ON tuid = u.id
LEFT JOIN (
SELECT o.aid AS ouid, SUM(o.net) AS orders FROM orders AS o
WHERE ( o.date BETWEEN ('2018-01-01 00:00:00') AND ( '2020-01-01 23:59:59' ) ) GROUP BY o.aid
) AS o2 ON ouid = u.id
WHERE u.status = 1
ORDER BY t2.transactions DESC
基本上,我需要汇总来自多个表的用户数据(并能够对其进行排序)
查询中没有明显的查询性能反模式。性能几乎取决于带有group by子句的两个子查询的性能。
让我们看一看其中的一些改进。
SELECT t.aid AS tuid,
SUM( IF( t.status = 1, t.amount, 0 ) ) AS transactions
FROM afs_transactions AS t
WHERE t.datetime BETWEEN '2018-01-01 00:00:00' AND '2020-01-01 23:59:59'
GROUP BY t.aid
如果在afs_transactions.datetime
上有索引,则可以。
但是整个子查询都可以重写
SELECT t.aid AS tuid,
SUM( t.amount ) AS transactions
FROM afs_transactions AS t
WHERE t.datetime BETWEEN '2018-01-01 00:00:00' AND '2020-01-01 23:59:59'
AND t.status = 1
GROUP BY t.aid
此查询将利用(status, datetime)
上的复合索引。如果status
值不等于1
的行很多,并且具有复合索引,则重写查询将更快。
专业提示:日期时间值的BETWEEN
通常是一个糟糕的选择,因为59:59。尝试使用<
而不是BETWEEN的<=
作为范围的结尾。
WHERE t.datetime >= '2018-01-01'
AND t.datetime < '2020-01-02' /* notice, it's the day after the range */