mysql数据页存储与磁盘之间的关系

数据库存储和读取

转载:https://my.oschina.net/u/1859679/blog/1581379

在整个数据库体系结构中,我们可以使用不同的存储引擎来存储数据,而绝大多数存储引擎都以二进制的形式存储数据。

在 InnoDB 存储引擎中,所有的数据都被逻辑地存放在表空间中,表空间(tablespace)是存储引擎中最高的存储逻辑单位,在表空间的下面又包括段(segment)、区(extent)、页(page):

在这里插入图片描述

同一个数据库实例的所有表空间都有相同的页大小;默认情况下,表空间中的页大小都为 16KB,当然也可以通过改变 innodb_page_size 选项对默认大小进行修改,需要注意的是不同的页大小最终也会导致区大小的不同:

三、随机读取和顺序读取
在我们常用的sql理解中,数据是以行的形式读取出来的,其实不然,通过上述的结构,我们可以了解到,单次从磁盘读取单位是页,而不是行,也就是说,你即便只读取一行记录,从磁盘中也是会读取一页的,当然了单页读取代价也是蛮高的,一般都会进行预读,这些后续再说。

关系型数据库管理系统最重要的一个目标就是,确保表或者索引中的数据是随时可以用的。那么为了尽可能的实现这个目标,会使用内存中的缓冲池来最小化磁盘活动。

每一个缓冲池都足够大,大到可以存放许多页,可能是成千上万的页。

缓冲池管理器将尽力确保经常使用的数据被保存于池中,以避免一些不必要的磁盘读。如果一个索引或者表页在缓冲池中被找到,那么将会处理很快。

如果在缓冲池中,没有找到数据,会从磁盘服务器的缓冲区里面去读取。

磁盘服务器的缓冲区,如同数据库的缓冲池读取一样,磁盘服务器试图将频繁使用的数据保留在内存中,以降低高昂的磁盘读取成本。这个读取成本大概会在1ms左右。

如果磁盘服务器的缓冲池中依然没有找到数据,此时就必须要从磁盘读取了,此时读取又分区随机读取和顺序读取。

2、随机I/O
我们必须记住一个页包含了多条记录,我们可能需要该页上的所有行,也可能是其中一部分,或者是一行,但所花费的成本都是相同的,读取一个页,需要一次随机I/O,大约需要10ms的时间。

在这里插入图片描述

3、顺序读取
如果我们需要将多个页读取到缓冲池中,并按顺序处理它们,此时读取的速度回变的很快,具体的原理,在B树索引中也有过介绍,此时读取每个页面(4kb)所花费的时间大概为0.1ms左右,这个时间消耗对随机IO有很大的优势。

以下几种情况,会对数据进行顺序读取。

全表扫描

全索引扫描

索引片扫描

通过聚蔟索引扫描表行

顺序读取有两个重要的优势:

同时读取多个页意味着平均读取每个页的时间将会减少。在当前磁盘服务器条件下,对于4kb大小的页而言,这一值可能会低于0.1ms(40MB/s)
由于数据库引擎知道需要读取哪些页,所有可以在页被真正请求之前就提前将其读取进来,我们称为预读

最大与最小(数据库的阀值)

  1. 一个表里最多可有1017列(在MySQL 5.6.9 之前最大支持1000列)。虚拟列也受限这个限制。

  2. 一个表最多可以有64个二级索引。

  3. 如果innodb_large_prefix打开,在InnoDB表DYNAMIC或COMPRESSED列格式下,索引前缀最大支持前3072字节;如果不打开的话,在任意列格式下,最多支持前767字节。这个限制既适用于前缀索引也适用于全列索引。
    基于一个16KB的页最多装3072个字节,如果你把InnoDB 的page 大小从8KB降到4KB,索引的长度也相应的降低。也就是说,当页是8KB的时候最大索引长度是1536字节;当页大小是4KB的时候最大索引长度是768字节;(

这里与“紧凑冗余行有关系”

紧凑和冗余行格式

当为外部页外存储选择可变长度列时InnoDB,将该行中的前768个字节存储在本地,其余外部存储到溢出页中。每个这样的列都有自己的溢出页列表。768字节的前缀伴随着一个20字节的值,该值存储列的真实长度并指向溢出列表,其中存储了值的其余部分。请参见 第14.11节“InnoDB行格式”。


转载https://dev.mysql.com/doc/refman/5.7/en/innodb-file-space.html
14.12.2文件空间管理

联合索引最多支持16列,如果超过这个限制就会遇到以下错误:
ERROR 1070 (42000): Too many key parts specified; max 16 parts allowed

  1. 行长度(除去可变长类型:VARBINARY/VARCHAR/BLOB/TEXT),要小于页长(如4KB, 8KB, 16KB, and 32KB)的一半。例如:innodb_page_size 长度是16KB的话,行长不超过8KB;如果innodb_page_size 是64KB的话,行长不超过16KB; LONGBLOB/LONGTEXT/BLOB/TEXT列必须小于4GB,整个行长也必须小于4GB。如果一行小于一页的一半,它可以存在一个page里面。如果超过了页的一半,就会把可变长列放到额外的页存(如果对这个感兴趣的话可以看看,MySQL页管理)。

  2. 行所存储的值的最大值为页的大小的一半,一般情况下页的大小是16kB,所以每行的长度大小不能超过8
    kb;2的16次刚好为65535;

  • 4
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值