【发布时间】:2016-08-10 11:44:31
【问题描述】:
我在 MySQL 中有两个表。一个带有accounts(4000 万条记录),一个带有transactions(3 亿条记录)。每天增加大约 20 万笔交易。它们具有 1:n 的关系:
+-----------------+
| Accounts |
+----+------------+
| ID | account_no |
+----+------------+
和
+--------------------------------+
| Transactions |
+----+------------+--------+-...-+
| ID | account_no | amount | ... |
+----+------------+--------+-...-+
我需要编写一个 SQL 查询来创建accounts 按交易量排序的列表。于是想到了这样的事情:
SELECT a.account_no , COUNT(a.account_no) tx_count FROM accounts a
INNER JOIN transactions tx ON a.account_no = tx.account_no
GROUP BY tx.account_no ORDER BY tx_count DESC LIMIT 1000;
我的问题:鉴于我必须处理数以千万计的记录,实现这一目标的最有效的方法是什么?
[注意:字段account_no当然是有索引的]
【问题讨论】:
-
使用 limit 而不是 order by 背后的想法是什么?
-
最好在
Accounts表中添加transaction_amount之类的新字段,用交易的实际数据更新他,之后你就不需要硬查询了。当然,如果您有新交易,您需要更新此字段。 -
@e4c5 自从我开始处理大量数据以来,使用
LIMIT成为一种习惯;) - 我编辑了问题,添加了我完全忘记的ORDER BY。 -
处理此问题的最有效方法是不计算记录。你如何做到这一点?通过实现计数。每次插入
Transactions时,更新Accounts中的计数(假设您创建了trx_count int unsigned字段)。当您从Transactions中删除时,请减少Accounts中的计数。这样一来,MySQL 在执行 I/O 时确实可以工作,这比遍历整个数据集并计算行数要高效得多。 -
@waki 每天添加大约 20 万笔交易 - 我编辑了问题以澄清这一点。