我目前运行一个网站,该网站在列表中跟踪最新的分数和评级。该列表有数千个经常更新的条目,并且该列表应该可以按这些分数和评级列进行排序。
目前获取这些数据的 Mysql 看起来像(大致):
SELECT e.*, SUM(sa.amount) AS score, AVG(ra.rating) AS rating
FROM entries e
LEFT JOIN score_adjustments sa ON sa.entry_id = e.id
HAVING sa.created BETWEEN ... AND ...
LEFT JOIN rating_adjustments ra ON ra.entry_id = e.id
HAVING ra.rating > 0
ORDER BY score
LIMIT 0, 10
表格所在位置(简化):
entries:
id: INT(11) PRIMARY
...other data...
score_adjustments:
id: INT(11), PRIMARY
entry_id: INT(11), INDEX, FOREIGN KEY (entries.id)
created: DATETIME
amount: INT(4)
rating_adjustments:
id: INT(11), PRIMARY
entry_id: INT(11), INDEX, FOREIGN KEY (entries.id)
rating: DOUBLE
大约有300,000score_adjustments
条目数量每天增加约 5,000 个。这rating_adjustments
大约是1/4。
现在,我不是 DBA 专家,但我猜想打电话SUM()
and AVG()
一直都不是一件好事——尤其是当sa
and ra
包含数十万条记录 - 对吗?
我已经对查询进行了缓存,但我希望查询本身能够快速 - 但仍尽可能保持最新。我想知道是否有人可以分享任何解决方案来优化像这样的繁重的联接/聚合查询?如有必要,我愿意进行结构性改变。
EDIT 1
添加了有关查询的更多信息。