mysql text字段的优化

mysql text字段比较特殊,text用来存储较多字符的字符串,因为text一般比较大,普通索引效率很低, 不可以直接在text字段上创建普通索引。

在text字段上可以创建2种索引:全文索引(fulltext index)和前缀索引(column prefix index)

(实际上全文索引可以在char,varchar,text上创建)

 

 

mysql全文索引

mysql的全文索引跟Oracle的全文索引是类似的,全文索引将字段中的词汇进行索引,获取方式跟parser相关,所以也存在text中存在的词索引不到的情况

全文索引创建语法跟一般索引不太一样,在index前有fulltext的关键字

create fulltext index idx_ft on t2(b);

如果没有fulltext关键字会报错

ERROR 1170 (42000): BLOB/TEXT column 'object_key' used in key specification without a key length

 

全文索引跟一般索引有所区别

mysql> show index from  t2;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t2    |          1 | idx_t2   |            1 | b           | A         |          47 |       10 | NULL   | YES  | BTREE      |         |               |
| t2    |          1 | idx_ft   |            1 | b           | NULL      |          47 |     NULL | NULL   | YES  | FULLTEXT   |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

其中index_type为fulltext

 

mysql使用全文索引不能使用like,必须用match  .. against

比如

SELECT * FROM lzltab WHERE MATCH (col1) AGAINST ('abcdefghijklmn');

 

 

mysql前缀索引

前缀索引会截取前N给字符并创建B+树索引。超过N个字符的索引是索引不到的

前缀索引跟普通索引创建方式类似

create index idx_t2 on t2(b(10));
mysql> show index from  t2;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t2    |          1 | idx_t2   |            1 | b           | A         |          47 |       10 | NULL   | YES  | BTREE      |         |               |
| t2    |          1 | idx_ft   |            1 | b           | NULL      |          47 |     NULL | NULL   | YES  | FULLTEXT   |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

 subpart字段可以看出该索引是只取了前10个字符的前缀索引

 

 

 

text字段sql的优化案例

某库cpu高,存在慢sql且执行次数和时间均偏高

执行计划如下

mysql> explain SELECT * FROM `tablzl` WHERE (ididid=73 and object_key='lzlzlzlzllz.pdf');
+----+-------------+------------------+------+--------------------+--------+---------+-------+--------+------------------------------------+
| id | select_type | table            | type | possible_keys      | key    | key_len | ref   | rows   | Extra                              |
+----+-------------+------------------+------+--------------------+--------+---------+-------+--------+------------------------------------+
|  1 | SIMPLE      | tablzl | ref  | uk_obj,idx_version | uk_obj | 8       | const | 400290 | Using index condition; Using where |
+----+-------------+------------------+------+--------------------+--------+---------+-------+--------+------------------------------------+

表数据分布和定义如下

mysql> select ididid,count(1) from tablzl group by ididid;
+-------------+----------+
| ididid | count(1) |
+-------------+----------+
|          23 |       64 |
|          73 |   633280 |
|         100 |     3627 |
|         106 |      481 |
|         107 |      914 |
|         121 |   178694 |
|         124 |      320 |
|         130 |      204 |
|         132 |      118 |
|         134 |      991 |
|         135 |      569 |
|         144 |      615 |
|         150 |      990 |
+-------------+----------+
13 rows in set (0.29 sec)
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_obj` (`ididid`,`file_id`),
  KEY `idx_region` (`uid`,`region_id`),
  KEY `idx_version` (`ididid`,`rule_version`)

sql走的是uk_obj索引,过滤的字段是ididid,而ididid的值为73时,过滤性很差,从而导致该sql执行效率较低。(当ididid不为73时,sql执行效率较高,所有慢sql只有ididid=73的)
 关键问题还是要让sql走object_key='lzlzlzlzllz.pdf'这样的条件过滤,所以要在object_key上创建索引

 

尝试创建普通索引

mysql> create index idx_obj_id on tablzl(object_key);
mysql> ERROR 1170 (42000): BLOB/TEXT column 'object_key' used in key specification without a key length

普通索引在text字段无法创建

 

尝试创建fulltext全文索引

mysql>  create fulltext index  idx_obj_id on tablzl(object_key);
Query OK, 0 rows affected, 1 warning (50.42 sec)
Records: 0  Duplicates: 0  Warnings: 1
mysql> explain SELECT * FROM `tablzl` WHERE (ididid=73 and object_key='lzlzlzlzllz.pdf');
+----+-------------+------------------+------+------------------------+-------------+---------+-------+--------+------------------------------------+
| id | select_type | table            | type | possible_keys          | key         | key_len | ref   | rows   | Extra                              |
+----+-------------+------------------+------+------------------------+-------------+---------+-------+--------+------------------------------------+
|  1 | SIMPLE      | tablzl | ref  | uk_obj ,idx_version | uk_obj | 8       | const | 408092 | Using index condition; Using where |
+----+-------------+------------------+------+------------------------+-------------+---------+-------+--------+------------------------------------+

使用全文索引必须用match agaist语句,不该sql是走不了的


因为sql的object_key='lzlzlzlzllz.pdf'前面没有%,所以可以走前缀索引

创建前缀索引

mysql> create index idx_obj_key on tablzl(object_key(50));
Query OK, 0 rows affected (9.39 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> explain SELECT * FROM `tablzl` WHERE (ididid=73 and object_key='lzlzlzlzllz.pdf');
+----+-------------+------------------+------+-------------------------+-------------+---------+-------+------+-------------+
| id | select_type | table            | type | possible_keys           | key         | key_len | ref   | rows | Extra       |
+----+-------------+------------------+------+-------------------------+-------------+---------+-------+------+-------------+
|  1 | SIMPLE      | tablzl | ref  | idx_inst_id,idx_obj_key | idx_obj_key | 153     | const |    1 | Using where |
+----+-------------+------------------+------+-------------------------+-------------+---------+-------+------+-------------+

包含text字段的sql成功走到前缀索引,cpu使用率从40%下降到4%
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liuzhilongDBA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值