我在MyISAM数据库中有一个包含1760万行的表。
我想在其中搜索一个文章编号,但结果不能依赖于特殊字符,如点,逗号和其他字符。
我正在使用这样的查询:
SELECT * FROM `table`
WHERE
replace(replace(replace( replace( `haystack` , ' ', '' ),
'/', '' ), '-', '' ), '.', '' )
LIKE 'needle'
这种方法非常慢。 table
的索引位于haystack
,但EXPLAIN
显示查询无法使用,这意味着查询必须扫描1760万行 - 在3.8秒内。
查询在页面中多次运行(10-15x),因此页面加载速度极慢。
我该怎么办?在查询中使用replace是不是一个坏主意?
答案 0 :(得分:0)
您可以尝试在列上使用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';
答案 1 :(得分:0)
将函数应用于列是“不好的”,因为它会强制扫描列。
也许这是一种更好的方法:
SELECT list
, of
, relevant
, columns
, only
FROM your_table
WHERE haystack LIKE 'two[ /-.]needles'
在这种情况下,我们正在寻找“两针”,其中单词之间的空格可以是方括号内的任何字符,即“两针”,“两针/针”,“双针”或“ two.needles”。
答案 2 :(得分:0)
当您对表中的实际数据进行替换时,MySQL无法使用索引,因为它没有任何需要与{{1}进行比较的替换结果的索引数据}。
也就是说,如果您的替换设置是静态的,那么最好对数据进行非规范化并添加一个新的列,如needle
,其中包含应用了所有替换的数据。可以在haystack_search
或INSERT
期间填写此列。然后可以有效地使用该列的索引。
请注意,您可能希望在UPDATE
查询中使用%
,因为它实际上与普通的相等比较相同。现在,如果您使用像LIKE
这样的搜索项(带有变量start),MySQL再次无法使用索引并回退到表扫描,因为只有在看到固定的启动时它才能使用索引搜索字词,例如%needle%
。
因此,最后,您可能最终必须调整数据库引擎,以便它可以将表保存在内存中。使用MyISAM表(或使用MySQL 5.6及更高版本的InnoDB表)的另一种方法是在数据上使用fulltext索引,这又可以进行相当有效的搜索。