[英]How to speed up a SQL query with HAVING
我有以下查询:
SELECT u.amount_limit
, SUM( t.amount ) AS approved
FROM table_transactions AS t
, table_users AS u
WHERE t.uid = u.id
AND t.status = 1
AND u.status = 1
AND u.amount_limit != 0
GROUP
BY t.uid
HAVING approved >= u.amount_limit
在一个有 1000 个用户和 1000000 个事务的数据库中,大约需要 7-8 秒。
有没有办法优化/加速这个 sql 查询?
PS:我需要达到限制的用户数量和数量,我目前使用 PHP mysql_num_rows() 获得。
更新:这是表格结构
CREATE TABLE IF NOT EXISTS table_users (
`id` varchar(32) COLLATE utf8_bin NOT NULL,
`amount_limit` float DEFAULT NULL,
....
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
CREATE TABLE IF NOT EXISTS `table_transactions` (
`id` varchar(32) COLLATE utf8_bin NOT NULL,
`uid` varchar(32) COLLATE utf8_bin NOT NULL,
`status` tinyint(1) NOT NULL DEFAULT '0',
`amount` float NOT NULL DEFAULT '0',
....
PRIMARY KEY (`id`),
KEY `uid` (`uid`),
KEY `status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
计划一:
SELECT u.amount_limit, x.approved
FROM ( SELECT uid, SUM(amount) AS approved
FROM transactions
WHERE status = 1
) AS x
JOIN users AS u ON u.id = x.uid
WHERE u.amount_limit != 0
AND u.status = 1
AND x.approved >= u.amount_limit
计划 B,如果很多用户的 limit=0 或 status:= 1,可能会更快:
SELECT u.amount_limit,
( SELECT SUM(amount) AS approved
FROM transactions
WHERE status = 1
AND uid = u.id
) AS approved
FROM users AS u
WHERE u.amount_limit != 0
AND u.status = 1
AND approved >= u.amount_limit
两者都将从这些综合指数中受益:
users: INDEX(status, amount_limit, id)
transactions: INDEX(status, uid, amount)
如果id
和uid
是像 UUID 或哈希这样的“随机”数字,则访问将是随机且缓慢的。 我提供的索引将“覆盖”,从而显着补偿问题。
建议您重新考虑 id 的设计。
对于货币值,应避免使用FLOAT
和DOUBLE
。 请参阅DECIMAL(m,n)
。
单独索引“标志”(例如status
)很少有用。 将它作为复合索引的一部分可能会很有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.