[英]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.