如何查询
SELECT * FROM sometable WHERE somefield LIKE '%value%'
优化?
这里的主要问题是第一个阻止DBMS使用索引的通配符。
编辑:更重要的是,某些字段值是实心字符串(不是一段文字),因此无法进行全文搜索。
答案 0 :(得分:21)
你的琴弦有多长时间?
如果它们相对较短(例如英文单词; avg_len = 5)并且您有备用数据库存储空间,请尝试以下方法:
value
给出:
value
alue
lue
ue
e
LIKE 'alu%'
搜索子字符串(它会在'值'中找到' alu')。通过存储所有后缀,您已经删除了对前导通配符的需求(允许使用索引进行快速查找),但代价是存储空间。
存储费用
在每个单词的基础上,存储单词所需的字符数变为word_len*word_len / 2
,即字长中的二次方。以下是各种字数增加的因素:
(3*3/2) / 3 = 1.5
(5*5/2) / 5 = 2.5
(7*7/2) / 7 = 3.5
(12*12/2) / 12 = 6
存储单词所需的行数从1增加到word_len
。注意这个开销。应将其他列保持在最低限度,以避免存储大量冗余数据。例如,最初找到该单词的页码应该没问题(想想unsigned smallint),但是单词上的大量元数据应该基于每个单词存储在单独的表中,而不是每个后缀。
<强>考虑强>
在我们拆分的地方进行权衡取舍&#39; (或片段)。作为一个现实世界的例子:我们用连字符做什么?我们将形容词five-letter
存储为一个或两个词吗?
权衡如下:
five
和letter
,则搜索five-letter
或fiveletter
将失败。为方便起见,您可能希望删除连字符并存储fiveletter
。现在可以通过搜索five
,letter
和fiveletter
找到该字词。 (如果您也从任何搜索查询中删除连字符,用户仍然可以成功找到five-letter
。)
最后,有一些存储后缀数组的方法不会产生太大的开销,但我还不确定它们是否可以很好地转换为数据库。
答案 1 :(得分:4)
使用Full Text Search。 “初步想法”标题具有相同的示例,并导致工作示例解决方案。
编辑:无法在SQL本身进行调整。使用LOCATE或PATINEX等功能也无济于事。
答案 2 :(得分:4)
考虑到你的问题是通配符,它不会产生很大的不同,但是不使用“SELECT *”会提高查询性能。如果你实际上并没有使用你得到的所有字段,那就是胜利,“SELECT *”会导致两个查询被触发,一个用于查找表的字段,然后查询添加了字段名称的查询。
答案 3 :(得分:4)
两种方式:
(1)使用内存表,因此速度非常快。
(2)制作比foo LIKE '%bar%'
更好的索引和搜索算法。如果不了解您的问题,就无法对此提出任何建议。
正如您所指出的,%bar%模式保证了每次查找的表扫描,这使数据库软件中任何可能的搜索独创性无效。