繁体   English   中英

关系数据库如何获取未索引的列?

[英]How do relational databases fetch the unindexed columns?

我的问题与关系数据库访问数据的方式有关,以及使用仅索引扫描的特殊情况,即仅检查所有“ where”条件并从某个索引获取所有返回值的扫描,而无需访问表本身。

  1. 想象我们需要访问一些不在索引中的列。 我们出于两个原因中的一个(或两个)而需要访问它们:与“ where”子句进行比较并作为结果获取列值。 在这种情况下,数据库将如何操作:它将获取整个行,或者仅获取所需的列?

  2. 作为第一个问题的结果,这个问题浮出水面:如果我们不使用仅索引扫描,在选择查询中返回的列数真的很重要吗? 我的意思是,如果我们必须获取“ where”子句或将其与未索引的某些列进行比较-返回多少列真的很重要,否则我们可以写“ select * from ...”而无需担心数据库提取整行吗?

  3. 当我们使用“仅索引扫描”时,我们必须将查询处理的所有列都包含在一个索引中。 如果其他索引中包含某些列,则不会破坏性能。 我对吗?

  4. 我已经读过MySQL InnoDB引擎默认使用聚集索引,即表中的所有行都按某个索引进行物理排序。 这意味着使用某些二级索引搜索该表的效率较低,因为在那之后搜索数据库必须在一级索引之上进行第二次搜索,因为在聚集索引中db不再存储rowId。 我对吗? 如果是,为什么MySQL以这种方式实现索引,从而限制了二级索引的使用?

其中一些解释可能会超出您已经知道的内容,但是完整的细节可能会对将来的读者有所帮助。

  1. 服务器很可能只会获取所需的行。 但是,这可能会受到数据存储方式的影响。 例如,InnoDB引擎通常存储大数据(例如TEXTBLOB的页外数据,因此,如果不需要这些数据,则可能不会被提取。

  2. 我想在这里需要澄清一下,如果我在您的问题中遗漏了一些东西,请纠正我。 首先,最好只返回所需的列并列出所有列,而不要选择*更快。 与#1一样,选择其他列将产生多大的差异。 选择大列(例如TEXTBLOB )通常比小列更昂贵。

  3. 我不确定100%在这里是什么意思,但我想我可以回答这个问题。 如果在SELECT c1, c2, c3 FROM table WHERE c1 = 1 AND c2 = 2SELECT c1, c2, c3 FROM table WHERE c1 = 1 AND c2 = 2类的查询,则像(c1,c2,c3)类的索引可能是最佳的; 查询所需的所有列都在索引中,因此服务器不需要查找完整的数据行。 c1c2c3是否包含在任何其他索引中都没有关系。

  4. 在您的问题中,您说a clustered index db is not storing the rowId anymore ,这不是完全正确的。

    假设rowId是数据的唯一标识符,可能是数字标识符:

    在非群集数据库表中,所有索引都将一些列连接到物理数据位置。 对于主索引,这看起来像rowId -> data location 次要索引看起来像column 1 -> column 2 -> data location 为了获取任何其他数据,服务器将根据物理位置查找数据。

    在集群表中,物理数据基本上是主要索引。 主索引看起来像rowId -> data ,辅助索引看起来像column 1 -> column 2 -> rowId

    对于非聚集表,完整的查找路径看起来像rowId -> data location -> data使用主索引的rowId -> data location -> datacolumn 1 -> column 2 -> data location -> data辅助索引的column 1 -> column 2 -> data location -> data

    对于集群表,它看起来像rowId -> data主索引的rowId -> datacolumn 1 -> column 2 -> rowId -> data次索引的column 1 -> column 2 -> rowId -> data

    因此,为纠正本节开头的引号,真正“存储” rowId的唯一索引是集群表上的辅助索引。

    虽然在聚簇表上的二级索引查找要比在非聚簇表上的查找慢,但如果使用短主键,则通常可以忽略不计。 集群表的主要优点之一是主索引查找速度更快,因此,如果您主要使用主键查找,那么它们将是有益的。

针对KutaBeach的评论:

提取不需要的列无济于事。 当服务器需要获取数据以获取不在索引中的行时,它并不总是获取该行的所有数据。 一些存储配置会存储一些与主行分开的数据,因为这些数据可能非常大,并且会影响性​​能。 例如TEXT列,每一行的长度为65535个字符。 如果存储引擎将数据存储在页面外,则在不需要TEXT列的情况下从行中获取数据要快得多。

这听起来像是说rowId ,是指行的物理地址,而不是分配给每行的唯一编号。 在这种情况下,您正确的是,只有群集表上的二级索引不存储rowId 所有其他索引都存储rowId 但是,这不是因为数据可以移动也不能移动。 表中的数据可以随时移动,在这种情况下,索引会更新以反映移动。 在MySQL中, PRIMARY INDEX基本上只是表的主要索引。 它与UNIQUE索引几乎相同,因为它强制值是唯一的,唯一的区别是它被用作表的主键。 非聚集索引确实包含每个rowId

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM