2012-06-18 132 views
1

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

这2个查询工作,但速度太慢(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 

我Dialcode是主键BIGINT(15)。

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

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

所以我想我的问题是,LIKE /对阵。

任何想法,将不胜感激。

Update解决方案:

解决方案改编自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 

谢谢你们!

+0

Hm'LIKE'需要强制转换为字符串/字符,这可能需要一段时间。您可以在表的副本上测试该理论:将列转换为字符,并查看其执行方式。 – Wrikken

+0

是的,我宁愿将列投射到一个字符,然后建立另一个索引;那么简单的LIKE CONCAT(值+'%')将会创造奇迹,我想它应该达到索引。 – raina77ow

回答

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

你可能的意思是:** AND%value%* 10 + 9 **而不是** AND%value%* 11 - 1 **等我喜欢你的解决方案(+1) – alfasin

+0

谢谢,你的数学福好于矿。 ) – raina77ow

+0

是的!那就是要走的路!我修改了一下,因为在这种情况下,34会匹配,并且它应该严格按照33 ...开始(例如) – remyremy

1

尝试使用正则表达式,是这样的:

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

我现在不能测试,但我认为它应该工作。

+0

并且LIKE不是使用正则表达式吗? – raina77ow

+0

@ raina77ow你可能会问是否* regex *没有使用* LIKE *这是一个很好的问题,我想这取决于实现。当比较数字,我希望答案是“不”,但老实说,我不知道。容易测试,并找出查询的运行时间,虽然;) – alfasin

+1

我测试,它是更快,但没有像BEETWEEN选项。 – remyremy