2010-09-23 81 views
4

我的数据库在mysql v5.x上运行。我有一个有5列的表T1,列C1是主键。 C1的类型是varchar(20)。它包含了像值约2000行:如何在mysql查询中使用索引效率

fxg 
axt3 
tru56 
and so on.. 

现在我的应用程序的任务是读取输入数据,发现如果输入数据具有类似于表T1列C1发现了一个起步模式。例如:我的输入可能显示为:

trx879478986 
    fxg87698x84 
    784xtr783utr 
    axt3487ghty 
... and so on 

因此,对于上面的输入,我不得不返回“fxg87698x84”和“axt3487ghty”真假他人。我使用的查询是:

select 1 from T1 where (? like concat(C1,'%')); 
note: the ? is replaced by the input value got from the application. 

的问题是我投入是巨大的(约1万条记录在30分钟内被处理)和我的查询速度不够快。有关如何重新编写查询或强制使用索引的任何想法?即使我必须使用不同的对象结构,如果有帮助的话,我也可以做到。所以任何帮助将不胜感激。谢谢。

回答

2

你的问题的设置方式,你几乎按照定义需要检查数据库中的每一行,对照每一个输入,按照你当前的方式进行。在这种情况下,索引并不重要,因为任何一行都可以匹配。

我不确定它会更快,但您可以尝试的一件事是查询数据库,以便在您的输入的每个可能有效的子字符串上进行完全匹配。

例如,如果你知道你的子字符串必须至少长3相匹配,开始第3个字符: trx879478986 => TRX,trx8,trx87,...

创建数组这些可能的匹配,并使用IN()运营商查询他们:

SELECT 1 FROM T1 WHERE c1 IN ($array_of_strings); 

我敢肯定的MySQL可以使用索引来匹配给IN()

+0

我要建议 - 只有我增加了一个“ORDER BY CHAR_LENGTH(C1)”为有利于比赛的“ ATX12345'对'ATX' – symcbean 2010-09-23 12:47:13

+0

+1,我正在输入。这确实使用了索引,并且通过避免使用LIKE来避免如果C1包含'%'或'_'字符会发生什么问题。 – bobince 2010-09-23 12:49:50

+0

Thx为输入。但是我必须做的有效子串的组合是3个字符到20个字符,而额外的处理类型可以抵消我可能获得的性能增益。 – Abdullah 2010-09-23 13:21:50

9

你凑值的列表LD尝试前N个查询,找到第一个候选,然后应用候选人,以实际的模式:

select 1 
    from (select c1 
      from junk 
     where c1 <= 'fxg87698x84' 
     order by c1 desc limit 1) tmp 
where 'fxg87698x84' like concat(c1, '%'); 

前N个查询应该在C1上使用常规指标。

编辑: 解释说,在更详细的在我的博客:http://blog.fatalmind.com/2010/09/29/finding-the-best-match-with-a-top-n-query/

+0

美丽!!这真的有助于减少我的全表扫描。 thx再次。 - Abdullah – Abdullah 2010-09-23 13:16:50

+0

@Abdullah答案是不正确的。比较'fxg'<='fxg87698x84'会返回1.但是比较'exg'<='fxg87698x84'也会返回1,这不能满足实际需求。 – 2017-02-22 03:24:25