在左表或右表的连接字段上建立索引对左、内连接的查询效率的优化情况分析
-- 1、建表
drop table if exists dept_tbl;create table dept_tbl (rcrd_id int unsigned primary key auto_increment comment '記錄編號', dept_id int unsigned not null comment '部門編號') engine = innodb default charset=utf8 comment '部門表';drop table if exists emp_tbl;create table emp_tbl (rcrd_id int unsigned primary key auto_increment comment '記錄編號', emp_id int unsigned not null comment '員工編號', dept_id int unsigned comment '部門編號') engine = innodb default charset=utf8 comment '員工表';-- 2、造數據;
insert into dept_tbl(dept_id) values (floor(1+(rand()*20)));insert into dept_tbl(dept_id) values (floor(1+(rand()*20)));insert into dept_tbl(dept_id) values (floor(1+(rand()*20)));insert into dept_tbl(dept_id) values (floor(1+(rand()*20)));insert into dept_tbl(dept_id) values (floor(1+(rand()*20)));insert into dept_tbl(dept_id) values (floor(1+(rand()*20)));insert into dept_tbl(dept_id) values (floor(1+(rand()*20)));insert into dept_tbl(dept_id) values (floor(1+(rand()*20)));insert into dept_tbl(dept_id) values (floor(1+(rand()*20)));insert into dept_tbl(dept_id) values (floor(1+(rand()*20)));insert into emp_tbl(emp_id, dept_id) values (floor(1+(rand()*10000)), floor(1+(rand()*50)));insert into emp_tbl(emp_id, dept_id) values (floor(1+(rand()*10000)), floor(1+(rand()*50)));insert into emp_tbl(emp_id, dept_id) values (floor(1+(rand()*10000)), floor(1+(rand()*50)));insert into emp_tbl(emp_id, dept_id) values (floor(1+(rand()*10000)), floor(1+(rand()*50)));insert into emp_tbl(emp_id, dept_id) values (floor(1+(rand()*10000)), floor(1+(rand()*50)));insert into emp_tbl(emp_id, dept_id) values (floor(1+(rand()*10000)), floor(1+(rand()*50)));insert into emp_tbl(emp_id, dept_id) values (floor(1+(rand()*10000)), floor(1+(rand()*50)));insert into emp_tbl(emp_id, dept_id) values (floor(1+(rand()*10000)), floor(1+(rand()*50)));insert into emp_tbl(emp_id, dept_id) values (floor(1+(rand()*10000)), floor(1+(rand()*50)));insert into emp_tbl(emp_id, dept_id) values (floor(1+(rand()*10000)), floor(1+(rand()*50)));-- 3、查看索引
?
?
-- 4、左連接
-- 4.1、在左右表的連接字段dept_id上均未建索引的情況下,測試其掃描類型type和掃描行數rows
explainselect a.rcrd_id, a.dept_id, b.rcrd_id, b.emp_id, b.dept_idfrom dept_tbl aleft join emp_tbl bon a.dept_id = b.dept_id-- 【結論4.1】 在左右表的連接字段dept_id上均未建索引的情況下:左連接使用全表掃描的方式查詢左右表;
?
-- 4.2、僅在左表連接字段dept_id上建索引,測試左連接的掃描類型type和掃描行數rows
alter table dept_tbladd key `idx_dept_id` (`dept_id`);explainselect a.rcrd_id, a.dept_id, b.rcrd_id, b.emp_id, b.dept_idfrom dept_tbl aleft join emp_tbl bon a.dept_id = b.dept_id;--【結論4.2】僅在左表連接字段dept_id上建索引: a表使用了覆蓋索引掃描,但掃描行數沒變,查詢效率得到優化;b表使用了全表掃描,且掃描行數沒變,查詢效率未得到優化;
?
-- 4.3、僅在右表連接字段dept_id上建索引,測試左連接的掃描類型type和掃描行數rows
alter table dept_tbldrop key `idx_dept_id`;alter table emp_tbladd key `idx_dept_id` (`dept_id`);explainselect a.rcrd_id, a.dept_id, b.rcrd_id, b.emp_id, b.dept_idfrom dept_tbl aleft join emp_tbl bon a.dept_id = b.dept_id;--【結論4.3】僅在右表連接字段dept_id上建索引: 對右表b上的連接字段建立索引的查詢效率優化情況如下:
a表使用了全表掃描,掃描行數沒變;b表使用了非唯一性索引單值掃描ref, 且掃描行數為15;對a表的查詢效率沒有優化,但b表卻優化了;
?
-- 4.4、在左表和右表的連接字段dept_id上都建索引,測試左連接的掃描類型type和掃描行數rows
alter table dept_tbladd key `idx_dept_id` (`dept_id`);alter table emp_tbladd key `idx_dept_id` (`dept_id`);explainselect a.rcrd_id, a.dept_id, b.rcrd_id, b.emp_id, b.dept_idfrom dept_tbl aleft join emp_tbl bon a.dept_id = b.dept_id;-- 【結論4.4】在左表a和右表b的連接字段dept_id上都建索引后: a表使用了覆蓋索引掃描,但掃描行數沒變;b表使用了非唯一性索引單值掃描ref,掃描行數減少,查詢效率得到優化;
?
-- 5、內連接
-- 5.0 查看索引
?
?
-- 5.1、在左右表的連接字段dept_id上均未建索引的情況下,測試其掃描類型type和掃描行數rows
explainselect a.rcrd_id, a.dept_id, b.rcrd_id, b.emp_id, b.dept_idfrom dept_tbl ainner join emp_tbl bon a.dept_id = b.dept_id;-- 【結論5.1】在左右表上的連接字段均不建索引:a表使用了全表掃描,且總行數100條;b表使用了全表掃描,其總行數700條,這時的查詢效率最低;
?
-- 5.2、僅在左表連接字段dept_id上建索引,測試內連接的掃描類型type和掃描行數rows
alter table dept_tbladd key `idx_dept_id` (`dept_id`);explainselect a.rcrd_id, a.dept_id, b.rcrd_id, b.emp_id, b.dept_idfrom dept_tbl ainner join emp_tbl bon a.dept_id = b.dept_id;-- 【結論5.2】 僅在左表連接字段上建索引:?a表使用了覆蓋索引掃描,掃描行數為2條,掃描行數減少;b表使用了全表掃描,掃描行數700條,掃描行數沒變;故在左表a的連接字段建立索引后,a表的查詢效率得到優化;
b表的查詢效率沒有得到優化;
?
-- 5.3、僅在右表emp_tbl的連接字段dept_id上建索引,測試內連接的掃描類型type和掃描行數rows
alter table dept_tbldrop key `idx_dept_id`;alter table emp_tbladd key `idx_dept_id` (`dept_id`);explainselect a.rcrd_id, a.dept_id, b.rcrd_id, b.emp_id, b.dept_idfrom dept_tbl ainner join emp_tbl bon a.dept_id = b.dept_id;-- 【結論5.3】僅在右表emp_tbl,即b表的連接字段dept_id上建索引: a表使用了全表掃描,掃描行數100條,查詢效率未優化; b表使用了非唯一性索引單值掃描,掃描行數15條,查詢效率得到優化;故在右表b的連接字段建立索引后,a表的查詢效率沒有得到優化;b表的查詢效率得到優化;
?
-- 5.4、在左表和右表的連接字段上都建索引,測試內連接的掃描類型type和掃描行數rows
alter table dept_tbladd key `idx_dept_id` (`dept_id`);alter table emp_tbladd key `idx_dept_id` (`dept_id`);explainselect a.rcrd_id, a.dept_id as a_dept_id, b.rcrd_id, b.emp_id, b.dept_id as b_dept_idfrom dept_tbl ainner join emp_tbl bon a.dept_id = b.dept_id;-- 【結論5.4】 在左表和右表的連接字段上都建索引:?左表即a表使用了覆蓋索引,掃描行數100條,查詢效率得到優化;?右表即b表使用了非唯一性索引掃描,掃描行數14條,查詢效率得到優化;
?
【總結論】
1、對于左連接:
- 1.1、在左表和右表的連接字段上都不建立索引:左右表都是全表掃描,查詢效率最低;
- 1.2、僅在左表的連接字段上建立索引:左表使用了覆蓋索引掃描,掃描行數沒變,查詢效率得到優化;b表使用了全表掃描,且掃描行數沒變,查詢效率未得到優化;
- 1.3、僅在右表連接字段上建索引: 左表表使用了全表掃描,掃描行數沒變,查詢效率未得到優化;右表使用了非唯一性索引單值掃描ref,掃描行數減少,查詢曉得得到優化;
- 1.4、在左表和右表的連接字段上都建索引后: 左表使用了覆蓋索引掃描,掃描行數沒變,查詢效率得到優化;右表使用了非唯一性索引單值掃描ref,掃描行數減少,查詢效率得到優化;?
2、對于內連接
- 2.1、在左表和右表的連接字段上都不建立索引:左右表都是全表掃描,查詢效率最低;
- 2.2、僅在左表的連接字段上建立索引: 左表使用了覆蓋索引掃描,掃描行數減少,查詢效率得到優化;右表使用了全表掃描,掃描行數沒變,查詢效率沒有得到優化;
- 2.3、僅在右表連接字段上建索引: 左表使用了全表掃描,掃描行數沒變,查詢效率未優化; 右表使用了非唯一性索引單值掃描,掃描行數減少,查詢效率得到優化;
- 2.4、在左表a和右表b的連接字段上都建索引后:左表使用了覆蓋索引,掃描行數不變,查詢效率得到優化;右表使用了非唯一性索引掃描,掃描行數減少,查詢效率得到優化;
3、全文總結論:
【關于左連接的結論補充】
- 補充1:由于非唯一性索引單值掃描ref 的查詢效率高于索引掃描index的查詢效率, 所以左連接建議優先在右表的連接字段添加索引,當然最好是左表也加上;
- 補充2:還有一個本質問題是左連接時左表是主表,無論右表如何,左表的記錄都會出現在查詢結果中,即無論索引怎么建立,都要遍歷左表的所有記錄行數;
?
?
總結
以上是生活随笔為你收集整理的在左表或右表的连接字段上建立索引对左、内连接的查询效率的优化情况分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 腾讯会议有回音怎么解决(电脑腾讯会议有回
- 下一篇: 台式电脑配置守望先锋(守望先锋电脑最低配