标签:为什么 name phone 推荐 主键 索引 InnoDB id select
为什么不推荐select * from
1. 不必要的磁盘I/O
对于无用的大字段,如 varchar、blob、text,会增加 io 操作,准确来说,长度超过 728 字节的时候,会先把超出的数据序列化到另外一个地方,因此读取这条记录会增加一次 io 操作。(MySQL InnoDB)
2. 不需要的列会增加数据传输时间和网络开销
保不住真的有人用*把TEXT
、MEDIUMTEXT
或者BLOB
类型的字段也查出来了,总数据量大了,这就直接导致网络传输的次数变多了。
3. 无法使用覆盖索引
为了说明这个问题,我们需要建一个表
CREATE TABLE `user_innodb` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `gender` tinyint(1) DEFAULT NULL, `phone` varchar(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `IDX_NAME_PHONE` (`name`,`phone`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
我们创建了一个存储引擎为InnoDB的表user_innodb
,并设置id
为主键,另外为name
和phone
创建了联合索引,最后向表中随机初始化了500W+条数据。
InnoDB会自动为主键id
创建一棵名为主键索引(又叫做聚簇索引)的B+树,这个B+树的最重要的特点就是叶子节点包含了完整的用户记录,大概长这个样子。
如果我们执行这个语句
SELECT * FROM user_innodb WHERE name = '蝉沐风';
使用EXPLAIN
查看一下语句的,发现这个SQL语句会使用到IDX_NAME_PHONE
索引,
这是一个二级索引。二级索引的叶子节点长这个样子:
InnoDB存储引擎会根据搜索条件在该二级索引的叶子节点中找到name
为蝉沐风
的记录,但是二级索引中只记录了name
、phone
和主键id
字段(谁让我们用的是SELECT *
呢),因此InnoDB需要拿着主键id
去主键索引中查找这一条完整的记录,这个过程叫做回表。
想一下,如果二级索引的叶子节点上有我们想要的所有数据,是不是就不需要回表了呢?是的,这就是覆盖索引。
举个例子,我们恰好只想搜索name
、phone
以及主键字段。
SELECT name, phone FROM user_innodb WHERE name = "蝉沐风";
会显示Using index
,表示我们的查询列表以及搜索条件中只包含属于某个索引的列,也就是使用了覆盖索引,能够直接摒弃回表操作,大幅度提高查询效率。
标签:为什么,name,phone,推荐,主键,索引,InnoDB,id,select 来源: https://www.cnblogs.com/karrya/p/16215382.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。