技术分享 | 在长字符串上创建索引

贾敏
• 阅读 1763

作者:姚远

MySQL ACE,华为云 MVP ,专注于 Oracle、MySQL 数据库多年,Oracle 10G 和 12C OCM,MySQL 5.6,5.7,8.0 OCP。现在鼎甲科技任技术顾问,为同事和客户提供数据库培训和技术支持服务。

本文来源:原创投稿

*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。


当在很长的字符串的字段上创建索引时,索引会变得很大而且低效,一个解决办法是 crc32 或 md5 函数对长字符串进行哈希计算,然后在计算的结果上创建索引。在 MySQL 5.7 以后的版本,可以创建一个自动生成的字段,例如可以创建下面一个表:

create table website(
id int unsigned not null,
web varchar(100) not null,
webcrc int unsigned generated always as (crc32(web)) not null,
primary key (id)
);

向这个表中插入记录:

mysql> insert into website(id,web) values(1,"https://www.scutech.com");
Query OK, 1 row affected (0.07 sec)

mysql> select * from website;
+----+-------------------------+-----------+
| id | web                     | webcrc    |
+----+-------------------------+-----------+
|  1 | https://www.scutech.com | 851176738 |
+----+-------------------------+-----------+
1 row in set (0.00 sec)

可以看到字段 webcrc 中自动生成了 web 字段的循环冗余校验值,在这个字段上创建索引,可以得到一个占用空间少,而且高效的索引。

在 MySQL 8.0.13 以后的版本,可以直接创建函数索引,例如:

create table website8(
id int unsigned not null,
web varchar(100) not null,
primary key (id),
index ((crc32(web)))
);

查询这个表上的索引:

mysql> show index from website8\G
*************************** 1. row ***************************
        Table: website8
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:
      Visible: YES
   Expression: NULL
*************************** 2. row ***************************
        Table: website8
   Non_unique: 1
     Key_name: functional_index
 Seq_in_index: 1
  Column_name: NULL
    Collation: A
  Cardinality: 0
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:
      Visible: YES
   Expression: crc32(`web`)
2 rows in set (0.00 sec)

可以看到第一个索引是主键,第二个索引是函数索引。

解决索引字段长的另一个办法是创建前缀索引(prefix index),前缀索引的创建语法是:col_name(length),前缀索引是对字符串的前面一部分创建索引,支持的数据类型包括:CHAR、VARCHAR、BINARY 和 VARBINARY。创建前缀索引的关键是选择前缀的字符串的长度,长度越长,索引的选择性越高,但存储的空间也越大。

sbtest2 表中 c 字段是 120 长度的字符串,下面的 SQL 语句查询在不同长度时索引的选择性:

mysql> select
count(distinct(left(c,3)))/count(*) sel3,
count(distinct(left(c,7)))/count(*) sel7,
count(distinct(left(c,9)))/count(*) sel9,
count(distinct c)/count(*) selectivity
from sbtest1;
+--------+--------+--------+-------------+
| sel3   | sel7   | sel9   | selectivity |
+--------+--------+--------+-------------+
| 0.0120 | 0.9959 | 1.0000 |      1.0000 |
+--------+--------+--------+-------------+
1 row in set (1.66 sec)

可以看到在这个字段的前 9 位创建索引即可达到 1 的选择性,再增加这个索引的前缀位数,索引的选择性并不会提高,下面是创建索引的命令:

mysql> alter table sbtest2 add index (c(9));
点赞
收藏
评论区
推荐文章
待兔 待兔
11个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
MySql索引下推知识分享
作者:刘邓忠Mysql是大家最常用的数据库,下面为大家带来mysql索引下推知识点的分享,以便巩固mysql基础知识,如有错误,还请各位大佬们指正。1什么是索引下推索引下推(IndexConditionPushdown,索引条件下推,简称ICP),是MyS
Wesley13 Wesley13
3年前
Mysql、Oracle、PostgreSql数据库索引失效场景详细讲解
Mysql、Oracle、PostgreSql数据库索引失效场景详细讲解前言前言Mysql、Oracle、PostgreSql数据库索引失效场景详细讲解。废话不多说直接贴:1、任何计算、函数、类型转换2、!、<3、ISNULL或者ISNOTNULL。类似导致索引失效的还有NOTIN
Stella981 Stella981
3年前
Django之Django模板
1、问:html页面从数据库中读出DateTimeField字段时,显示的时间格式和数据库中存放的格式不一致,比如数据库字段内容为2012082616:00:00,但是页面显示的却是Aug.26,2012,4p.m.答:为了页面和数据库中显示一致,需要在页面格式化时间,需要添加<td{{dayrecord.p\_time|date:
Stella981 Stella981
3年前
MyRocks及其使用场景分析
出处:https://zhuanlan.zhihu.com/p/45652076作者:温正湖(任职于网易杭州研究院,从事数据库内核开发)MyRocks是一种经过空间和写性能优化的MySQL数据库,为您业务的数据库选型提供一种靠谱的选择。本文主要介绍什么是MyRocks,包括其功能特性,重点讲解MyRocks相比InnoDB的优势,详细
Wesley13 Wesley13
3年前
MySQL索引背后的数据结构及算法原理
摘要本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题。特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等。为了避免混乱,本文将只关注于BTree索引,因为这是平常使用MySQL时主要打交道的索引,至于哈希索引和全文索引本文
Wesley13 Wesley13
3年前
Java程序访问Mysql Cluster
在192.168.56.10或者192.168.56.20任意一台机器上,访问数据库,命令为:1/bin/mysql比如现在我在192.168.56.10机器上面创建数据库assetscenterdb,执行命令:1createdatabaseassetscenterdb创建成功之后,在192.168.56.20的机器上
Stella981 Stella981
3年前
ELK学习笔记之ElasticSearch的索引详解
0x00ElasticSearch的索引和MySQL的索引方式对比Elasticsearch是通过Lucene的倒排索引技术实现比关系型数据库更快的过滤。特别是它对多条件的过滤支持非常好,比如年龄在18和30之间,性别为女性这样的组合查询。倒排索引很多地方都有介绍,但是其比关系型
Wesley13 Wesley13
3年前
MongoDB性能篇
一、索引MongoDB提供了多样性的索引支持,索引信息被保存在system.indexes中,且默认总是为\_id创建索引,它的索引使用基本和MySQL等关系型数据库一样。其实可以这样说说,索引是凌驾于数据存储系统之上的另一层系统,所以各种结构迥异的存储都有相同或相似的索引实现及使用接口并不足为奇。1.基础索引在字段age
子桓 子桓
2年前
DBeaverEE Mac版
DBeaverEE一款功能强大的数据库管理工具,它支持多种数据库管理系统,包括MySQL、PostgreSQL、Oracle、SQLServer、SQLite等。DBeaverEE是DBeaver的企业版,提供了更多高级功能和技术支持。DBeaverEE具