`
purpen
  • 浏览: 785561 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

一个例子与InnoDB索引的几个概念

阅读更多

1 、一个简单的 sql 语 句问题

    假设当前我们有一个表记录用户信息,结构如下:

    a)      表结构

CREATE TABLE `u` (

  `id` int(11) NOT NULL DEFAULT ‘0′,

  `regdate` int(1) unsigned,

  …..

  PRIMARY KEY (`id`),

  KEY `regdate` (`regdate`)

) ENGINE=InnoDB DEFAULT CHARSET=gbk

说明:1) 由于需要按照注册时间单独查询,建了一个regdate的索引

            2) 其他信息未列出, 一行长度100字节左右,表行数百万级。 

b)      需求:需要一个语句查出表中id为10000整数倍的记录总数。

 

2 、常规答案

    一个正常想到的语句是 select sum(id % 10000 = 0) from u; —— (SQL1)

    我们来看这个语句的执行流程:

a)      遍历所有数据,取出id字段

b)      计算id%10000=0的值并通过sum累计。

           在构造的环境中这个语句的执行时间为2.6s.

 

3 、查的多,查得快

    假设我们同时要查出注册时间在2007年之前的用户总数,我们自然得到这个语句

     select sum(id % 10000 = 0), sum(regdate<1167667200) from sbtest;—-(SQL2)

    执行结果发现这个语句执行时间约0.5s 。 这个语句查的数据结果比SQL1多,但执行时间却降为1/5.

 

4 、分析  

    可以直接从执行期间的磁盘参数,或者在os/os0file.c中将程序读取的数据量输出结果查看,直观结果是SQL1读取了更多的磁盘数据。

问题1: 在SQL1执行过程中,遍历所有数 据,InnoDB只从磁盘读取了id这个字段,还是全部读入?

    实际上由于id是聚簇索引,并没有一个单独的索引树存id,因此在磁盘上,id索引树的叶节点上就是数据。 InnoDB以page为单位读取,在取id的过程中,必须将所有的数据读入。

    于是我们发现,在SQL1中,我们只需要id字段,而每行额外读入了几百字节的数据。

问题2: SQL2避免了读全数据?

    确实如此。

    我们对比两个语句的explain结果, 发现仅有的不同是选用的key结果不同。

SQL1 SQL2
key: PRIMARY key: regdate

    由于regdate是非聚簇(secondary index)索引,单独存于另一棵树。 我们知道使用非聚簇索引时,需 要读行数据的时候 ,需要再到聚簇索引中取得。显然SQL2不会再读一遍全数据(否则性能必然低于SQL1)。

    而其原因是覆盖索引(covering index)。 非聚簇索引的叶节点上是聚簇索引的字段值,需要取数据时,根据这个值再去聚簇索引上取。而这时InnoDB变“聪明”了, 需要取的值只是id,而id作为聚簇索引的key信息,已经得到,不需要再到聚簇索引中 读取数据。

    由于regdate索引树上只有regdate和主键(id)的信息,因此数据量远小于全表数据,因此SQL2的读盘量小于SQL1,执行速度快。

 

5 、其他  

    这个例子涉及到几个概念, 聚簇索引(cluster index)、非聚簇索引(secondary index), 覆盖索引(covering index),还有磁盘的数据存放。都算是一些基本的内容,却是平时见到的一些优化的理论基础。举几个例子如下:

1)      我们经常被告诫select之后只填最必须的字段

    其中的一个原因是减少网络传输。但不一定能够提升服务器执行性能。比如例子中的表,select  * from u where id = n; 与select user_name from u where id =n一样。

    当然有些时候效果会很理想,比如 select id from u where regdate=xxx 就比select * from u where regdate=xxx快很多,原因已说明。

2)      查询符合条件的第10w个记录开始的10个记录。

    这个例子在其他博文上被多次提及,

select * from t order by a limit 100000, 10; 可以改进为

select * from t where a>=(select a from t order by a limit 100000,1) limit 10;

    在笔者环境中性能提升约1000倍。

    原因即在于, 改进语句中,子查询中的排序只在非聚餐索引a上执行,由于覆盖索引,排序过程不需要访问聚簇索引。实际读读取全数据的只有10条记录,而原语句则需要读所 有记录的全数据。

    当然执行排序的过程消耗是一样的。 

6、结束

    回到开头,如果只需要查id满足特定条件的记录总数,可以使用select sum(id % 10000 = 0) from u force index (`regdate`);  

    把sum(id %10000=0)换成其他操作对执行效率均没有影响。 

    但若查询内容中出现除id和regdate外的其他字段,则force index优化无效,可自行分析。

分享到:
评论

相关推荐

    MySQL Innodb 索引原理详解

    MySQL Innodb 索引原理详解

    辛星笔记之InnoDB索引

    辛星笔记之MySQL部分之InnoDB引擎的索引部分。

    关于InnoDB的索引大小

    NULL 博文链接:https://dinglin.iteye.com/blog/1682188

    002.InnoDB索引与MyISAM索引实现的区别是什么?.mp4

    InnoDB索引与MyISAM索引实现的区别是什么?.mp4 InnoDB索引与MyISAM索引实现的区别是什么?.mp4 InnoDB索引与MyISAM索引实现的区别是什么?.mp4 InnoDB索引与MyISAM索引实现的区别是什么?.mp4 InnoDB索引与MyISAM...

    MyISAM与InnoDB的索引差异

    MyISAM和InnoDB都使用B+树来实现索引: • MyISAM的索引与数据分开存储 • MyISAM的索引叶子存储指针,主键索引...• InnoDB一定有且只有一个聚集索引 • InnoDB建议使用趋势递增整数作为PK,而不宜使用较长的列作为PK

    浅析InnoDB索引结构

    我们知道,InnoDB引擎的聚集索引组织表,必然会有一个聚集索引。 行数据(row data)存储在聚集索引的叶子节点(除了发生overflow的列,参见 ,后面简称 “前置文”),并且其存储的相对顺序取决于聚集索引的顺序...

    mysql,innodb索引介绍

    BTree索引的基本概念,优劣势,分裂问题,explain输出解释,如何使用optimizer trace

    1.1.6 从innodb的索引结构分析,为什么索引的 key 长度不能太长.md

    1.1.6 从innodb的索引结构分析,为什么索引的 key 长度不能太长

    深入讲解MySQL Innodb索引的原理

    主要给大家介绍了关于MySQL Innodb索引原理的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用mysql具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    浅谈innodb的索引页结构,插入缓冲,自适应哈希索引

    下面小编就为大家带来一篇浅谈innodb的索引页结构,插入缓冲,自适应哈希索引。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    MyISAM引擎与InnoDB引擎性能的对比

    MyISAM引擎与InnoDB引擎性能的对比

    一文搞定InnoDB索引

    关于InnoDB索引及相关知识的个人理解,如遇错误欢迎指正。 目录InnoDB的索引聚集索引(clustered index)普通索引(secondary index)回表是什么覆盖索引/索引覆盖...一个InnoDB引擎的表,必须有且只有一个聚集索引 聚集索

    innoDB 索引结构详解

    1、数据库索引 innoDB和MyISAM对比 区别 innoDB MyISAM 事物支持 支持 不支持 锁粒度 行锁 表锁 并发性 高并发 低并发 构成结构和缓存机制 数据和索引文件都存在在.Idb文件里,并且都缓存在内存里。 ...

    MyISAM和InnoDB索引引擎的B+树索引实现1

    2)辅助索引(Secondary key)在 MyISAM 中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求 key 是唯

    InnoDB存储引擎中有页(Page)的概念

    系统从磁盘读取数据到内存时是以磁盘块(block)为基本单位的,位于同一个磁盘块中的数据...而系统一个磁盘块的存储空间往往没有这么大,因此InnoDB每次申请磁盘空间时都会是若干地址连续磁盘块来达到页的大小16KB。In

    【数据库】浅析Innodb的聚集索引与非聚集索引

    Mysql存储引擎之一的Innodb的索引,可以分为聚集索引与非聚集索引,这两种索引都是使用B+树组织的。 本文不讲解什么是索引,对索引不了解的同学可以先移步到我的另外一篇文章【数据库】mysql索引简谈 在分析这两种...

    MySQL技术内幕 InnoDB存储引擎.pdf

    5. 索引与算法 5.1 概述 5.2 数据结构与算法 5.3 B+树索引 5.4 B+树索引的分裂 5.5 Cardinality值 5.6 全文索引 6. 锁 - 实现事务的隔离性 6.1 什么是锁 6.2 lock和latch 6.3 InnoDB存储引擎中的锁 6.4 ...

    Mysql InnoDB引擎的索引与存储结构详解

    主要给大家介绍了Mysql InnoDB引擎的索引与存储结构的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧

Global site tag (gtag.js) - Google Analytics