iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >MySQL中InnoDB引擎如何对索引的扩展
  • 598
分享到

MySQL中InnoDB引擎如何对索引的扩展

2024-04-02 19:04:59 598人浏览 八月长安
摘要

Mysql中InnoDB引擎如何对索引的扩展,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。InnoDB引擎对索引的扩展,自动追加主键值及其对执

Mysql中InnoDB引擎如何对索引的扩展,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

InnoDB引擎对索引的扩展,自动追加主键值及其对执行计划的影响。


mysql中,使用InnoDB引擎的每个表,创建的普通索引(即非主键索引),都会同时保存主键的值。
比如语句
CREATE TABLE t1 (
 i1 INT NOT NULL DEFAULT 0,
 i2 INT NOT NULL DEFAULT 0,
 d DATE DEFAULT NULL,
 PRIMARY KEY (i1, i2),
 INDEX k_d (d)
) ENGINE = InnoDB;
创建了t1表,其主键为(i1, i2),同时创建了基于d列的索引k_d,但其实在底层,InnoDB引擎将索引k_d扩展成(d,i1,i2)。
InnoDB引擎这么做,是用空间换性能,优化器在判断是否使用索引及使用哪个索引时会有更多列参考,这样可能生成更高效的执行计划,获得更好的性能。
优化器在ref、range和index_merge类型的访问,Loose Index Scan访问,连接和排序优化, MIN()/MAX()优化时使都会使用扩展列。
我们来看个例子:
root@database-one 15:15:  [gftest]> CREATE TABLE t1 (
   ->   i1 INT NOT NULL DEFAULT 0,
   ->   i2 INT NOT NULL DEFAULT 0,
   ->   d DATE DEFAULT NULL,
   ->   PRIMARY KEY (i1, i2),
   ->   INDEX k_d (d)
   -> ) ENGINE = InnoDB;
Query OK, 0 rows affected (0.06 sec)

root@database-one 15:15:  [gftest]> INSERT INTO t1 VALUES
   -> (1, 1, '1998-01-01'), (1, 2, '1999-01-01'),
   -> (1, 3, '2000-01-01'), (1, 4, '2001-01-01'),
   -> (1, 5, '2002-01-01'), (2, 1, '1998-01-01'),
   -> (2, 2, '1999-01-01'), (2, 3, '2000-01-01'),
   -> (2, 4, '2001-01-01'), (2, 5, '2002-01-01'),
   -> (3, 1, '1998-01-01'), (3, 2, '1999-01-01'),
   -> (3, 3, '2000-01-01'), (3, 4, '2001-01-01'),
   -> (3, 5, '2002-01-01'), (4, 1, '1998-01-01'),
   -> (4, 2, '1999-01-01'), (4, 3, '2000-01-01'),
   -> (4, 4, '2001-01-01'), (4, 5, '2002-01-01'),
   -> (5, 1, '1998-01-01'), (5, 2, '1999-01-01'),
   -> (5, 3, '2000-01-01'), (5, 4, '2001-01-01'),
   -> (5, 5, '2002-01-01');
Query OK, 25 rows affected (0.01 sec)
Records: 25  Duplicates: 0  Warnings: 0

root@database-one 15:21:  [gftest]> show index from t1;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| t1    |          0 | PRIMARY  |            1 | i1          | A         |           5 |     NULL | NULL   |      | BTREE      |         |               |
| t1    |          0 | PRIMARY  |            2 | i2          | A         |          25 |     NULL | NULL   |      | BTREE      |         |               |
| t1    |          1 | k_d      |            1 | d           | A         |           5 |     NULL | NULL   | YES  | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.01 sec)
在普通索引中追加扩展主键是InnoDB在底层做的,show index等语句不显示追加列,但我们可以通过其它方式来验证。看这个sql
SELECT COUNT(*) FROM t1 WHERE i1 = 3 AND d = ‘2000-01-01’
如果InnoDB没有扩展索引,索引k_d为(d),生成的执行计划应该类似这样,使用k_d索引找到d为’2000-01-01’的5行数据,再回表过滤出i1为3的,最后计算count。或者使用主键索引找到i1为3的5行数据,再回表过滤出d为’2000-01-01’的,最后计算count。下面仅示意走k_d索引的情况:
mysql> EXPLaiN SELECT COUNT(*) FROM t1 WHERE i1 = 3 AND d = '2000-01-01'\G
*************************** 1. row ***************************
          id: 1
 select_type: SIMPLE
       table: t1
        type: ref
