Patrick Dezecache Asked: 2014-12-08 06:39:00 +0800 CST2014-12-08 06:39:00 +0800 CST 2014-12-08 06:39:00 +0800 CST 数据库文件中的索引和行放置 772 物理数据库文件或物理文件页面中存储的索引和数据表在哪里: 同一个物理页中的不同表可以有不同的行吗? MySQL 是如何决定在某个页面的什么地方放置一行的? 索引放置也怎么样? 我对网络数据库(IDMSX 数据库)略知一二,它在物理页面上直接计算位置(如果可能,其他记录存储在附近)。 mysql physical-design 2 个回答 Voted Michael - sqlbot 2014-12-08T07:45:05+08:002014-12-08T07:45:05+08:00 从技术上讲,“MySQL”本身并没有单一的答案,因为MySQL具有可插拔的存储引擎架构,而服务器本身本质上是不关心也不知道数据的物理存储是如何完成的。这些细节由存储引擎处理。 MySQL 中最相关的存储引擎是 InnoDB。 在同一个物理页中可以有来自不同表的不同行吗? 不,不能。事实上,表通常甚至不会将表存储在同一个文件中,如果您使用推荐的配置,其中每个表都有自己单独的表空间文件;但是,即使innodb_file_per_table未启用,页面也不会在表之间共享。默认情况下innodb_page_size是 16K 字节,但也可以使用 8k 和 4k 大小。 MySQL 是如何决定在某个页面的什么地方放置一行的? 索引放置也怎么样? 任何特定的行或索引条目只能放在一个地方,因为行是按主键列排序存储的,而索引条目是按索引列排序存储的。 组成每个表的页面排列在称为 B 树索引的树数据结构中。表数据和二级索引都使用这种类型的结构。表示整个表的 B 树索引称为聚簇索引,它根据主键列进行组织。索引数据结构的节点包含该行中所有列的值(对于聚集索引)或索引列和主键列(对于二级索引)。 — http://dev.mysql.com/doc/refman/5.6/en/innodb-row-format-overview.html 不适合页面的行数据,在BLOBAND 的情况下,有时VARCHAR列存储在 b 树页面之外,在溢出页面中,由指向页面外位置的指针引用。该列可以完全页外或部分存储(以便在页上提供一些前缀字符以减少某些情况下对页外访问的需求)。此行为因行格式以及您是否使用内部表压缩而异。当您的系统受 I/O 限制但有可用的 CPU 周期时,表压缩可以提高性能,因为它减少了总体磁盘 I/O。 如果按顺序(升序或降序)插入索引记录,则生成的索引页大约为 15/16 满。如果记录以随机顺序插入,则页面从 1/2 到 15/16 满。如果索引页的填充因子低于 1/2,InnoDB 会尝试收缩索引树以释放该页。 — http://dev.mysql.com/doc/refman/5.6/en/innodb-physical-structure.html 当然,当插入新数据时,表空间的全部内容不会“向下移动”以为其他页面腾出空间。页面是链接的,因此相对于每个页面上的内部排序,页面在磁盘上的存储连续性取决于数据是按顺序插入还是随机插入。 值得注意的是,InnoDB 缓冲池通过在物理存储和更高层之间提供中间缓冲区,使底层存储实现不那么相关——在 RDBMS 中它应该如此——不那么相关。该缓冲区是固定数量的内存,在服务器守护程序启动时分配,这使得物理磁盘存储变得不那么重要。 InnoDB 在内存中维护了一个称为缓冲池的存储区域,用于缓存数据和索引。了解 InnoDB 缓冲池的工作原理,并利用它在内存中保留经常访问的数据,是 MySQL 调优的一个重要方面。 缓冲池越大,InnoDB 就越像一个内存数据库,一次从磁盘读取数据,然后在后续读取期间从内存访问数据。缓冲池甚至缓存由插入和更新操作更改的数据,以便磁盘写入可以组合在一起以获得更好的性能。 池插入/更新操作当然会立即提交到磁盘,但它们不会直接写入磁盘上存储它们的页面中的位置。要写入的更改被记录(使用顺序磁盘写入)并在 InnoDB 缓冲池中在内存中、页面上更新,然后缓冲池中更改的页面被刷新(写出)到它们的位置通过后台线程在表空间文件中。 Best Answer akuzminsky 2014-12-08T07:23:40+08:002014-12-08T07:23:40+08:00 MySQL 存储数据的方式取决于存储引擎。InnoDB 中有页的概念,而 MyISAM 中有块。在 InnoDB 中,一个页面固定为 16k,而在 MyISAM 中,一个块的大小取决于块的类型和其中记录的大小。 InnoDB 将表存储在他们称为索引的 B+ 树数据结构中。表本身(包含所有字段值的记录)存储在索引 PRIMARY 中。任何二级键也存储在其 B+树索引中。如果为 ON,则表的所有索引都存储在相应的 .ibd 文件中;如果innodb_file_per_table为 OFF,则存储在 ibdata1 中。 MyISAM 是不同的。表的记录以块的形式存储在 .MYD 文件中。任何新记录都会附加到 MYD 文件的末尾。MYD 文件不是一棵树——只是一组块。如果表有主键或辅助键,它们将保存在 B+ 树索引中,这些索引存储在 .MYI 文件中。(我不记得它是否完全是 B+ 树,但肯定是一些 B 树)。 在同一个物理页中可以有来自不同表的不同行吗? 不。 InnoDB 中的页面属于某个索引。页面不能在索引之间共享。MyISAM 块也是如此。 MySQL 是如何决定在某个页面的什么地方放置一行的? 对于 MyISAM,它只是将记录添加到 MYD 文件的末尾。MYI 中的索引根据树算法重建。对于 InnoDB 来说,新记录被插入到 B+ 树中,所以同样,根据 B+ 树算法。
从技术上讲,“MySQL”本身并没有单一的答案,因为MySQL具有可插拔的存储引擎架构,而服务器本身本质上是不关心也不知道数据的物理存储是如何完成的。这些细节由存储引擎处理。
MySQL 中最相关的存储引擎是 InnoDB。
不,不能。事实上,表通常甚至不会将表存储在同一个文件中,如果您使用推荐的配置,其中每个表都有自己单独的表空间文件;但是,即使
innodb_file_per_table
未启用,页面也不会在表之间共享。默认情况下innodb_page_size
是 16K 字节,但也可以使用 8k 和 4k 大小。任何特定的行或索引条目只能放在一个地方,因为行是按主键列排序存储的,而索引条目是按索引列排序存储的。
不适合页面的行数据,在
BLOB
AND 的情况下,有时VARCHAR
列存储在 b 树页面之外,在溢出页面中,由指向页面外位置的指针引用。该列可以完全页外或部分存储(以便在页上提供一些前缀字符以减少某些情况下对页外访问的需求)。此行为因行格式以及您是否使用内部表压缩而异。当您的系统受 I/O 限制但有可用的 CPU 周期时,表压缩可以提高性能,因为它减少了总体磁盘 I/O。当然,当插入新数据时,表空间的全部内容不会“向下移动”以为其他页面腾出空间。页面是链接的,因此相对于每个页面上的内部排序,页面在磁盘上的存储连续性取决于数据是按顺序插入还是随机插入。
值得注意的是,InnoDB 缓冲池通过在物理存储和更高层之间提供中间缓冲区,使底层存储实现不那么相关——在 RDBMS 中它应该如此——不那么相关。该缓冲区是固定数量的内存,在服务器守护程序启动时分配,这使得物理磁盘存储变得不那么重要。
池插入/更新操作当然会立即提交到磁盘,但它们不会直接写入磁盘上存储它们的页面中的位置。要写入的更改被记录(使用顺序磁盘写入)并在 InnoDB 缓冲池中在内存中、页面上更新,然后缓冲池中更改的页面被刷新(写出)到它们的位置通过后台线程在表空间文件中。
MySQL 存储数据的方式取决于存储引擎。InnoDB 中有页的概念,而 MyISAM 中有块。在 InnoDB 中,一个页面固定为 16k,而在 MyISAM 中,一个块的大小取决于块的类型和其中记录的大小。
InnoDB 将表存储在他们称为索引的 B+ 树数据结构中。表本身(包含所有字段值的记录)存储在索引 PRIMARY 中。任何二级键也存储在其 B+树索引中。如果为 ON,则表的所有索引都存储在相应的 .ibd 文件中;如果
innodb_file_per_table
为 OFF,则存储在 ibdata1 中。MyISAM 是不同的。表的记录以块的形式存储在 .MYD 文件中。任何新记录都会附加到 MYD 文件的末尾。MYD 文件不是一棵树——只是一组块。如果表有主键或辅助键,它们将保存在 B+ 树索引中,这些索引存储在 .MYI 文件中。(我不记得它是否完全是 B+ 树,但肯定是一些 B 树)。
不。 InnoDB 中的页面属于某个索引。页面不能在索引之间共享。MyISAM 块也是如此。
对于 MyISAM,它只是将记录添加到 MYD 文件的末尾。MYI 中的索引根据树算法重建。对于 InnoDB 来说,新记录被插入到 B+ 树中,所以同样,根据 B+ 树算法。