我在 MyISAM 数据库中有一个包含 1760 万行的表。
我想在其中搜索一个文章编号,但结果不能依赖于点、逗号等特殊字符。
我正在使用这样的查询:
SELECT * FROM `table`
WHERE
replace(replace(replace( replace( `haystack` , ' ', '' ),
'/', '' ), '-', '' ), '.', '' )
LIKE 'needle'
这种方法非常非常慢。 table
在 haystack
上有一个索引,但是 EXPLAIN
显示查询不能使用它,这意味着查询必须在 3.8 秒内扫描 1760 万行。
查询在一个页面中运行多次 (10-15x),因此页面加载速度极慢。
我该怎么办?在查询中使用替换是个坏主意吗?
最佳答案
当您对表中的实际数据进行替换时,MySQL 无法使用索引,因为它没有替换结果的任何索引数据需要与 指针进行比较
。
也就是说,如果您的替换设置是静态的,那么对数据进行非规范化并添加一个新列(如 haystack_search
)可能是个好主意,其中包含应用了所有替换的数据。此列可以在 INSERT
或 UPDATE
期间填充。然后可以有效地使用此列上的索引。
请注意,您可能希望在 LIKE
查询中使用 %
,否则它实际上与普通的相等比较相同。现在,如果您使用像 %needle%
这样的搜索项(即带有变量 start),MySQL 将再次无法使用索引并回退到表扫描,因为它只能在以下情况下使用索引它看到搜索词的固定开头,即类似 needle%
的内容。
所以最后,您可能最终不得不调整您的数据库引擎,以便它可以将表保存在内存中。 MyISAM 表(或 MySQL 5.6 及更高版本以及 InnoDB 表)的另一种替代方法是使用 fulltext索引您的数据,这再次允许相当有效的搜索。
关于mysql - 大 MySQL 表,REPLACE -> 非常慢的查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19807716/