`
丁林.tb
  • 浏览: 797306 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

关于InnoDB的索引大小

阅读更多

     这篇文章来自在一个啾啾群纠结的问题。

 

 

背景

         关于InnoDB内的索引大小。对于表

CREATE TABLE `testtb` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a` int(11) DEFAULT NULL,
  `b` int(11) DEFAULT NULL,
  `c` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `i1` (`a`),
  KEY `i2` (`a`,`id`),
  KEY `i3` (`id`,`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

 

 

由于InnoDB在存储索引的时候会自动取出重复的主键,源码分析见这里

先说几个结论

1)       Index i2 由于索引定义中已经包含pk  id,因此不会存两份,实际就是(a, id)

2)       Index i1 本身要包含主键id,因此也是(a, id) i2 相同

3)       同理1,Index i3 里存的也只是(id, a)

 

异常

         按照上面的结论,以下操作能发现“异常”

 

 

 

 

    

CREATE TABLE `t1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a` int(11) DEFAULT NULL,
  `b` int(11) DEFAULT NULL,
  `c` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `i2` (`a`,`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `testtb` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a` int(11) DEFAULT NULL,
  `b` int(11) DEFAULT NULL,
  `c` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `i3` (`id`,`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

  

          接下来往这个两个表中各插入5w行记录,插入语句类似

 

 Foreach I in 1 to 5w
     {
       Set @v = rand() * 100;
       Insert into testtb(a,b,c) values(@v, @v, @v);
     }

 

         插入数据完成后,这个两个表索引大小是否相同?

 

         show table status like ‘%t1%’; show table status like ‘%t2%’;index_length可以看出来,是不同的,t1大一些。

         存储的行数相同,数据也相同,为什么大小不一样?

 

原因说明

         主要在于插入顺序导致的分裂。在上面的例子中,由于a,b,c的值都是随机值,导致索引 (a, id)是随机的。 Id是递增的,所以(id, a)是递增的。

         随机插入索引和顺序递增插入索引之所以有差别,就在于随机插入会导致更多的Btree分裂。

 

这也就是为什么在某些场景下,我们建议在表比较大的应用中,用自增id替代unique key (并非唯一的原因,也不是固定的规范,需要具体分析)

 

验证

有了上面的分析,要验证就比较简单了,把两个表清空(truncate)

插入数据改为如下的语句

 

Foreach I in 1 to 5w
     {
       Set @v = i;
       Insert into testtb(a,b,c) values(@v, @v, @v);
     }

 

 

这样插入的每行都是(n,n,n,n), n15w的递增。这样索引(a, id)也是顺序递增方式,与(id,a)一样紧凑,再看show table status能发现一样了。

 

有个工具

         分两个表验证比较麻烦。这个是之前写过的一个分析文件利用率的工具 ibd_used,可以看一个表上各个索引的大小和索引上page的利用率。

         用法

./ibd_used testtb.ibd 0 N > k

 

说明:第一个参数是要分析的ibd文件

              第二、三个参数是起始、结束page_no  如果你要分析整个文件,N可以输入一个很大的数就行。

               结果中会输出每个page的利用率,因此比较多,记得重定向输出

 

         最后几行是整个索引的统计结果。

 

 

用文章开头的例子和随机值插入的case,得到的表中,执行

 

ibd_used data/test/testtb.ibd 0 99999999 > k
最后几行如下
index_id:1517 rate 1751652/1949696=0.898423
index_id:1518 rate 701314/1212416=0.578443
index_id:1519 rate 701314/1212416=0.578443
index_id:1520 rate 700828/770048=0.910109

 

 

 

 

 按顺序对应索引,可以看出,i1i2的利用率一模一样,但跟i3 比起来就差多了。

 

grep -Po " index_id:\d+" k | sort | uniq -c                                    
    120 index_id:1517
     75 index_id:1518
     75 index_id:1519
     48 index_id:1520

 

 

    这个命令看每个索引占用多少page,与我们的结论一致:i3因为紧凑,所以占用更少的page

5
6
分享到:
评论
8 楼 7先生 2013-04-01  
请问ibd_used这个工具去哪下载?你给的链接好像已经取消分享了。
7 楼 zhoujy 2012-09-21  
丁林.tb 写道
zhoujy 写道
houjy@zhoujy:~$ ll ibd_used
-rwxr-xr-x 1 zhoujy zhoujy 11087 2012-09-20 15:38 ibd_used
zhoujy@zhoujy:~$ md5sum  ibd_used
b90f6a038ea162c102f5abccc332453c  ibd_used

http://pan.baidu.com/share/link?shareid=61749&uk=1191507911 这里下的。

这都对哦。。对了, 你是不是32位系统。。?




是的。原来不适合32位的系统啊,那我还到64位的试试。








6 楼 丁林.tb 2012-09-20  
zhoujy 写道
houjy@zhoujy:~$ ll ibd_used
-rwxr-xr-x 1 zhoujy zhoujy 11087 2012-09-20 15:38 ibd_used
zhoujy@zhoujy:~$ md5sum  ibd_used
b90f6a038ea162c102f5abccc332453c  ibd_used

http://pan.baidu.com/share/link?shareid=61749&uk=1191507911 这里下的。

这都对哦。。对了, 你是不是32位系统。。?
5 楼 zhoujy 2012-09-20  
houjy@zhoujy:~$ ll ibd_used
-rwxr-xr-x 1 zhoujy zhoujy 11087 2012-09-20 15:38 ibd_used
zhoujy@zhoujy:~$ md5sum  ibd_used
b90f6a038ea162c102f5abccc332453c  ibd_used

http://pan.baidu.com/share/link?shareid=61749&uk=1191507911 这里下的。
4 楼 丁林.tb 2012-09-20  
./ibd_used
zhoujy 写道
已经是可执行文件了,但是还是报这个问题。
root@zhoujy:/home/zhoujy# ./ibd_used  /var/lib/mysql/cms/cms_new_block.ibd 0 99999999  > /home/zhoujy/aaa.txt
-bash: ./ibd_used: 无法执行二进制文件

b90f6a038ea162c102f5abccc332453c  ibd_used md5没错吧?

ll ibd_used   输出什么
3 楼 zhoujy 2012-09-20  
已经是可执行文件了,但是还是报这个问题。
root@zhoujy:/home/zhoujy# ./ibd_used  /var/lib/mysql/cms/cms_new_block.ibd 0 99999999  > /home/zhoujy/aaa.txt
-bash: ./ibd_used: 无法执行二进制文件
2 楼 丁林.tb 2012-09-20  
zhoujy 写道
ibd_used 这个工具好像很好用,但是怎么执行报错:
-bash: ./ibd_used: 无法执行二进制文件 

chmod 755 ibd_used
1 楼 zhoujy 2012-09-20  
ibd_used 这个工具好像很好用,但是怎么执行报错:
-bash: ./ibd_used: 无法执行二进制文件 

相关推荐

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

    在优化方面,选择合适的主键对于InnoDB尤为重要,因为主键的大小直接影响到所有辅助索引的大小。过长的主键会导致辅助索引变得庞大,降低查询效率。此外,使用自增整数作为主键有利于保持B+树的平衡,提高插入性能。...

    浅析InnoDB索引结构

    【InnoDB索引结构浅析】 InnoDB是MySQL数据库中常用的一种存储引擎,以其支持事务处理和行级锁定而著名。在InnoDB中,索引的构建和组织方式对数据库性能有着重大影响。本文将深入探讨InnoDB的索引特性,特别是聚集...

    MyISAM与InnoDB的索引差异

    因此,建议选择较短且趋势递增的整数类型作为主键,以减少索引大小并优化插入性能。例如,如果查询条件是根据非主键列执行的,如`select * from t where name='lisi'`,InnoDB会首先通过name辅助索引找到主键值,...

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

    索引页,也称为页节点,是InnoDB存储索引记录的基本单位,其默认大小为16KB。当新记录插入时,InnoDB会保留1/16的页面空间作为预留空间,以适应未来的插入和更新操作。如果索引记录按顺序插入,页可填满至15/16;若...

    innoDB 索引结构详解

    【InnoDB 索引结构详解】 InnoDB和MyISAM是MySQL中两种常见的存储引擎,它们在事务处理、锁粒度以及并发性方面存在显著差异。InnoDB支持事务处理,提供行级锁,适合高并发环境。而MyISAM不支持事务,采用表级锁,...

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

    InnoDB默认页大小为16KB。 #### 页面存储格式 - **页头(Page Header)**:记录页面的控制信息,包括页的状态、上一个和下一个页的指针等。 - **最小虚记录(Infimum)和最大虚记录(Supremum)**:存储在页面的...

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

    在实际应用中,开发者还可以通过调整数据库参数,如缓冲池大小、索引缓存等,进一步优化这两种引擎的性能。 总的来说,MyISAM和InnoDB引擎各有优劣,选择哪种引擎取决于你的应用场景和性能需求。如果你的工作负载...

    解读InnoDB数据库索引页与数据行的紧密关联

    在这座城市中,每一块16KB大小的土地都被称为一个“页”(Page),而这些页是城市基础设施的核心,其主角就是“索引页”(INDEX页),这些页专门用于存储我们表中的实际记录数据,因此也被称为“数据页”(Data Page...

    XtraDB、InnoDB 内部结构示意图

    这个参数决定了InnoDB可以用来缓存数据和索引的内存大小。 2. InnoDB的页面缓存机制 内容中提到页面缓存是针对表和索引的。InnoDB通过ibdata1文件来存储数据字典信息,并将表和索引的数据分成16KB大小的页面。对于...

    innodb_ruby-master.zip

    B+树是InnoDB主要使用的索引结构,理解其工作原理有助于创建高效索引。应避免全表扫描,合理利用覆盖索引(Covering Index)和组合索引(Composite Index)。 5. 缓冲池(Buffer Pool) InnoDB的缓冲池用于缓存...

    MySql Innodb 引擎特性详解

    7. **不支持全文索引**:尽管InnoDB功能强大,但它不支持全文索引功能,这一点在特定的应用场景中可能需要额外考虑。 #### 三、InnoDB 引擎应用场景 1. **需要事务支持的业务**:任何需要保证数据完整性和一致性的...

    InnoDB官方文档中文翻译版

    包括调整缓冲池大小、优化索引使用、合理设置事务隔离级别、使用连接池、合理设计表结构等,都是提升InnoDB性能的重要手段。 十、InnoDB Plugin InnoDB Plugin是InnoDB的一个增强版本,引入了许多新的特性和改进,...

    InnoDB 中文参考手册(CHM)

    合理配置缓冲池大小和刷新策略是优化InnoDB性能的关键。 9. **自增列与插入缓冲(Insert Buffer)** 对于非聚集索引的插入,InnoDB会使用插入缓冲,以减少对非主键索引页的直接修改,提高插入性能。 10. **多...

    MySQL Innodb 参数详解与优化实践

    - **描述**:设置InnoDB用于高速缓存数据和索引的内存大小。 - **应用场景**:根据服务器可用内存大小调整,一般建议设置为物理内存的80%,以减少磁盘I/O操作。 ##### 12. `innodb_additional_mem_pool_size` - **...

    实战mysql innodb 删除数据后释放磁盘

    缓存的大小可以通过参数 innodb_buffer_pool_size 来设置。缓存的作用是提高查询效率,但是如果缓存太小,将会导致查询效率下降。 InnoDB 删除数据后释放磁盘空间需要通过设置参数 innodb_file_per_table=1 和使用 ...

Global site tag (gtag.js) - Google Analytics