16

查询如何

SELECT * FROM sometable WHERE somefield LIKE '%value%'

被优化?

这里的主要问题是第一个阻止 DBMS 使用索引的通配符。

编辑:更重要的是,somefield 值是实心字符串(不是一段文本),因此无法执行全文搜索。

4

4 回答 4

21

你的琴弦有多长?

如果它们相对较短(例如英语单词;avg_len=5)并且您有可用的数据库存储空间,请尝试以下方法:

  • 对于要存储在表中的每个单词,取该单词的所有可能后缀。换句话说,你一直在剥离第一个字符,直到什么都没有。例如,这个词value给出:
    • value
    • alue
    • lue
    • ue
    • e
  • 将这些后缀中的每一个都存储在数据库中。
  • 您现在可以使用搜索子字符串LIKE 'alu%'(它会发现 'alu' 作为 'value' 的一部分)。

通过存储所有后缀,您无需使用前导通配符(允许使用索引进行快速查找),但会占用存储空间。

存储成本

存储一个单词所需的字符数变为word_len*word_len / 2,即单词长度的二次方,以每个单词为基础。以下是各种字长的增加因素:

  • 三字词:(3*3/2) / 3 = 1.5
  • 5字词:(5*5/2) / 5 = 2.5
  • 7个字母的单词:(7*7/2) / 7 = 3.5
  • 12个字母的单词:(12*12/2) / 12 = 6

存储一个单词所需的行数从 1 增加到word_len. 请注意此开销。额外的列应保持在最低限度,以避免存储大量冗余数据。例如,最初找到该单词的页码应该没问题(想想 unsigned smallint),但是该单词的大量元数据应该按每个单词而不是每个后缀存储在单独的表中。

注意事项

There is a trade-off in where we split 'words' (or fragments). As a real-world example: what do we do with hyphens? Do we store the adjective five-letter as one word or two?

The trade-off is as follows:

  • Anything that is broken up cannot be found as a single element. If we store five and letter separately, searching for five-letter or fiveletter will fail.
  • Anything that is not broken up will take more storage space. Remember, the storage requirement increases quadratically in the word length.

For convenience, you might want to remove the hyphen and store fiveletter. The word can now be found by searching five, letter, and fiveletter. (If you strip hyphens from any search query as well, users can still successfully find five-letter.)

Finally, there are ways of storing suffix arrays that do not incur much overhead, but I am not yet sure if they translate well to databases.

于 2014-03-20T11:16:43.600 回答
5

两种方式:

(1) 使用内存表,所以它运行得非常快。

(2) 设计出比 . 更好的索引和搜索算法foo LIKE '%bar%'。在不了解您的问题的情况下,不可能就此提出任何建议。

正如您所指出的,%bar% 模式保证每次查找都进行表扫描,这使数据库软件中任何可能的搜索独创性无效。

于 2010-01-18T01:39:12.843 回答
4

使用全文搜索。“初始想法”标题具有相同的示例,并导致工作示例解决方案。

和 MySQL 文档

编辑:它不能在 SQL 本身中调整。使用 LOCATE 或 PAINEX 之类的函数也无济于事。

于 2010-01-17T18:04:29.567 回答
4

考虑到通配符的问题,它不会有很大的不同,但不使用“SELECT *”会提高查询性能。如果您实际上并没有使用返回的所有字段,那是一个胜利,“SELECT *”会触发两个查询,一个是查找表的字段,然后是添加了字段名称的查询。

于 2010-01-17T18:19:45.660 回答