与“ =”运算符相比,SQLite“ LIKE”运算符非常慢

时间:2019-12-19 11:42:09

标签: sql performance sqlite database-performance sqlperformance

当我在SQLite中使用LIKE运算符时,它比我使用=时要慢得多。 使用=运算符大约需要14毫秒,但是当我使用LIKE时,大约需要440毫秒。我正在用DB Browser for SQLite进行测试。这是可以快速运行的查询:

SELECT re.ENTRY_ID, 
       GROUP_CONCAT(re.READING_ELEMENT, '§') AS read_element,
       GROUP_CONCAT(re.FURIGANA_BOTTOM, '§') AS furigana_bottom,
       GROUP_CONCAT(re.FURIGANA_TOP, '§') AS furigana_top,
       GROUP_CONCAT(re.NO_KANJI, '§') AS no_kanji,
       GROUP_CONCAT(re.READING_COMMONNESS, '§') AS read_commonness, 
       GROUP_CONCAT(re.READING_RELATION, '§') AS read_rel,
       GROUP_CONCAT(se.SENSE_ID, '§') AS sense_id, 
       GROUP_CONCAT(se.GLOSS, '§') AS gloss, 
       GROUP_CONCAT(se.POS, '§') AS pos, 
       GROUP_CONCAT(se.FIELD, '§') AS field,
       GROUP_CONCAT(se.DIALECT, '§') AS dialect, 
       GROUP_CONCAT(se.INFORMATION, '§') AS info 
FROM Jmdict_Reading_Element AS re LEFT JOIN 
     Jmdict_Sense_Element AS
     se ON re.ENTRY_ID = se.ENTRY_ID
WHERE re.ENTRY_ID IN (SELECT ENTRY_ID FROM Jmdict_Reading_Element WHERE READING_ELEMENT = 'example') OR 
      re.ENTRY_ID IN (SELECT ENTRY_ID FROM Jmdict_Sense_Element WHERE GLOSS = 'example')
 GROUP BY re.ENTRY_ID

当我改变时,速度变慢

WHERE re.ENTRY_ID IN (SELECT ENTRY_ID FROM Jmdict_Reading_Element WHERE READING_ELEMENT = 'example') OR 
re.ENTRY_ID IN (SELECT ENTRY_ID FROM Jmdict_Sense_Element WHERE GLOSS = 'example')

WHERE re.ENTRY_ID IN (SELECT ENTRY_ID FROM Jmdict_Reading_Element WHERE READING_ELEMENT LIKE 'example') OR 
re.ENTRY_ID IN (SELECT ENTRY_ID FROM Jmdict_Sense_Element WHERE GLOSS LIKE 'example')

我需要这样做,以便可以使用通配符,例如

WHERE re.ENTRY_ID IN (SELECT ENTRY_ID FROM Jmdict_Reading_Element WHERE READING_ELEMENT LIKE 'example%') OR 
re.ENTRY_ID IN (SELECT ENTRY_ID FROM Jmdict_Sense_Element WHERE GLOSS LIKE 'example%')

这里是数据库本身的链接: https://www.mediafire.com/file/hyuymc84022gzq7/dictionary.db/file

谢谢

3 个答案:

答案 0 :(得分:3)

尝试在正在使用的列上放置全文索引。

请参阅Full Text Indexing

创建目录

USE {yourDB}  
GO  
CREATE FULLTEXT CATALOG {catalogName}
WITH ACCENT_SENSITIVITY = OFF

创建索引

USE {yourDB}  
GO  
CREATE FULLTEXT INDEX ON {someTable} ({col1}, {col2})
ON catalogName

注意 这更加方便,但是请查看您的排序规则是否区分大小写,例如“ a” =“ A”。通常,排序规则将具有例如ci_utf8(ci =不区分大小写)。我这样做是为了给用户和程序员带来方便。

答案 1 :(得分:0)

我想知道使用HAVING是否会加快查询速度:

SELECT re.ENTRY_ID, 
       GROUP_CONCAT(re.READING_ELEMENT, '§') AS read_element,
       GROUP_CONCAT(re.FURIGANA_BOTTOM, '§') AS furigana_bottom,
       GROUP_CONCAT(re.FURIGANA_TOP, '§') AS furigana_top,
       GROUP_CONCAT(re.NO_KANJI, '§') AS no_kanji,
       GROUP_CONCAT(re.READING_COMMONNESS, '§') AS read_commonness, 
       GROUP_CONCAT(re.READING_RELATION, '§') AS read_rel,
       GROUP_CONCAT(se.SENSE_ID, '§') AS sense_id, 
       GROUP_CONCAT(se.GLOSS, '§') AS gloss, 
       GROUP_CONCAT(se.POS, '§') AS pos, 
       GROUP_CONCAT(se.FIELD, '§') AS field,
       GROUP_CONCAT(se.DIALECT, '§') AS dialect, 
       GROUP_CONCAT(se.INFORMATION, '§') AS info 
FROM Jmdict_Reading_Element re LEFT JOIN 
     Jmdict_Sense_Element se
     ON re.ENTRY_ID = se.ENTRY_ID
GROUP BY re.ENTRY_ID
HAVING SUM(CASE WHEN re.READING_ELEMENT = 'example' THEN 1 ELSE 0 END) > 0 OR
       SUM(CASE WHEN se.GLOSS = 'example' THEN 1 ELSE 0 END) > 0);

答案 2 :(得分:0)

FTS?

在Win 10上将数据库浏览器用于sqlite。

  • “快速”查询在84毫秒内返回25行
  • “慢速”查询(使用LIKE "example%")在1025毫秒内返回33行

像这样创建fts4表:

create virtual table jre_fts using FTS4(entry_id,reading_element);
insert into jre_fts select entry_id, reading_element from Jmdict_Reading_Element;
create virtual table jse_fts using FTS4(entry_id,gloss);
insert into jse_fts select entry_id, gloss from Jmdict_Sense_Element;

花费了7390毫秒,数据库从70,296KB增长到110,708KB。

像这样修改WHERE:

 WHERE re.ENTRY_ID IN (SELECT ENTRY_ID FROM jre_fts WHERE READING_ELEMENT MATCH '^example') OR 
re.ENTRY_ID IN (SELECT ENTRY_ID FROM jse_fts WHERE GLOSS MATCH '^example')

查询在60毫秒内返回了33行。

我无法测试或分析FTS在reading_element列上的工作方式,但是也许这种方法显示出了希望。