全文索引提高速度,SQL 数据库设计

FULLTEXT Indexes for speed, SQL database design

我有一千万条记录。 MySQL 数据库如下所示:

tagline: varchar(255)   
location: varchar(80)   
experience: text (normally about 600 characters)
country varchar(50) 

以前,我正在执行这样的查询,这导致了完整的 table 扫描,这花费了太长时间:

SELECT COUNT(*) FROM `mytable` WHERE
`tagline` LIKE '%sales%'
AND `location` LIKE '%texas%'
AND `experience` LIKE '%software%'

这里的人告诉我应该对每个字段应用全文索引。他们告诉我应该执行这样的查询:

SELECT COUNT(*) FROM `mytable` WHERE
MATCH(tagline) AGAINST("sales")
AND MATCH(location) AGAINST("texas")
AND MATCH(experience) AGAINST("software")

我只想确认一下:

(a) 结果应该是一样的

(b)速度会更快

(c) 唯一的缺点是数据库的大小增加以及我的系统在每个字段上实现 FULLTEXT 索引所花费的时间。

请不要指责我太具体。仅以我的设置为例。任何想要搜索功能并拥有大量文本数据的人都会从回复中受益。

正如我在上面的评论中提到的,如果您分别为三列中的每一列编制索引,则 MySQL 查询必须为每个 table 引用选择一个索引。它不能在同一查询中使用所有三个索引,除非您使用不同的 table 引用。

您应该为所有三列创建一个全文索引:

ALTER TABLE mytable ADD FULLTEXT INDEX(tagline, location, experience);

然后用一个谓词搜索:

SELECT COUNT(*) 
FROM `mytable`
WHERE MATCH(tagline, location, experience) 
  AGAINST("+sales +texas +software" IN BOOLEAN MODE);

但这失去了在每列中找到哪个关键字的关联。然后您可以应用 old-school LIKE 条件来优化搜索,这些条件只需要检查与全文搜索匹配的行。

SELECT COUNT(*) 
FROM `mytable`
WHERE MATCH(tagline, location, experience) 
  AGAINST("+sales +texas +software" IN BOOLEAN MODE)
AND tagline LIKE '%sales%'
AND location LIKE '%texas%'
AND experience LIKE '%software%';

代价高昂的部分是当查询必须执行 table-scan 以检查数百万行时。如果您使用全文索引将候选匹配项缩小到几行,则使用 LIKE 对一小部分行进行的额外字符串比较可能不会太昂贵。


回复您的评论:

这是我在 运行 EXPLAIN 测试 table 中得到的结果:

mysql> create table mytable (
  id serial primary key, 
  tagline text, 
  location text, 
  experience text, 
  fulltext index(tagline, location, experience) 
);

mysql> explain SELECT COUNT(*) 
    -> FROM `mytable`
    -> WHERE MATCH(tagline, location, experience) 
    ->   AGAINST("+sales +texas +software" IN BOOLEAN MODE)
    -> AND tagline LIKE '%sales%'
    -> AND location LIKE '%texas%'
    -> AND experience LIKE '%software%'\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: mytable
   partitions: NULL
         type: fulltext
possible_keys: tagline
          key: tagline
      key_len: 0
          ref: const
         rows: 1
     filtered: 100.00
        Extra: Using where; Ft_hints: no_ranking

type: fulltext表示将使用全文索引。