crossoverJie / crossoverJie/JCSprout

关于【SQL优化】中-【不要让数据库帮我们做强制类型转换】和【如果需要进行 join 的字段两表的字段类型要相同】的一点疑问

Open
#180 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
26.8k
Forks
7k
PR merge metrics
No merged PRs in 30d

Description

**在提交issue之前请回答以下问题,谢谢!**

> 建议首先查看是否已经有类似的 Issues (提交时可删除该提示)

### 你使用的是哪个版本

版本信息:mysql Ver 14.14 Distrib 5.7.23, for macos10.13 (x86_64) using EditLine wrapper

### 预期结果
1. 【不要让数据库帮我们做强制类型转换】,该结论不严谨
2. 【如果需要进行 join 的字段两表的字段类型要相同】,该结论有问题

### 实际结果
1. 【不要让数据库帮我们做强制类型转换】,该结论不严谨
> 结论:隐式转换,where column_name=2 id是字符串类型,相当于使用字符串转整型,不用索引;而整数转字符串会用到索引
2. 【如果需要进行 join 的字段两表的字段类型要相同】,该结论有问题
> 结论:关联查询中,关联字段如果没有索引,会导致后面的索引都失效

以下是我测试中用到的sql
```
-- =========================================隐式转换测试=====================================
-- 建表
CREATE TABLE `user` (
`id` int(11) unsigned NOT NULL auto_increment,
`age` int(3) NOT NULL,
`user_name` varchar(16) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4;
-- 插入数据
insert into user (age,user_name) value(23,'13000001111');
insert into user (age,user_name)values(24,'13000001112');
insert into user (age,user_name)values(25,'13000001113');
insert into user (age,user_name)values(26,'13000001114');
insert into user (age,user_name)values(27,'13000001115');

-- 添加索引
alter table user add index idx_user_name (user_name);
-- 添加索引
alter table user add index idx_age (age);

-- user_name是字符串类型,这里不是用索引,extra的结果是Using where
explain
SELECT * from user where user_name = 13000001115;

-- user_name是字符串类型,这里用索引,extra的结果是null
explain
SELECT * from user where user_name = '13000001115';

-- age是整型,这里可以用索引,extra的结果是null
explain
SELECT * from user where age = '23';

-- age是整型,这里可以用索引,extra的结果是null
explain
SELECT * from user where age = 23;

结论:隐式转换,where column_name=2 id是字符串类型,相当于使用字符串转整型,不用索引;而整数转字符串会用到索引

-- =========================================join测试=====================================
-- 建表
CREATE TABLE `user2` (
`id` int(11) unsigned NOT NULL auto_increment,
`age` varchar(3) NOT NULL,
`phone` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4;
-- 插入数据
insert into user2 (age,phone) value('23',130001111);
insert into user2 (age,phone)values('24',130001112);
insert into user2 (age,phone)values('25',130001113);
insert into user2 (age,phone)values('26',130001114);
insert into user2 (age,phone)values('27',130001115);

-- 添加索引
alter table user2 add index idx_phone (phone);
-- 添加索引
alter table user2 add index idx_age (age);
-- 删除user2 age索引
drop index idx_age on user2;

-- ========== 有索引测试
-- 有索引Using where; Using index; Using join buffer (Block Nested Loop)
explain
SELECT u1.* from user u1 left join user2 u2 on u1.age = u2.age;

-- 有索引Using where; Using index
explain
SELECT u1.* from user u1 left join user2 u2 on u1.age = u2.age where u1.id = 1;
-- ========== 没有索引测试
-- user2.age没有索引 Using where; Using join buffer (Block Nested Loop)
explain
SELECT u1.* from user u1 left join user2 u2 on u1.age = u2.age;

-- user2.age没有索引 Using where
explain
SELECT u1.* from user u1 left join user2 u2 on u1.age = u2.age where u1.id = 1;

结论:关联查询中,关联字段如果没有索引,会导致后面的索引都失效
```
**Using where; Using index的释意:**
- using index,查询时不需要回表查询,直接通过索引就可以获得数据;如果同时出现了using where表示索引用来执行查找值,没有出现using where说明索引是用来读取数据的;效率不错

- using where,出现这个表示数据在server层过滤,反之是存储引擎存过滤;效率较低

### 其他相关信息
建议:MySQL部分结论受版本影响,有争议的建议注明版本

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the SQL optimization section referenced by the issue and reproduce its implicit-conversion and JOIN EXPLAIN statements on MySQL 5.7.23. Compare the observed index behavior with the two stated conclusions, then update the documentation with precise, version-specific caveats and verify the revised examples.

Written by the indexing model from the issue text.

Assessment

Tech stack
mysql
Domain
databases
Issue type
Documentation
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.