不是索引的列是否与索引一起在磁盘上排序?


8

在MySQL,MyISAM和InnoDB中,不是索引的列是否与索引一起在磁盘上排序?

我开始写一个错误的想法:

我认为可能不会,因为它们没有索引。如果将它们排序,则意味着它们是索引。

这是不正确的,因为每个索引列均按其自身内容的顺序排序,但是我要询问的是每一行(或仅某些列)及其相应索引的排序。

解释一下,我说:这对于使选择行的范围(按索引并排在一起)的速度更快很有用。例如,如果我想select * where id >1000 and id<2000(MySQL语法中可能有错误,我不太了解),那么可以快速从磁盘读取id列本身,因为它的1000到2000的单元可能一起位于物理磁盘上。但是可以将与id 1000到2000对应的其他列内容写入物理磁盘上的不同位置。如果还对它们进行了排序,则读取速度会更快。我认为,也许MySQL会自动对物理磁盘上的该列进行排序,以实现此类操作。

它们是否在其他类型的数据库(PostgreSQL等)中排序?

12月27日:从这两个答案中可以看到,在存在聚集索引/主键的情况下,简单行本身并未在物理磁盘上排序(正如我认为的那样/可能),甚至聚集索引也是没有排序,如果它是b树,我已经阅读了有关b树的信息,并且据我了解,它的节点停留在磁盘上的随机位置。

Answers:


9

在某些情况下,它们可能会被排序。该分类指数通常被称为聚集键。如果是这种情况,则整个表都存储在该索引内(通常以某种B树结构形式)。

在另一种情况下,表结构被称为,行将按行存储,删除数据块中的叶子“空洞”,然后这些空洞被新行填充,因此甚至不保留“插入顺序”。

MyISAM使用结构,每一行由数据文件中的offset(数组索引的排序)标识。然后,每个索引都包含每一行的索引列,并按正确的顺序排序,并带有偏移量编号以查找实际行。这意味着通过任何索引访问该行都意味着在索引(B树)中找到正确的节点,然后从数据文件中读取正确的偏移量(可能会随机搜索到磁盘的其他部分) )。

InnoDB通过主键使用集群(或者,如果没有定义集群,则使用第一个非null唯一键,或者添加内部自动递增列-以便始终以某种方式对行进行排序)。在这种情况下,通过主键进行的访问是“直接”,找到正确的值后,您就可以拥有整行,而无需进行第二次读取。另一方面,二级索引不能像MyISAM中那样存储偏移量(因为B树本身是动态重新平衡的,因此特定行的偏移量可以随时更改),而是存储该行的主键值-因此,通过辅助键访问意味着在InnoDB中进行两次B树搜索。

MS SQL Server提供了使主键(或另一个索引)成为群集或非群集主键的选项,因此您可以在(无索引的群集)和树结构(一个索引的群集)之间进行选择。所有其他非聚集索引在堆情况下存储特殊(RowID)值,在CI情况下存储行的聚集键值。

PostgreSQL仅使用表,但允许您根据需要按某些索引对其进行重新排序(您必须触发它,因此行将在操作后进行排序,但进一步写入表可能会再次破坏该顺序)。

TokuDB(第三方MySQL / MariaDB引擎)可以在一个表上使用多个集群键-有效地维护表的多个副本,每个副本以不同的方式排序。它伴随着写入的损失,但是TokuDB声称使用某种想法,他们称之为分形索引,这会使该损失很小。

如果您需要对某些查询使用该功能,则可以通过创建覆盖索引来“模拟”它-这样,您查询所需要的列就可以按正确的顺序随时可用,但这又意味着要维护(部分的)中的表格。


5

通常,数据库的简短回答是:不,表中行的物理顺序通常与该表中某些索引的顺序不同。

一般而言(我之所以这么说是因为在某些特殊情况下不正确),表和索引是磁盘上的两个不同的物理结构。传统的RDBM存储数据,以使来自一个表(而非)的值在磁盘上彼此相邻;行本身不以任何特定顺序存储。另一方面,索引条目按顺序存储;典型的b树索引包含索引列的排序值(而不是其他列!)和某种指向表中整行位置的指针,正如我之前所说的,这是磁盘上一个单独的物理结构。

话虽这么说,有一些特殊情况。例如,MySQL的InnoDB以类似索引的结构存储实际的数据行。在“索引表”中放置行的索引通常是表的主键;这种索引称为聚簇索引。但是,当然,InnoDB表可能具有其他索引,并且这些索引中的行顺序(即相应索引中包含的行列)与表本身中的行顺序无关。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.