【问题标题】:Query Optimization, What more can I do?查询优化,我还能做什么?
【发布时间】:2017-02-15 11:10:56
【问题描述】:
Table type: MyISAM
Rows: 120k
Data Length: 30MB
Index Length: 40MB

my.ini,MySQL 5.6.2 Windows

read_rnd_buffer_size = 512K
myisam_sort_buffer_size = 16M

Windows Server 2012,12GB RAM,SSD 400MB/s

1 慢查询:

SELECT article_id, title, author, content, pdate, MATCH(author, title, content) 
AGAINST('Search Keyword') AS score FROM articles ORDER BY score DESC LIMIT 10;

执行此查询需要 352 毫秒使用索引。 profiling 后,显示大部分时间都花在了创建排序索引上。 (完整详情:http://pastebin.com/raw/jT58DCN5

2 更快的查询:

SELECT article_id, title, author, content, pdate, MATCH(author, title, content) 
AGAINST('Search Keyword') AS score FROM articles LIMIT 10;

执行此查询需要 23ms 并进行全表扫描,我不喜欢全表扫描。

问题/疑问是,查询 #1 是我需要使用的,因为排序非常重要。

我能做些什么来加快查询/重写它并获得相同的结果(如 #1)?

感谢任何意见和帮助。

【问题讨论】:

    标签: mysql performance query-optimization


    【解决方案1】:

    也许您只是期望过高? 350ms 做一个

    • MATCH(author, title, content) AGAINST('Search Keyword')
    • 订购人

    对我来说,120k 唱片听起来并不太寒酸;特别是如果content 是“大”...

    请记住,要使您的“慢查询”起作用,系统必须读取每一行,计算分数,然后最后对所有分数进行排序,找出最低的 10 个值并然后为其返回所有相关的行信息。如果您省略了 ORDER BY,那么它只会选择 前 10 行,并且只需要计算这 10 行的 score

    也就是说,我认为EXPLAIN 有点误导,因为它似乎将所有事情都归咎于 SORT,而很可能是 MATCH 占用了大部分时间。我猜MATCH() 运算符是以“惰性”方式执行的,因此仅在要求数据时运行,在这种情况下是在排序发生时。

    要解决这个问题,只需添加一个新列score 并将查询分成两部分。

    • UPDATE articles SET score = MATCH() 等... => 我猜大约需要 300 毫秒
    • SELECT article_id, title, author, content, pdate, score FROM articles ORDER BY score DESC LIMIT 10; => 我猜大概需要 50 毫秒

    当然,这不是可行的解决方案,但如果我是对的,它会告诉您您的问题不在于 SORT,而是在于全文搜索......

    PS:您忘记提及表上的索引是什么,知道也可能有用。 cfhttps://dev.mysql.com/doc/refman/5.7/en/innodb-fulltext-index.html

    【讨论】:

    • 嗯,内容不大,varchar 255是content字段的最大长度,也就是最大的那个。我有关于作者、标题、内容的所有类型 varchar 的索引,并且符合 FULL TEXT SEARCH 要求。我并不是说我对现在的情况不满意,但该网站正在发展,我只是想确保在投资其他任何东西之前,我已经用这些资源做了可能做的事情。我确实有一些其他选项可能是更有效的优化选项,而不是那个查询。非常感谢任何其他可以提供帮助的意见。
    【解决方案2】:

    试试这些变体:

    AGAINST('word')
    AGAINST('+word')
    AGAINST('+word' IN BOOLEAN MODE)
    

    试试

    SELECT ... MATCH ...,
        FROM tbl
        WHERE  MATCH ...  -- repeat the test here
        ...
    

    测试是消除根本不匹配的行,从而大大减少要排序的行数。 (同样,取决于+BOOLEAN。)

    (我通常使用所有三个:+BOOLEANWHERE MATCH。)

    key_buffer_size = 2G 也可能有帮助。

    您应该考虑迁移到 InnoDB,因为 FT 更快。

    【讨论】:

      猜你喜欢
      • 2011-02-12
      • 1970-01-01
      • 1970-01-01
      • 2012-03-20
      • 1970-01-01
      • 2010-10-03
      • 2014-04-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多