【问题标题】:How to improve performance of MySQL query with frequent insert rate?如何以频繁插入率提高 MySQL 查询的性能?
【发布时间】:2010-10-29 12:27:00
【问题描述】:

我大约有。表tb_post 中有 200K 行,每 5 分钟大约有 200K 行。 10 个新插入。

我正在使用以下查询来获取行 -

SELECT tb_post.ID, tb_post.USER_ID, tb_post.TEXT, tb_post.RATING, tb_post.CREATED_AT,
       tb_user.ID, tb_user.NAME 
FROM tb_post, tb_user 
WHERE tb_post.USER_ID=tb_user.ID 
ORDER BY tb_post.RATING DESC 
LIMIT 30

以排序方式获取所有行需要 10 多秒。

以下是 EXPLAIN 查询的报告:

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE tb_user ALL PRIMARY NULL NULL NULL 20950 使用临时;使用文件排序
1 简单 tb_post ref tb_post_FI_1 tb_post_FI_1 4 tb_user.id 4

输入很少:

  • tb_post.RATING 是浮点型
  • tb_post.USER_ID 上有索引

谁能给我一些建议,告诉我应该如何优化这个查询并提高它的读取性能?

PS:我是数据库扩展问题的新手。因此,任何类型的建议都会对该查询有用。

【问题讨论】:

  • 很抱歉给您带来了困惑。我纠正了我的问题。我确实想要索引,并且 USER_ID 已经被索引,但它仍然没有帮助。问题是 - 我是否也应该索引其他列,如果是,哪些列?
  • 也许您应该考虑使用 JOIN 操作并注意您加入表格的顺序 - 首先较小。但这取决于您使用的数据库.. 更多信息stackoverflow.com/questions/173726/…

标签: php mysql performance scalability


【解决方案1】:

您需要一个涵盖 ORDER BY 和 WHERE 子句的 tb_post 索引。

CREATE INDEX idx2 on tb_post (rating,user_id)

=> EXPLAIN SELECT ...ORDER BY tb_post.RATING DESC LIMIT 30 的输出

“id”;“select_type”;“table”;“type”;“possible_keys”;“key”;“key_len”;“ref”;“rows”;“Extra”
"1";"简单";"tb_post";"索引";NULL;"idx2";"10";NULL;"352";""
"1";"SIMPLE";"tb_user";"eq_ref";"PRIMARY";"PRIMARY";"4";"test.tb_post.USER_ID";"1";""
    

【讨论】:

    【解决方案2】:

    您可以尝试索引tb_post.RATING:MySQL 有时可以使用索引来优化ORDER BY 子句:http://dev.mysql.com/doc/refman/5.0/en/order-by-optimization.html

    如果您尝试聚合来自不同表的数据,您还可以检查您想要的连接类型 (http://en.wikipedia.org/wiki/Join_(SQL))。有些比其他更好,这取决于您想要什么。

    【讨论】:

    • “对不起,网址,我不允许发布超链接...” - 这是“可修复”:-)
    • tb_post.RATING 是浮点类型。那么索引在浮点类型列上工作正常吗?此外,当有人对该帖子进行投票时,RATING 确实会经常发生变化。所以每次有人投票时,MySQL 都需要重新建立索引。如果投票率非常频繁,那么每次构建索引都会很昂贵,对吧?我尝试在 RATING 上添加索引,现在第一次需要超过 10 秒,但下一次,如果没有新的投票,则需要 1-2 秒。但是一旦有人投票,又要花费大量时间来获取相同的页面。所以请指教。
    • 如何创建索引,更重要的是如何更新评级?我刚刚检查了一个 200k 行的测试表(id、rating、text、user_id):无论索引包含什么(特别是使用 VolkerK 的方式),创建索引都需要 3 秒。更新单行以更改评级需要几毫秒,因为它应该。您不必在每次更新时都创建索引:相反,您可以运行正常的 UPDATE 查询并让 MySQL 更新其索引。如果您确定您正确地进行了更新(更新,而不是创建索引),请检查罪魁祸首确实是 MySQL,而不是缓存系统或其他什么。
    【解决方案3】:

    如果取消 ORDER BY 会发生什么,这会对性能产生影响吗?如果这有很大的影响,那么可以考虑索引 tb_post.RATING。

    卡尔

    【讨论】:

    • 我无法取消 ORDER BY 子句。我需要根据其受欢迎的评分显示结果。
    • @Aditya - 您是否尝试在 tb_post.rating 上添加索引?
    猜你喜欢
    • 1970-01-01
    • 2012-02-07
    • 2013-03-21
    • 1970-01-01
    • 2013-03-28
    • 1970-01-01
    • 1970-01-01
    • 2011-12-03
    • 2023-04-08
    相关资源
    最近更新 更多