MySQL和预先分配表

时间:2011-08-30 09:42:27

标签: mysql optimization indexing

我的服务器上有一个MySQL数据库,其中一个表有一个主索引,所有其他列都有全文索引。通常我执行SELECT语句,如:

SELECT * FROM myTable WHERE MATCH(myInfo) AGAINST ('stuff') ORDER BY id LIMIT 30

这样做很好,但速度很慢 - ORDER BY id子句大大减慢了速度,特别是当经常发生很多命中时。例如,如果没有子句搜索,则需要约0.001秒,并使用0.6秒(但产生理想结果)。

  1. 是否可以预先分配我的表格以便我不需要ORDER BY运算符?该表是静态的 - 只能读取数据。毕竟,只有在返回(顶部)30时才排序5000次点击似乎是一种浪费,这可以在事先轻松决定。

  2. 如果没有,我该怎么办?

  3. PS - MATCH似乎混杂起来,而LIKE虽然速度慢但不需要ORDER BY

    %% 编辑#1,在phpMyAdmin上输出EXPLAIN SELECT

    id  select_type table   type    possible_keys   key key_len ref rows    Extra
    
    1   SIMPLE  myTable fulltext    full_index  full_index  0       1   Using where
    

    编辑#2,更好的EXPLAIN

    表示对结果进行排序所花费的时间。

    状态时间

    从0.000016开始

    检查查询缓存以查询0.000048

    开盘表0.000012

    系统锁定0.000007

    表锁0.000024

    init 0.000026

    优化0.000010

    statistics 0.000017

    准备0.000012

    FULLTEXT初始化0.000199

    执行0.000004

    排序结果0.001663

    发送数据0.000304

    结束0.000005

    查询结束0.000004

    释放物品0.000025

    将结果存储在查询缓存0.000007

    记录慢查询0.000003

    清理0.000005

2 个答案:

答案 0 :(得分:1)

  

1 - 可以预先分配我的桌子吗?

不,这张桌子已经被PK预先分类了 全文索引强制按照该索引指定的顺序访问行 因此,他们需要在之后进行重新排序。

  

2-我该怎么办?

如果您不介意获得略有不同的结果,可以将查询更改为

  SELECT * FROM 
    (
    SELECT * FROM myTable WHERE MATCH(myInfo) AGAINST ('stuff') LIMIT 30
    ) as s ORDER BY id 

要获得下一个30结果,请limit 30,30等。

您还可以通过不选择所有行来加速查询,但只选择您需要的行。这将限制MySQL必须保留在内存中的数据量,从而限制在排序时必须移动的数据量。

SELECT id, myinfo FROM mytable ....

答案 1 :(得分:1)

试试这个:

SELECT * FROM myTable WHERE MATCH(myInfo) AGAINST ('stuff') > 0.25 ORDER BY id LIMIT 30

MATCH(...) AGAINST(...)返回[0,1]范围内的匹配分数(也称为“相关性”)。您可以通过筛选低相关性行(上面的查询中的> 0.25)来修剪中间结果;如果您未在WHERE子句中指定此项,则与指定> 0相同)。 0.25是任意的,试图在查询时间和漏报之间找到一个很好的平衡。

注意:我不能保证你在所有情况下都会得到相同的结果,但我真的不知道如何做到这一点。