MySQL:复合索引全文+ btree?

时间:2018-01-17 08:39:53

标签: mysql postgresql indexing full-text-search

我想要一个查询在一个字段上进行全文搜索,然后在另一个字段上进行排序(想象一下搜索一些文本文档并按发布日期排序)。该表有大约17M行,它们在日期中或多或少均匀分布。这将在webapp请求/响应周期中使用,因此查询必须在最多200ms内完成。

示意性地:

SELECT * FROM table WHERE MATCH(text) AGAINST('query') ORDER BY date=my_date DESC LIMIT 10;

一种可能性是在文本字段上使用全文索引,在发布日期使用btree:

ALTER TABLE table ADD FULLTEXT index_name(text);
CREATE INDEX index_name ON table (date);

在我的情况下,这不是很好。会发生什么是MySQL评估两个执行路径。一种是使用全文索引来查找相关行,一旦选中它们,使用FILESORT对这些行进行排序。第二种是使用BTREE索引对整个表进行排序,然后使用FULL TABLE SCAN查找匹配项。他们都很糟糕。在我的情况下,MySQL选择前者。问题是,第一步可以选择一些30k的结果然后必须排序,这意味着整个查询可能需要10秒的订单。

所以我在想:FULLTEXT + BTREE的复合索引是否存在?如果您知道FULLTEXT索引的工作原理,它首先将您要编制索引的列标记化,然后为该标记构建索引。对于我来说,想象一个复合索引似乎是合理的,这样第二个索引在每个令牌的日期中都是BTREE。这是否存在于MySQL中,如果是,那么语法是什么?

奖金问题:如果MySQL中不存在,那么PostgreSQL会在这种情况下表现更好吗?

1 个答案:

答案 0 :(得分:1)

使用IN BOOLEAN MODE

日期索引无效。无法合并这两个索引。

请注意,如果用户搜索出现在30K行中的内容,则查询速度会很慢。周围没有直接的方法。

我怀疑桌子上有TEXT列?如果是这样,那就有希望了。我们不是盲目地SELECT *,而是首先找到ID并应用LIMIT然后执行*

SELECT a.* 
    FROM tbl AS a
    JOIN ( SELECT date, id
             FROM tbl
             WHERE MATCH(...) AGAINST (...)
             ORDER BY date DESC
             LIMIT 10 ) AS x
        USING(date, id)
    ORDER BY date DESC;

一起
PRIMARY KEY(date, id),
INDEX(id),
FULLTEXT(...)

这种表述和索引应该像这样工作:

  1. 使用FULLTEXT查找30K行,然后发送PK。
  2. 使用PK,按date排序30K行。
  3. 选择最后10个,提供date, id
  4. 使用PK重新回到桌面10次。
  5. 再次排序。 (是的,这是必要的。)
  6. 更多(回应过多评论):

    我重新制定的目标是避免获取 30K 行的所有列。相反,它只提取PRIMARY KEY,然后将其降至10,然后只提取10行*。铲掉的东西少得多。

    关于InnoDB表上的COUNT

    • INDEX(col)使索引扫描适用于SELECT COUNT(*)SELECT COUNT(col)而不使用WHERE
    • 没有INDEX(col), SELECT COUNT(*)will use the "smallest" index; but SELECT COUNT(col)`需要扫描。
    • 表扫描通常比索引扫描慢。
    • 注意时间 - 它很大程度上受索引和/或表是否已缓存在RAM中的影响。

    关于FULLTEXT的另一件事是单词前面的+ - 说每个单词必须存在,否则就没有匹配。这可能会减少30K。

    FULLTEXT索引将传递date, id随机顺序,而不是PK顺序。无论如何,这是错误的'假设任何排序,因此它是正确的#39;要添加ORDER BY,如果知道它是多余的,请让优化器抛弃它。有时,优化工具可以利用ORDER BY(不是您的情况)。

    在许多情况下,只删除ORDER BY会使查询运行得更快。这是因为它可以避免获取30K行并对其进行排序。相反,它只是提供"任何" 10行。

    (我没有使用过Postgres,所以我无法解决这个问题。)