possible_keys: PRIMARY,k_d
         key: k_d
     key_len: 4
         ref: const
        rows: 5
       Extra: Using where; Using index
如果InnoDB扩展了索引,索引k_d为(d,i1,i2),这时,优化器可以使用最左边的索引前缀(d,i1),生成的执行计划应该类似这样,使用k_d索引找到d为’2000-01-01’及i1为3的1行数据,然后计算count
mysql> EXPLAIN SELECT COUNT(*) FROM t1 WHERE i1 = 3 AND d = '2000-01-01'\G
*************************** 1. row ***************************
          id: 1
 select_type: SIMPLE
       table: t1
        type: ref
possible_keys: PRIMARY,k_d
         key: k_d
     key_len: 8
         ref: const,const
        rows: 1
       Extra: Using index
并且d列是DATE类型占4个字节,i1是INT类型占4个字节,所以查询中使用的键值长度就是8个字节(key_len: 8)。
我们看看实际生成的执行计划
root@database-one 15:35:  [gftest]> EXPLAIN SELECT COUNT(*) FROM t1 WHERE i1 = 3 AND d = '2000-01-01'\G
*************************** 1. row ***************************
          id: 1
 select_type: SIMPLE
       table: t1
  partitions: NULL
        type: ref
possible_keys: PRIMARY,k_d
         key: k_d
     key_len: 8
         ref: const,const
        rows: 1
    filtered: 100.00
       Extra: Using index
1 row in set, 1 warning (0.01 sec)
果然跟我们的判断一致,注意执行计划中的细节:
  • key_len从4字节变为8字节,表明键查找使用列d和i1,而不仅仅是d。

  • ref从const更改为const,const,表明查找使用两个键值,而不是一个。

  • rows从5减少到1,表明检索更少的行。

  • Extra从Using where; Using index改为Using index,表示只用索引读取,不必回表。


InnoDB引擎底层扩展普通索引的情况,也可以通过跟MyISAM引擎对比来进行旁证:
root@database-one 16:07:  [gftest]> CREATE TABLE t1MyISAM (
   ->   i1 INT NOT NULL DEFAULT 0,
   ->   i2 INT NOT NULL DEFAULT 0,
   ->   d DATE DEFAULT NULL,
   ->   PRIMARY KEY (i1, i2),
   ->   INDEX k_d (d)
   -> ) ENGINE = MyISAM;
Query OK, 0 rows affected (0.01 sec)

root@database-one 16:07:  [gftest]> INSERT INTO t1myisam VALUES
   -> (1, 1, '1998-01-01'), (1, 2, '1999-01-01'),
   -> (1, 3, '2000-01-01'), (1, 4, '2001-01-01'),
   -> (1, 5, '2002-01-01'), (2, 1, '1998-01-01'),
   -> (2, 2, '1999-01-01'), (2, 3, '2000-01-01'),
   -> (2, 4, '2001-01-01'), (2, 5, '2002-01-01'),
   -> (3, 1, '1998-01-01'), (3, 2, '1999-01-01'),
   -> (3, 3, '2000-01-01'), (3, 4, '2001-01-01'),
   -> (3, 5, '2002-01-01'), (4, 1, '1998-01-01'),
   -> (4, 2, '1999-01-01'), (4, 3, '2000-01-01'),
   -> (4, 4, '2001-01-01'), (4, 5, '2002-01-01'),
   -> (5, 1, '1998-01-01'), (5, 2, '1999-01-01'),
   -> (5, 3, '2000-01-01'), (5, 4, '2001-01-01'),
   -> (5, 5, '2002-01-01');
Query OK, 25 rows affected (0.02 sec)
Records: 25  Duplicates: 0  Warnings: 0

root@database-one 16:07:  [gftest]> EXPLAIN SELECT COUNT(*) FROM t1myisam WHERE i1 = 3 AND d = '2000-01-01'\G
*************************** 1. row ***************************
          id: 1
 select_type: SIMPLE
       table: t1myisam
  partitions: NULL
        type: ref
possible_keys: PRIMARY,k_d
         key: PRIMARY
     key_len: 4
         ref: const
        rows: 4
    filtered: 16.00
       Extra: Using where
1 row in set, 1 warning (0.01 sec)
可以看到,同样的结构同样的数据,因为MyISAM引擎不会在底层自动扩展普通索引,所以执行计划还是通过主键索引进行处理。
按照官方手册的说明,也可以用SHOW STATUS命令来验证
root@database-one 16:12:  [gftest]> FLUSH TABLE t1;
Query OK, 0 rows affected (0.00 sec)

