我在MyISAM数据库中有一个有1760万行的表。
我想在它里面搜索一个文章号,但是结果不能取决于特殊的字符如点,逗号和其他。
我使用这样的查询:
SELECT * FROM `table`
WHERE
replace(replace(replace( replace( `haystack` , ' ', '' ),
'/', '' ), '-', '' ), '.', '' )
LIKE 'needle'这种方法非常-非常慢。table在haystack上有一个索引,但是EXPLAIN显示查询不能使用,这意味着查询必须在3.8秒内扫描1760万行。
查询在一个页面中运行多次(10-15x),因此页面加载非常慢。
我该怎么办?在查询中使用替换是个坏主意吗?
发布于 2013-11-06 09:12:55
在对表中的实际数据进行替换时,MySQL不能使用索引,因为它没有需要与needle比较的替换结果的任何索引数据。
尽管如此,如果您的替换设置是静态的,那么最好是对数据进行去修饰,并添加一个新列,如haystack_search,其中包含所有已应用的替换数据。此列可以在INSERT或UPDATE期间填充。然后,可以有效地使用该列上的索引。
请注意,您可能希望在%查询中使用LIKE,因为它实际上与正常的相等比较相同。现在,如果使用像%needle%这样的搜索项(即带有变量开始),那么MySQL再次不能使用索引并返回到表扫描,因为只有当它看到搜索项的固定开始时才能使用索引,例如needle%。
因此,最终,您可能不得不调优数据库引擎,以便它能够将表保存在内存中。使用MyISAM表(或使用MySQL 5.6或更新后的InnoDB表)的另一种选择是对数据使用全文索引,这再次允许进行相当高效的搜索。
发布于 2013-11-06 09:06:16
您可以尝试在列上使用LENGTH,不确定它是否会产生更好的效果。此外,在使用LIKE时,您应该使用%
SELECT * FROM `table`
WHERE
haystack LIKE 'needle%' AND
LENGTH(haystack) - LENGTH(REPLACE(haystack,'/','')) = 0 AND
LENGTH(haystack) - LENGTH(REPLACE(haystack,'-','')) = 0 AND
LENGTH(haystack) - LENGTH(REPLACE(haystack,'.','')) = 0;如果干草堆完全是针,那么就这样做。
SELECT * FROM `table`
WHERE
haystack='needle';发布于 2013-11-06 09:10:02
将函数应用到列中是“不好的”,因为它将强制对列进行扫描。
也许这是一个更好的方法:
SELECT list
, of
, relevant
, columns
, only
FROM your_table
WHERE haystack LIKE 'two[ /-.]needles'在这个场景中,我们搜索“两个针头”,其中单词之间的空格可以是方括号内的任何字符,即“两针”、“两针”、“两针”或"two.needles“。
https://stackoverflow.com/questions/19807716
复制相似问题