我的服务器上有一个MySQL数据库,其中一个表有一个主索引,所有其他列都有全文索引。通常我执行SELECT语句,如:
SELECT * FROM myTable WHERE MATCH(myInfo) AGAINST ('stuff') ORDER BY id LIMIT 30
这样做很好,但速度很慢 - ORDER BY id
子句大大减慢了速度,特别是当经常发生很多命中时。例如,如果没有子句搜索,则需要约0.001秒,并使用0.6秒(但产生理想结果)。
是否可以预先分配我的表格以便我不需要ORDER BY
运算符?该表是静态的 - 只能读取数据。毕竟,只有在返回(顶部)30时才排序5000次点击似乎是一种浪费,这可以在事先轻松决定。
如果没有,我该怎么办?
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
答案 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是任意的,试图在查询时间和漏报之间找到一个很好的平衡。
注意:我不能保证你在所有情况下都会得到相同的结果,但我真的不知道如何做到这一点。