我的数据库在mysql v5.x上运行。我有一个表格T1有5列,C1列是主键。 C1的类型为varchar(20)。它包含大约2000行,其值如:
fxg
axt3
tru56
and so on..
现在我的应用程序的工作是读取输入数据并查找输入数据是否具有类似于表T1中列C1中的起始模式。例如:我的输入可能显示为:
trx879478986
fxg87698x84
784xtr783utr
axt3487ghty
... and so on
因此,对于上述输入,我必须为'fxg87698x84'和'axt3487ghty'返回true,对其他输入则返回false。我使用的查询是:
select 1 from T1 where (? like concat(C1,'%'));
note: the ? is replaced by the input value got from the application.
问题是我的输入很大(在30分钟内处理大约100万条记录),我的查询速度不够快。有关如何重写查询或强制使用索引的任何想法?即使我必须使用不同的对象结构,我也能做到,如果这有帮助的话。所以任何帮助将不胜感激。 THX。
答案 0 :(得分:9)
您可以尝试使用Top-N查询来查找第一个候选项,然后将该候选项仅应用于实际模式:
select 1
from (select c1
from junk
where c1 <= 'fxg87698x84'
order by c1 desc limit 1) tmp
where 'fxg87698x84' like concat(c1, '%');
top-n查询应该在c1上使用常规索引。
修改强>: 在我的博客中详细解释:http://blog.fatalmind.com/2010/09/29/finding-the-best-match-with-a-top-n-query/
答案 1 :(得分:2)
您的问题设置方式,您几乎按照定义需要检查数据库中的每一行,而不是按照您当前的方式对每个输入进行检查。在这种情况下,索引并不重要,因为任何行都可以匹配。
我不确定它会更快,但您可以尝试的一件事是查询数据库以确保输入的每个可能有效的子字符串完全匹配。
例如,如果您知道您的子字符串必须至少长度为3才能匹配,请从前3个字符开始: trx879478986 =&gt; trx,trx8,trx87,...
构建这些可能匹配的数组,并使用IN()
运算符查询它们:
SELECT 1 FROM T1 WHERE c1 IN ($array_of_strings);
我很确定mysql可以使用索引来匹配给IN()
的值列表