使用 fts + 复合索引优化查询

Posted

技术标签:

【中文标题】使用 fts + 复合索引优化查询【英文标题】:Optinimizing query with fts + composite index 【发布时间】:2020-01-17 23:24:14 【问题描述】:

我有以下疑问:

SELECT * 
FROM table 
WHERE 
    structural_type=1 
    AND parent_id='167F2-F' 
    AND points_to_id=''
    # AND match(search) against ('donotmatch124213123123')

搜索运行大约需要 10 毫秒,在复合索引(structural_type、parent_id、points_to_id)上运行。但是,当我添加 fts 索引时,无论匹配条件中包含什么,查询都会膨胀到大约 1 秒。基本上,每当我应用 fts 搜索时,它似乎都会“跳过索引”。

优化此查询的最佳方法是什么?

更新:一些解释:

EXPLAIN SELECT... # without fts

id  select_type table   partitions  type    possible_keys   key key_len ref rows    filtered    Extra
1   SIMPLE  table   NULL    ref structural_type structural_type 209 const,const,const   2   100.00  NULL

使用 fts(同时添加“强制索引”):

explain SELECT ... force INDEX (structural_type) AND match...

id  select_type table   partitions  type    possible_keys   key key_len ref rows    filtered    Extra
1   SIMPLE  table   NULL    fulltext    structural_type,search  search  0   const   1   5.00    Using where; Ft_hints: sorted

我能想到的唯一一件令人难以置信的骇人听闻的事情就是在 fts 中添加一个附加术语,以便它在“内部”执行过滤器。例如:

fts_term = fts_term += " StructuralType1ParentID167F2FPointsToID"

【问题讨论】:

查询的注释版本返回多少个结果? @BenoitEsnard 2 个结果。桌子大小为 2.4m。 @David542:你在桌子上运行OPTIMIZE TABLE 查询了吗? 不同模式对搜索表达式使用不同的语法,表达式的结果返回不同的值。我宁愿参考文档而不是全部输入:dev.mysql.com/doc/refman/8.0/en/fulltext-search.html 我来自 PostgreSQL 背景,所以我不确定 MySQL 内部是如何在这里真正工作的。在 PostgreSQL 中,您需要对表进行一些维护(数据统计,在您的情况下),所以我想这里是一样的。 【参考方案1】:

MySQL 优化器只能为您的 WHERE 子句使用一个索引,因此它必须在复合索引和 FULLTEXT 索引之间进行选择。

由于它不能同时运行两个查询来确定哪个更快,它会估计不同执行计划的速度。

为此,MySQL 使用它保存的有关每个表的一些内部统计信息。但是,如果这些统计数据没有更新并且表格中的数据发生变化,这些统计数据可能与实际情况大不相同。

运行OPTIMIZE TABLE table 查询允许 MySQL 刷新其表统计信息,因此它将能够执行更好的估计并选择更好的索引。

【讨论】:

【参考方案2】:

尝试在没有全文逻辑的情况下表达这一点,使用like

SELECT * 
FROM table 
WHERE structural_type = 1 AND
      parent_id  ='167F2-F' AND
      points_to_id = '' AND
      search not like '%donotmatch124213123123%';

索引仍应用于前三列。 LIKE 可能会很慢,但如果没有多少行与前三个匹配,这可能不如使用全文索引那么糟糕。

【讨论】:

这是一个可能的解决方案,尽管在我的问题中我没有包含多个术语,而在其他查询中我可能需要在 fts 索引中使用多个术语。 @David542 。 . .如果这有更好的性能,您可以尝试使用正则表达式。

以上是关于使用 fts + 复合索引优化查询的主要内容,如果未能解决你的问题,请参考以下文章

使用复合索引优化MySQL查询

复合索引顺序 MySQL 查询

注意使用 BTREE 复合索引各字段的 ASC/DESC 以优化 order by 查询效率

#yyds干货盘点#MySQL索引优化系列:索引全用及最左法则

索引优化

有关于mysql复合索引