我正在使用 MySQL (MyISAM) 5.0.41 并且我有这个查询:
SELECT `x`.`items`.id, `x`.`items`.name, COUNT(*) AS count
FROM `x`.`items` INNER JOIN `x`.`user_items`
ON `x`.`items`.id = `x`.`user_items`.item_id
GROUP BY name HAVING count > 2 ORDER BY count DESC
我有大约 36,000 个用户、175,000 个 user_items 和 60,000 个不断添加的项目。所以这个查询有点慢......
是否更好:
- 在
items
中有一个count
字段并定期更新(比如每次用户添加一个项目时) - 或像这样(慢慢地)运行查询..
或者是否有任何 SQL 可以为我填充计数字段?
谢谢
最佳答案
您可以使用中间解决方案:
将
ts DATETIME
列添加到user_items
表,该列将描述用户添加项目的时间在
users
表中添加一个ts DATETIME
列来描述实际情况,只要cnt
,缓存计数列使用新的计数和时间戳定期更新
users
表:INSERT INTO users (id, ts, cnt) SELECT * FROM ( SELECT user_id, NOW() AS nts, COUNT(*) AS ncnt FROM user_items ui WHERE ui.timestamp <= NOW() ) ON DUPLICATE KEY UPDATE ts = nnow, cnt = ncnt
删除
user_items
条目时使用户的时间戳无效发出此查询以计算项目数:
SELECT u.id, u.cnt + ( SELECT COUNT(*) FROM user_items ui WHERE ui.ts > u.ts AND ui.user_id = u.id ) FROM users
这样,user_items
表中只会计算新添加的项目,速度要快得多,而且您不会因为过于频繁地更新记录而遇到并发问题。
关于SQL 计算多对多值还是每次添加新行时都计算?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2148005/