mysql full-text index

When mysql large table query, 'String%' fuzzy query can use the B+ tree type index prefix, but the 'String%' matching pattern is not what we need in the application, often need '%String%', this is what we can do Consider using the FULLTEXT index. INNODE is based on a red-black tree to store the full-text index. Let's test the full-text index.
First create a table:
CREATE TABLE fts_a(
FTS_DOC_ID BIGINT UNSIGNED AUTO_INCREMENT NOT NULL,
body TEXT,
PRIMARY KEY (FTS_DOC_ID)
);
Insert records:
INSERT INTO `test`.`fts_a` (`FTS_DOC_ID`, `body`) VALUES ('1 ', 'some one like you');
INSERT INTO `test`.`fts_a` (`FTS_DOC_ID`, `body`) VALUES ('2', 'you can you up');
INSERT INTO `test`.`fts_a ` (`FTS_DOC_ID`, `body`) VALUES ('3', 'I like your style');
INSERT INTO `test`.`fts_a` (`FTS_DOC_ID`, `body`) VALUES ('4', 'one day ,i see you');

mysql> CREATE FULLTEXT INDEX idx_fts ON fts_a(body);
Query OK, 0 rows affected
Records: 0  Duplicates: 0  Warnings: 0
查看索引:
mysql> show index from fts_a;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| fts_a | 0 | PRIMARY | 1 | FTS_DOC_ID | A | 4 | NULL | NULL | | BTREE | | |
| fts_a | 1 | idx_fts | 1 | body | NULL | 4 | NULL | NULL | YES | FULLTEXT | | |
+ -------+------------+------------+---------------+--- ----------+------------+-------------+----------+-- ------+------+------------+---------+------------- --+
2 rows in set

Set index parameters:
mysql> SET GLOBAL innodb_ft_aux_table='test/fts_a';
​​Query OK, 0 rows affected
View full-text index (inverted index) information:
mysql> select * from fts_a;
+--- ---------+--------------------------------+
| FTS_DOC_ID | body |
+------------+--------------------+
|          1 | some one like you  |
|          2 | you can you up     |
|          3 | I like your style  |
|          4 | one day ,i see you |
+------------+--------------------+
4 rows in set
mysql> select * from information_schema.INNODB_FT_INDEX_TABLE;
+-------+--------------+-------------+-----------+--------+----------+
| WORD  | FIRST_DOC_ID | LAST_DOC_ID | DOC_COUNT | DOC_ID | POSITION |
+-------+--------------+-------------+-----------+--------+----------+
| can   |            2 |           2 |         1 |      2 |        4 |
| day   |            4 |           4 |         1 |      4 |        4 |
| like  |            1 |           3 |         2 |      1 |        9 |
| like  |            1 |           3 |         2 |      3 |        2 |
| one   |            1 |           4 |         2 |      1 |        5 |
| one   |            1 |           4 |         2 |      4 |        0 |
| see   |            4 |           4 |         1 |      4 |       11 |
| some  |            1 |           1 |         1 |      1 |        0 |
| style |            3 |           3 |         1 |      3 |       12 |
| you   |            1 |           4 |         3 |      1 |       14 |
| you   |            1 |           4 |         3 |      2 |        0 |
| you   |            1 |           4 |         3 |      2 |        8 |
| you | 1 | 4 | 3 | 4 | 15 |
| your | 3 | 3 | 1 | 3 | 7 |
+-------+--------------+ -------------+------------+--------+----------+
14 rows in set
Deleting a record innodb will not delete the index immediately. To optimize the operation, the test is as follows
mysql> DELETE FROM fts_a WHERE fts_doc_id=4;
Query OK, 1 row affected

mysql> SELECT * FROM information_schema.INNODB_FT_DELETED;
+------- -+
| DOC_ID |
+--------+
| 4 |
+--------+
1 row in set
optimization:
mysql> SET GLOBAL innodb_optimize_fulltext_only=1;
Query OK, 0 rows affected

mysql> OPTIMIZE TABLE test.fts_a;
+------------+----------+----------+----------+
| Table      | Op       | Msg_type | Msg_text |
+------------+----------+----------+----------+
| test.fts_a | optimize | status   | OK       |
+------------+----------+----------+----------+
1 row in set

mysql> SELECT * FROM information_schema.INNODB_FT_DELETED;
+--------+
| DOC_ID |
+--------+
|      4 |
+--------+
1 row in set

mysql> SELECT * FROM information_schema.INNODB_FT_BEING_DELETED;
+--------+
| DOC_ID |
+--------+
|      4 |
+--------+
1 row in set
利用全文索引查询记录:
mysql> SELECT * FROM fts_a WHERE MATCH(body) AGAINST ('like' IN NATURAL LANGUAGE MODE);
+------------+-------------------+
| FTS_DOC_ID | body              |
+------------+-------------------+
|          1 | some one like you |
|          3 | I like your style |
+------------+-------------------+
2 rows in set
从查询解释我们可以看出使用个全文索引
mysql> EXPLAIN SELECT * FROM fts_a WHERE MATCH(body) AGAINST ('like' IN NATURAL LANGUAGE MODE);
+----+-------------+-------+----------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type     | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+-------+----------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | fts_a | fulltext | idx_fts       | idx_fts | 0       | NULL |    1 | Using where |
+----+-------------+-------+----------+---------------+---------+---------+------+------+-------------+
1 row in set
查询文档相关性
mysql>
SELECT FTS_DOC_ID,body,MATCH(body) AGAINST ('like' IN NATURAL LANGUAGE MODE) AS Relevance FROM fts_a ;
+------------+-------------------+--------------------+
| FTS_DOC_ID | body              | Relevance          |
+------------+-------------------+--------------------+
|          1 | some one like you | 0.0906190574169159 |
| 2 | you can you up | 0 |
| 3 | I like your style | 0.0906190574169159 |
| 5 | hell girls | 0 |
+------------+-------- -----------+--------------------------------+
4 rows in set
query exists like and you documentation
mysql> SELECT * FROM fts_a WHERE MATCH(body) AGAINST ('+like +you' IN BOOLEAN MODE);
+------------+------------------ -+
| FTS_DOC_ID | body |
+------------+-------------------+
| 1 | some one like you |
+ ------------+-------------------+
1 row in set
to see general matching queries, not using indexes
mysql> EXPLAIN SELECT * FROM fts_a WHERE body LIKE '%like%';
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | fts_a | ALL  | NULL          | NULL | NULL    | NULL |    4 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set


Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326692289&siteId=291194637