使用Like / match的慢mysql查询

时间:2012-06-18 22:33:55

标签: mysql sql-like match-against

我需要搜索比实际更大的Dialcode。例如,最接近33的将是331或332(如果331不存在)......所以它必须是33xxxx,34是无效的。

这两个查询有效但速度太慢(250毫秒/行):

SELECT Dialcode
FROM table
WHERE (Dialcode LIKE '$var%' AND Dialcode > '$var' AND Price IS NOT NULL)
ORDER BY Dialcode ASC LIMIT 1

SELECT Dialcode
FROM table
WHERE (MATCH(Dialcode) AGAINST ('$var*' IN BOOLEAN MODE) AND Dialcode > '$var'
      AND Price IS NOT NULL)
ORDER BY Dialcode ASC LIMIT 1

我的拨号码是一个主要的大键(15)。

我这样做,它真的很快(> 1毫秒/行),但这不是我需要的:

SELECT Dialcode
FROM table
WHERE (Dialcode >= '$var' AND Price IS NOT NULL)
ORDER BY Dialcode ASC LIMIT 1

所以我猜我的问题就是喜欢/匹配。

任何想法都会受到赞赏。

更新解决方案:

解决方案改编自raina77ow建议:

SELECT Dialcode FROM table WHERE (( (Dialcode BETWEEN $var * 1 AND ’9’ )
   OR (Dialcode BETWEEN $var * 10 AND $var.’99’ )   
   OR (Dialcode BETWEEN $var * 100 AND $var.’999’ )
OR (Dialcode BETWEEN $var * 1000 AND $var.’9999’ )
…
) AND Price IS NOT NULL) ORDER BY Dialcode ASC LIMIT 1

谢谢你们!

2 个答案:

答案 0 :(得分:2)

我看到这里的主要问题是索引是建立在Dialcode的数值上 - 而不是字符串的数值。因此,两个查询都根本不使用索引。

你可以尝试建立一个数字函数,问题是这个函数在评估的左边部分会有Dialcode - 所以再也不会使用索引。

也许这种方法可能更有用。

SELECT Dialcode 
FROM table 
WHERE ( (Dialcode BETWEEN %value% * 10 AND (%value%*10 + 9) 
   OR (Dialcode BETWEEN %value% * 100 AND (%value%*100 + 99) 
   OR (Dialcode BETWEEN %value% * 1000 AND (%value%*1000 + 999)
   ...
) AND Price IS NOT NULL
ORDER BY Dialcode LIMIT 1;

这很丑陋(我甚至在前两次写错了 - alfasin应该得到纠正我的功劳),是的,但它应该达到指数。另一种方法是使用UNION(而不是OR),但我认为两个查询都将以相同的方式执行(但它没有经过验证)。

答案 1 :(得分:1)

尝试使用正则表达式,例如:

SELECT Dialcode
FROM table
WHERE Dialcode REGEXP '^[$var]'
ORDER BY Dialcode ASC LIMIT 1

我现在无法测试它,但我相信它应该可行。