MySQL中的隐藏列的具体查看
查看mysql索引⽬录
1、存在主键
2、⽆主键,存在唯⼀索引
3、存在联合主键或联合唯⼀索引
4、存在多个唯⼀索引
5、同时存在主键与唯⼀索引
6、⽆符合条件的主键与唯⼀索引
在介绍mysql的多版本并发控制mvcc的过程中,我们提到过mysql中存在⼀些隐藏列,例如⾏标识、事务ID、回滚指针等,不知道⼤家是否和我⼀样好奇过,要怎样才能实际地看到这些隐藏列的值呢?
本⽂我们就来重点讨论⼀下诸多隐藏列中的⾏标识DB_ROW_ID,实际上,将⾏标识称为隐藏列并不准确,因为它并不是⼀个真实存在的列,DB_ROW_ID实际上是⼀个⾮空唯⼀列的别名。在拨开它的神秘⾯
纱之前,我们看⼀下官⽅⽂档的说明:
If a table has a PRIMARY KEY or UNIQUE NOT NULL index that consists of a single column that has an integer type,
you can use _rowid to refer to the indexed column in SELECT statements
简单翻译⼀下,如果在表中存在主键或⾮空唯⼀索引,并且仅由⼀个整数类型的列构成,那么就可以使⽤SELECT语句直接查询_rowid,并且这个_rowid的值会引⽤该索引列的值。
着重看⼀下⽂档中提到的⼏个关键字,主键、唯⼀索引、⾮空、单独⼀列、数值类型,接下来我们就要从这些⾓度⼊⼿,探究⼀下神秘的隐藏字段_rowid。
1、存在主键
先看设置了主键且是数值类型的情况,使⽤下⾯的语句建表:
CREATE TABLE `table1` (
`id` bigint(20) NOT NULL PRIMARY KEY ,
`name` varchar(32) DEFAULT NULL
) ENGINE=InnoDB;
插⼊三条测试数据后,执⾏下⾯的查询语句,在select查询语句中直接查询_rowid:
select *,_rowid from table1
查看执⾏结果,_rowid可以被正常查询:
可以看到在设置了主键,并且主键字段是数值类型的情况下,_rowid直接引⽤了主键字段的值。对于这种可以被select语句查询到的的情况,可以将其称为显式的rowid。
回顾⼀下前⾯提到的⽂档中的⼏个关键字,分别对其进⾏分析。由于主键必定是⾮空字段,下⾯来看⼀下主键是⾮数值类型字段的情况,建表如下:
CREATE TABLE `table2` (
`id` varchar(20) NOT NULL PRIMARY KEY ,
`name` varchar(32) DEFAULT NULL
) ENGINE=InnoDB;
在table2执⾏上⾯相同的查询,结果报错⽆法查询_rowid,也就证明了如果主键字段是⾮数值类型,那么将⽆法直接查询_rowid。
2、⽆主键,存在唯⼀索引
上⾯对两种类型的主键进⾏了测试后,接下来我们看⼀下当表中没有主键、但存在唯⼀索引的情况。⾸先测试⾮空唯⼀索引加在数值类型字段的情况,建表如下:
CREATE TABLE `table3` (
`id` bigint(20) NOT NULL UNIQUE KEY,
`name` varchar(32)
)
ENGINE=InnoDB;
查询可以正常执⾏,并且_rowid引⽤了唯⼀索引所在列的值:
唯⼀索引与主键不同的是,唯⼀索引所在的字段可以为NULL。在上⾯的table3中,在唯⼀索引所在的列上添加了NOT NULL⾮空约束,如果我们把这个⾮空约束删除掉,还能显式地查询到_rowid吗?下⾯再创建⼀个表,不同是在唯⼀索引所在的列上,不添加⾮空约束:
CREATE TABLE `table4` (
`id` bigint(20) UNIQUE KEY,
`name` varchar(32)
) ENGINE=InnoDB;
执⾏查询语句,在这种情况下,⽆法显式地查询到_rowid:
和主键类似的,我们再对唯⼀索引被加在⾮数值类型的字段的情况进⾏测试。下⾯在建表时将唯⼀索引添加在字符类型的字段上,并添加⾮空约束:
CREATE TABLE `table5` (
`id` bigint(20),
`name` varchar(32) NOT NULL UNIQUE KEY
) ENGINE=InnoDB;
同样⽆法显⽰的查询到_rowid:
针对上⾯三种情况的测试结果,可以得出结论,当没有主键、但存在唯⼀索引的情况下,只有该唯⼀索引被添加在数值类型的字段上,且该字段添加了⾮空约束时,才能够显式地查询到_rowid,并且_rowid引⽤了这个唯⼀索引字段的值。
3、存在联合主键或联合唯⼀索引
在上⾯的测试中,我们都是将主键或唯⼀索引作⽤在单独的⼀列上,那么如果使⽤了联合主键或联合唯⼀索引时,结果会如何呢?还是先看⼀下官⽅⽂档中的说明:
_rowid refers to the PRIMARY KEY column if there is a PRIMARY KEY consisting of a single integer c
olumn. If there is a PRIMARY KEY but it does not consist of a single integer column, _rowid cannot be used.
简单来说就是,如果主键存在、且仅由数值类型的⼀列构成,那么_rowid的值会引⽤主键。如果主键是由多列构成,那
么_rowid将不可⽤。
根据这⼀描述,我们测试⼀下联合主键的情况,下⾯将两列数值类型字段作为联合主键建表:
CREATE TABLE `table6` (
`id` bigint(20) NOT NULL,
`no` bigint(20) NOT NULL,
`name` varchar(32),
PRIMARY KEY(`id`,`no`)
) ENGINE=InnoDB;
执⾏结果⽆法显⽰的查询到_rowid:
同样,这⼀理论也可以作⽤于唯⼀索引,如果⾮空唯⼀索引不是由单独⼀列构成,那么也⽆法直接查询得到_rowid。这⼀测试过程省略,有兴趣的⼩伙伴可以⾃⼰动⼿试试。
4、存在多个唯⼀索引
在mysql中,每张表只能存在⼀个主键,但是可以存在多个唯⼀索引。那么如果同时存在多个符合规则的唯⼀索引,会引⽤哪个作为_rowid的值呢?⽼规矩,还是看官⽅⽂档的解答:
Otherwise, _rowid refers to the column in the first UNIQUE NOT NULL index if that index consists of a single integer
column. If the first UNIQUE NOT NULL index does not consist of a single integer column, _rowid cannot be used.
简单翻译⼀下,如果表中的第⼀个⾮空唯⼀索引仅由⼀个整数类型字段构成,那么_rowid会引⽤这个字段的值。否则,如果第⼀个⾮空唯⼀索引不满⾜这种情况,那么_rowid将不可⽤。
在下⾯的表中,创建两个都符合规则的唯⼀索引:
CREATE TABLE `table8_2` (
`id` bigint(20) NOT NULL,
`no` bigint(20) NOT NULL,
`name` varchar(32),
UNIQUE KEY(no),
UNIQUE KEY(id)
) ENGINE=InnoDB;
看⼀下执⾏查询语句的结果:
可以看到_rowid的值与no这⼀列的值相同,证明了_rowid会严格地选取第⼀个创建的唯⼀索引作为它的引⽤。
那么,如果表中创建的第⼀个唯⼀索引不符合_rowid的引⽤规则,第⼆个唯⼀索引满⾜规则,这种情况下,_rowid可以被显⽰地查询吗?针对这种情况我们建表如下,表中的第⼀个索引是联合唯⼀索引,第⼆个索引才是单列的唯⼀索引情况,再来进⾏⼀下测试:
CREATE TABLE `table9` (
`id` bigint(20) NOT NULL,
`no` bigint(20) NOT NULL,
`name` varchar(32),
UNIQUE KEY `index1`(`id`,`no`),
UNIQUE KEY `index2`(`id`)
) ENGINE=InnoDB;
进⾏查询,可以看到虽然存在⼀个单列的⾮空唯⼀索引,但是因为顺序选取的第⼀个不满⾜要求,因此仍然不能直接查
询_rowid:
如果将上⾯创建唯⼀索引的语句顺序调换,那么将可以正常显式的查询到_rowid。
5、同时存在主键与唯⼀索引
从上⾯的例⼦中,可以看到唯⼀索引的定义顺序会决定将哪⼀个索引应⽤_rowid,那么当同时存在主键和唯⼀索引时,定义顺序会对其引⽤造成影响吗?
按照下⾯的语句创建两个表,只有创建主键和唯⼀索引的顺序不同:
CREATE TABLE `table11` (
`id` bigint(20) NOT NULL,
`no` bigint(20) NOT NULL,
PRIMARY KEY(id),
UNIQUE KEY(no)
) ENGINE=InnoDB;
CREATE TABLE `table12` (
`id` bigint(20) NOT NULL,
`no` bigint(20) NOT NULL,
UNIQUE KEY(id),
PRIMARY KEY(no)
) ENGINE=InnoDB;
查看运⾏结果:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论