root@database-one 16:12:  [gftest]> FLUSH STATUS;
Query OK, 0 rows affected (0.14 sec)

root@database-one 16:12:  [gftest]> SELECT COUNT(*) FROM t1 WHERE i1 = 3 AND d = '2000-01-01';
+----------+
| COUNT(*) |
+----------+
|        1 |
+----------+
1 row in set (0.03 sec)

root@database-one 16:12:  [gftest]> SHOW STATUS LIKE 'handler_read%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Handler_read_first    | 0     |
| Handler_read_key      | 1     |
| Handler_read_last     | 0     |
| Handler_read_next     | 1     |
| Handler_read_prev     | 0     |
| Handler_read_rnd      | 0     |
| Handler_read_rnd_next | 0     |
+-----------------------+-------+
7 rows in set (0.01 sec)

root@database-one 16:13:  [gftest]> FLUSH TABLE t1myisam;
Query OK, 0 rows affected (0.01 sec)

root@database-one 16:13:  [gftest]> FLUSH STATUS;
Query OK, 0 rows affected (0.00 sec)

root@database-one 16:13:  [gftest]> SELECT COUNT(*) FROM t1myisam WHERE i1 = 3 AND d = '2000-01-01';
+----------+
| COUNT(*) |
+----------+
|        1 |
+----------+
1 row in set (0.01 sec)

root@database-one 16:13:  [gftest]> SHOW STATUS LIKE 'handler_read%';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Handler_read_first    | 0     |
| Handler_read_key      | 1     |
| Handler_read_last     | 0     |
| Handler_read_next     | 5     |
| Handler_read_prev     | 0     |
| Handler_read_rnd      | 0     |
| Handler_read_rnd_next | 0     |
+-----------------------+-------+
7 rows in set (0.00 sec)
Handler_read_next表示在进行索引扫描时,按照索引从数据文件里取数据的次数。使用MyISAM引擎的t1myisam表,Handler_read_next值为5,使用InnoDB引擎的t1表,Handler_read_next值减小到1,就是因为InnoDB引擎对索引进行了主键扩展,读取的次数少,效率更好。
默认情况下,优化器分析InnoDB表的索引时会考虑扩展列,但如果因为特殊原因让优化器不考虑扩展列,可以使用SET optimizer_switch = 'use_index_extensions=off’设置。
root@database-one 16:26:  [gftest]> SET optimizer_switch = 'use_index_extensions=off';
Query OK, 0 rows affected (0.01 sec)

root@database-one 16:26:  [gftest]> EXPLAIN SELECT COUNT(*) FROM t1 WHERE i1 = 3 AND d = '2000-01-01'\G
*************************** 1. row ***************************
          id: 1
 select_type: SIMPLE
       table: t1
  partitions: NULL
        type: ref
possible_keys: PRIMARY,k_d
         key: PRIMARY
     key_len: 4
         ref: const
        rows: 5
    filtered: 20.00
       Extra: Using where
1 row in set, 1 warning (0.02 sec)

看完上述内容,你们掌握MySQL中InnoDB引擎如何对索引的扩展的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注编程网数据库频道,感谢各位的阅读!

您可能感兴趣的文档:

--结束END--

本文标题: MySQL中InnoDB引擎如何对索引的扩展

本文链接: https://www.lsjlt.com/news/61483.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • MySQL中InnoDB引擎如何对索引的扩展
    MySQL中InnoDB引擎如何对索引的扩展,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。InnoDB引擎对索引的扩展,自动追加主键值及其对执...
    99+
    2024-04-02
  • MySQL中Innodb存储引擎索引的示例分析
    这篇文章主要为大家展示了“MySQL中Innodb存储引擎索引的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“MySQL中Innodb存储引擎索引的示例...
    99+
    2024-04-02
  • Mysql Innodb存储引擎之索引与算法
    目录一、概述二、数据结构与算法1、二分查找2、二叉查找树和平衡二叉树1)二叉查找树2)平衡二叉树三、B+树1、B+树完整定义2、关于 M 和 L的选定案例四、B+树索引1、聚集索引2...
    99+
    2024-04-02
  • MySQL-SQL InnoDB引擎 (中)
    ♥️作者:小刘在C站 ♥️个人主页: 小刘主页  ♥️努力不一定有回报,但一定会有收获加油!一起努力,共赴美好人生! ♥️学习两年总结出的运维经验,以及思科模拟器全套网络实验教程。专栏:云计算技术 ♥️小刘私信可以随便问,只要会...
    99+
    2023-08-31
    数据库 mysql sql
  • 如何开启mysql的innodb引擎
    如何开启mysql的innodb引擎,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。 开启mysql的innodb引...
    99+
    2024-04-02
  • Mysql InnoDB引擎的索引与存储结构详解
    前言 在Oracle 和SQL Server等数据库中只有一种存储引擎,所有数据存储管理机制都是一样的。 而MySql数据库提供了多种存储引擎。用户可以根据不同的需求为数据表选择不同的存储引擎,用户也可以根...
    99+
    2024-04-02
  • MySQL中MyISAM引擎与InnoDB引擎性能比较
    MySQL中MyISAM引擎与InnoDB引擎性能比较,基本上我们可以考虑使用InnoDB来替代我们的MyISAM引擎。MySQL表结构CREATE TABLE `myisam` (`id` int(11)...
    99+
    2024-04-02
  • 如何将MySQL中的MyISAM存储引擎转换为InnoDB存储引擎?
    要将MyISAM引擎转换为InnoDB,我们可以使用ALTER命令。现在让我们借助引擎MyISAM 创建一个表。 mysql> create table MyISAMToInnoDBDemo -> ( -> id ...
    99+
    2023-10-22
  • 怎么进行InnoDB引擎和MyISAM引擎的对比
    这期内容当中小编将会给大家带来有关怎么进行InnoDB引擎和MyISAM引擎的对比,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。  ...
    99+
    2024-04-02
  • 如何理解InnoDB引擎
    这期内容当中小编将会给大家带来有关如何理解InnoDB引擎,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。一、综述innodb的物理文件包括系统表空间文件ibdata,用户表空间文件ibd,日志文件ib_l...
    99+
    2023-05-31
  • MySQL扩展存储引擎有哪些
    这篇文章将为大家详细讲解有关MySQL扩展存储引擎有哪些,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。 下面介绍几个列式存储引擎:一:TokuDBToku...
    99+
    2024-04-02
  • MySQL中InnoDB存储引擎是如何设计的
    小编给大家分享一下MySQL中InnoDB存储引擎是如何设计的,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!  MySQL 中的...
    99+
    2024-04-02
  • Mysql Innodb存储引擎之索引与算法的示例分析
    这篇文章将为大家详细讲解有关Mysql Innodb存储引擎之索引与算法的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、概述索引太少,查询效率低;索引太多程序性能受到影响,索引的使用...
    99+
    2023-06-29
  • MySql中的存储引擎和索引
    目录一、MySql的逻辑结构二、什么是存储引擎MySQL支持的存储引擎三、操作四、数据库的索引索引的分类五、索引操作一、MySql的逻辑结构 MySQL体系结构分为四层:分别是连接层...
    99+
    2022-11-13
    MySql存储引擎 MySql索引
  • mysql中怎么开启Innodb引擎
    mysql中怎么开启Innodb引擎,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1、stop mysql2、编辑my.cnf文件,把skip...
    99+
    2024-04-02
  • MySQL存储引擎中的索引分析
    本篇内容主要讲解“MySQL存储引擎中的索引分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“MySQL存储引擎中的索引分析”吧!我们知道不同的存储引擎文件是不...
    99+
    2024-04-02
  • mysql如何修改存储引擎为innodb
    这篇文章主要介绍“mysql如何修改存储引擎为innodb”,在日常操作中,相信很多人在mysql如何修改存储引擎为innodb问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”...
    99+
    2024-04-02
  • MySQL的存储引擎InnoDB和MyISAM
    目录1. MyISAM底层存储1.1 MyISAM底层存储(非聚集索引方式)1.2 InnoDB底层存储(聚集索引方式)2. InnoDB与MyISAM简介3. MyISAM与Inn...
    99+
    2024-04-02
  • MySQL中InnoDB存储引擎是什么
    这篇文章给大家分享的是有关MySQL中InnoDB存储引擎是什么的内容。小编觉得挺实用的,因此分享给大家做个参考。一起跟随小编过来看看吧。在MySQL中InnoDB属于存储引擎层,并以插件的形式集成在数据库...
    99+
    2024-04-02
  • MySQL5.7中的InnoDB引擎简介
    这篇文章主要讲解了“MySQL5.7中的InnoDB引擎简介”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“MySQL5.7中的InnoDB引擎简介”吧! ...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作