如何给mysql创建组合索引并分析索引命中(官方校正版)

MySQL 可以使用多列索引来执行测试索引中所有列的查询,或者仅测试第一列、前两列、前三列等的查询。如果您在索引定义中以正确的顺序指定列,则单个复合索引可以加速同一表上的几种查询。

MySQL 可以创建复合索引(即在多个列上建立索引)。索引最多可包含 16 个列。

对于某些数据类型,您可以索引列的前缀。

多列索引可以被视为一个排序数组,其行包含通过连接索引列的值而创建的值。

以下语句可以通过命令行操作,如需要SQL工具可以试用SQLynx或MySQL workbench等

作为复合索引的替代方法,您可以引入一个基于其他列的信息进行"散列"的列。如果此列很短、相当唯一且已编入索引,则它可能比在许多列上建立"宽"索引更快。在 MySQL 中,使用此额外列非常容易:

language-sql 复制代码
SELECT * FROM tbl_name
  WHERE hash_col=MD5(CONCAT(val1,val2))
  AND col1=val1 AND col2=val2;

假设有一张表具有以下规格:

language-sql 复制代码
CREATE TABLE test (
    id         INT NOT NULL,
    last_name  CHAR(30) NOT NULL,
    first_name CHAR(30) NOT NULL,
    PRIMARY KEY (id),
    INDEX name (last_name,first_name)
);

索引是和列name的索引 。索引可用于在指定已知范围内的值的查询中查找 和 值的组合。它还可以用于仅指定值的查询, 因为该列是索引的最左前缀(如本节后面所述)。因此,索引用于以下查询中的查找: last_name``first_name``last_name``first_name``last_name``name

language-sql 复制代码
SELECT * FROM test WHERE last_name='Jones';

SELECT * FROM test
  WHERE last_name='Jones' AND first_name='John';

SELECT * FROM test
  WHERE last_name='Jones'
  AND (first_name='John' OR first_name='Jon');

SELECT * FROM test
  WHERE last_name='Jones'
  AND first_name >='M' AND first_name < 'N';

但是,name索引 用于以下查询中的查找:

language-sql 复制代码
SELECT * FROM test WHERE first_name='John';

SELECT * FROM test
  WHERE last_name='Jones' OR first_name='John';

假设您发出以下 SELECT语句:

language-sql 复制代码
SELECT * FROM tbl_name
  WHERE col1=val1 AND col2=val2;

col1如果和 上存在多列索引col2,则可直接提取相应的行。如果 和 上存在单独的单列索引 col1,则col2优化器将尝试使用索引合并优化(请参见 第 10.2.1.3 节"索引合并优化"),或者尝试通过确定哪个索引排除更多行并使用该索引提取行来找到最严格的索引。

如果表具有多列索引,则优化器可以使用索引的任何最左前缀来查找行。例如,如果您在 上有一个三列索引,则您具有对、和 的 (col1, col2, col3)索引搜索功能 。 (col1)(col1, col2)(col1, col2, col3)

如果列不构成索引的最左前缀,则 MySQL 无法使用索引执行查找。假设您有SELECT如下所示的语句:

sql 复制代码
SELECT * FROM tbl_name WHERE col1=val1;
SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;

SELECT * FROM tbl_name WHERE col2=val2;
SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;

如果 上有索引(col1, col2, col3),则只有前两个查询会使用索引。第三和第四个查询确实涉及索引列,但不使用索引来执行查找,因为(col2)(col2, col3)不是的最左前缀 (col1, col2, col3)

相关推荐
Muscleheng43 分钟前
Navicat连接postgresql时出现‘datlastsysoid does not exist‘报错
数据库·postgresql
X1A0RAN1 小时前
解决Pycharm中部分文件或文件夹被隐藏不展示问题
ide·python·pycharm
kyriewen1 小时前
面试官让我查各部门工资最高的员工,我用AI三秒写出窗口函数,他愣了
后端·mysql·面试
小码工作室1 小时前
使用 HAVING 进行 MySQL 集合筛选
mysql
罗超驿1 小时前
18.事务的隔离性和隔离级别:MySQL面试高频考点全解析
数据库·mysql·面试
jran-2 小时前
Redis 命令
数据库·redis·缓存
小江的记录本2 小时前
【Java基础】Java 8-21新特性:JDK21 LTS:虚拟线程、模式匹配switch、结构化并发、序列集合(附《思维导图》+《面试高频考点清单》)
java·数据库·python·mysql·spring·面试·maven
June`2 小时前
多线程redis下如何解决aof重写和rdb持久化的数据一致性问题
数据库·redis·缓存
木心术13 小时前
Windows系统下MySQL与AI工具集成方案:数据存储与调用实践
人工智能·windows·mysql
二宝哥3 小时前
离线安装maven
java·数据库·maven