成人性生交大片免费看视频r_亚洲综合极品香蕉久久网_在线视频免费观看一区_亚洲精品亚洲人成人网在线播放_国产精品毛片av_久久久久国产精品www_亚洲国产一区二区三区在线播_日韩一区二区三区四区区区_亚洲精品国产无套在线观_国产免费www

主頁 > 知識庫 > MySQL復合索引的深入探究

MySQL復合索引的深入探究

熱門標簽:外呼系統(tǒng)打電話上限是多少 南昌三維地圖標注 地圖標注費用是多少 曲靖移動外呼系統(tǒng)公司 武漢網(wǎng)絡(luò)外呼系統(tǒng)服務(wù)商 百應(yīng)電話機器人優(yōu)勢 電話外呼系統(tǒng)改號 怎樣在地圖標注銷售區(qū)域 啥是企業(yè)400電話辦理

復合索引(又稱為聯(lián)合索引),是在多個列上創(chuàng)建的索引。創(chuàng)建復合索引最重要的是列順序的選擇,這關(guān)系到索引能否使用上,或者影響多少個謂詞條件能使用上索引。復合索引的使用遵循最左匹配原則,只有索引左邊的列匹配到,后面的列才能繼續(xù)匹配。本文主要探究復合索引的創(chuàng)建順序與使用情況。 

(一)復合索引的概念

在單個列上創(chuàng)建的索引我們稱為單列索引,在2個以上的列上創(chuàng)建的索引稱為復合索引。在單個列上創(chuàng)建索引相對簡單,通常只需要考慮列的選擇率即可,選擇性越好,代表數(shù)據(jù)越分散,創(chuàng)建出來的索引性能也就更好。通常,某列選擇率的計算公式為:
selectivity = 施加謂詞條件后返回的記錄數(shù) / 未施加謂詞條件后返回的記錄數(shù)
可選擇率的取值范圍是(0,1],值越小,代表選擇性越好。
對于復合索引(又稱為聯(lián)合索引),是在多個列上創(chuàng)建的索引。創(chuàng)建復合索引最重要的是列順序的選擇,這關(guān)系到索引能否使用上,或者影響多少個謂詞條件能使用上索引。復合索引的使用遵循最左匹配原則,只有索引左邊的列匹配到,后面的列才能繼續(xù)匹配。

(二)什么情況下會使用復合索引的列

復合索引遵循最左匹配原則,只有索引中最左列匹配到,下一列才有可能被匹配。如果左邊列使用的是非等值查詢,則索引右邊的列將不會被查詢使用,也不會被排序使用。

實驗:哪些情況下會使用到復合索引

 復合索引中的哪些字段被使用到了,是我們非常關(guān)心的問題。網(wǎng)絡(luò)上一個經(jīng)典的例子:

-- 創(chuàng)建測試表
CREATE TABLE t1(
c1 CHAR(1) not null,
c2 CHAR(1) not null,
c3 CHAR(1) not null,
c4 CHAR(1) not null,
c5 CHAR(1) not null
)ENGINE innodb CHARSET UTF8;

-- 添加索引
alter table t1 add index idx_c1234(c1,c2,c3,c4);

--插入測試數(shù)據(jù)
insert into t1 values('1','1','1','1','1'),('2','2','2','2','2'),
('3','3','3','3','3'),('4','4','4','4','4'),('5','5','5','5','5');

 需要探索下面哪些查詢語句使用到了索引idx_c1234,以及使用到了索引的哪些字段?

(A) where c1=? and c2=? and c4>? and c3=?

(B) where c1=? and c2=? and c4=? order by c3

(C) where c1=? and c4=? group by c3,c2

(D) where c1=? and c5=? order by c2,c3

(E) where c1=? and c2=? and c5=? order by c2,c3

(F) where c1>? and c2=? and c4>? and c3=?

A選項:

mysql> explain select c1,c2,c3,c4,c5 from t1 where c1='2' and c2='2' and c4>'1' and c3='2';
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref | rows | filtered | Extra     |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------+
| 1 | SIMPLE  | t1 | NULL  | range | idx_c1234  | idx_c1234 | 12  | NULL | 1 | 100.00 | Using index condition |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------+

使用的索引長度為12,代表4個字段都使用了索引。由于c1、c2、c3都是等值查詢,所以后面的c4列也可以用上。

注:utf8編碼,一個索引長度為3,這里12代表4個字段都用到該索引。

B選項:

mysql> explain select c1,c2,c3,c4,c5 from t1 where c1='2' and c2='2' and c4='2' order by c3;
+----+-------------+-------+------------+------+---------------+-----------+---------+-------------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref   | rows | filtered | Extra     |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------------+------+----------+-----------------------+
| 1 | SIMPLE  | t1 | NULL  | ref | idx_c1234  | idx_c1234 | 6  | const,const | 1 | 20.00 | Using index condition |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------------+------+----------+-----------------------+

 使用的索引長度為6,代表2個字段使用了索引。根據(jù)最左使用原則,c1、c2使用了索引。因為查詢中沒有c3謂詞條件,所以索引值使用到c2后就發(fā)生了中斷,導致只使用了c1、c2列。這里SQL使用了order by排序,但是在執(zhí)行計劃Extra部分未有filesort關(guān)鍵字,說明在索引中按照c3字段順序讀取數(shù)據(jù)即可。

這里特別留意,雖然索引中的c3字段沒有放在索引的最后,但是確實使用到了索引中c2字段的有序特性,因為執(zhí)行計劃的Extra部分未出現(xiàn)"fileasort"關(guān)鍵字。這是為什么呢?這里用到了MySQL5.6版本引入的Index Condition Pushdown (ICP) 優(yōu)化。其核心思想是使用索引中的字段做數(shù)據(jù)過濾。我們來整理一下不使用ICP和使用ICP的區(qū)別:

如果沒有使用ICP優(yōu)化,其SQL執(zhí)行步驟為:

1.使用索引列c1,c2獲取滿足條件的行數(shù)據(jù)。where c1='2' and c2='2'

2.回表查詢數(shù)據(jù),使用where c4='2'來過濾數(shù)據(jù)

3.對數(shù)據(jù)排序輸出

如果使用了ICP優(yōu)化,其SQL執(zhí)行步驟為:

1.使用索引列c1,c2獲取滿足條件的行數(shù)據(jù)。where c1='2' and c2='2'

2.在索引中使用where c4='2'來過濾數(shù)據(jù)

3.因為數(shù)據(jù)有序,直接按順序取出滿足條件的數(shù)據(jù)

C選項:

mysql> explain select c2,c3 from t1 where c1='2' and c4='2' group by c3,c2;
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-----------------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref | rows | filtered | Extra              |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-----------------------------------------------------------+
| 1 | SIMPLE  | t1 | NULL  | ref | idx_c1234  | idx_c1234 | 3  | const | 2 | 14.29 | Using where; Using index; Using temporary; Using filesort |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-----------------------------------------------------------+

 使用的索引長度為3,代表1個字段使用了索引。根據(jù)最左使用原則,c1使用了索引。因為查詢中沒有c2謂詞條件,所以索引值使用到c1后就發(fā)生了中斷,導致只使用了c1列。該SQL執(zhí)行過程為:

1.在c1列使用索引找到c1='2'的所有行,然后回表使用c4='2'過濾掉不匹配的數(shù)據(jù)
2.根據(jù)上一步的結(jié)果,對結(jié)果中的c3,c2聯(lián)合排序,以便于得到連續(xù)變化的數(shù)據(jù),同時在數(shù)據(jù)庫內(nèi)部創(chuàng)建臨時表,用于存儲group by的結(jié)果。

C選項擴展:

mysql> explain select c2,c3 from t1 where c1='2' and c4='2' group by c2,c3;
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref | rows | filtered | Extra     |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+--------------------------+
| 1 | SIMPLE  | t1 | NULL  | ref | idx_c1234  | idx_c1234 | 3  | const | 2 | 14.29 | Using where; Using index |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+--------------------------+

 使用的索引長度為3,代表1個字段使用了索引。根據(jù)最左使用原則,c1使用了索引。

D選項:

mysql> explain select c2,c3 from t1 where c1='2' and c5='2' order by c2,c3;
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref | rows | filtered | Extra        |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+------------------------------------+
| 1 | SIMPLE  | t1 | NULL  | ref | idx_c1234  | idx_c1234 | 3  | const | 2 | 14.29 | Using index condition; Using where |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+------------------------------------+

 使用的索引長度為3,代表1個字段都使用了索引。根據(jù)最左使用原則,c1使用了索引。因為查詢中沒有c2謂詞條件,所以索引值使用到c1后就發(fā)生了中斷,導致只使用了c1列。

D選項擴展:

mysql> explain select c2,c3 from t1 where c1='2' and c5='2' order by c3,c2;
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+----------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref | rows | filtered | Extra            |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+----------------------------------------------------+
| 1 | SIMPLE  | t1 | NULL  | ref | idx_c1234  | idx_c1234 | 3  | const | 2 | 14.29 | Using index condition; Using where; Using filesort |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+----------------------------------------------------+

 使用的索引長度為3,代表1個字段都使用了索引。根據(jù)最左使用原則,c1使用了索引。因為查詢中沒有c2謂詞條件,所以索引值使用到c1后就發(fā)生了中斷,導致只使用了c1列。

E選項:

mysql> explain select c1,c2,c3,c4,c5 from t1 where c1='2' and c2='2' and c5='2' order by c2,c3;
+----+-------------+-------+------------+------+---------------+-----------+---------+-------------+------+----------+------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref   | rows | filtered | Extra        |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------------+------+----------+------------------------------------+
| 1 | SIMPLE  | t1 | NULL  | ref | idx_c1234  | idx_c1234 | 6  | const,const | 2 | 14.29 | Using index condition; Using where |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------------+------+----------+------------------------------------+

 使用的索引長度為6,代表2個字段都使用了索引。根據(jù)最左使用原則,c1、c2使用了索引。這里SQL使用了order by排序,但是在執(zhí)行計劃Extra部分未有filesort關(guān)鍵字,說明在索引中按照c3字段順序讀取數(shù)據(jù)即可(c2是常量)。

F選項:

mysql> explain select c1,c2,c3,c4,c5 from t1 where c1>'4' and c2='2' and c3='2' and c4='1';
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref | rows | filtered | Extra     |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------+
| 1 | SIMPLE  | t1 | NULL  | range | idx_c1234  | idx_c1234 | 3  | NULL | 1 | 20.00 | Using index condition |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------+

 使用的索引長度為3,代表1個字段都使用了索引。根據(jù)最左使用原則,c1使用了索引。這里c1使用了不等值查詢,導致后面的c2查詢無法使用索引。該案例非常值得警惕,謂詞條件中含有等值查詢和范圍查詢時,如果范圍查詢在索引前面,則等值查詢將無法使用索引;如果等值查詢在前面,范圍查詢在后面,則都可以使用到索引。

(三)如何創(chuàng)建復合索引

復合索引創(chuàng)建的難點在于字段順序選擇,我的觀點如下:

  • 如果存在等值查詢和排序,則在創(chuàng)建復合索引時,將等值查詢字段放在前面,排序放在最后面;
  • 如果存在多個等值查詢,則選擇性好的放在前面,選擇性差的放在后面;
  • 如果存在等值查詢、范圍查詢、排序。等值查詢放在最前面,范圍查詢和排序需根據(jù)實際情況決定索引順序;

此外,《阿里巴巴Java開發(fā)手冊-2020最新嵩山版》中有幾個關(guān)于復合索引的規(guī)約,我們可以看一下:

1.如果有order by的場景,請注意利用索引的有序性。order by后的字段是組合索引的一部分,并且放在組合索引的最后,避免出現(xiàn)filesort的情況,影響查詢性能。

正例:where a=? b=? order by c; 索引a_b_c

反例:索引如果存在范圍查詢,那么索引有序性將無法使用。如:where a>10 order by b; 索引a_b無法排序。

2.建復合索引的時候,區(qū)分度最高的在最左邊,如果where a=? and b=?,a列的值幾乎接近唯一值,那么只需建單列索引idx_a即可。

說明:存在等號和非等號混合判斷條件時,在建索引時,請把等號條件的列前置。如:where c>? and d=?,那么即使c的區(qū)分度

更高,也必須把d放在索引的最前列,即創(chuàng)建索引idx_d_c。

實驗:應(yīng)該如何創(chuàng)建復合索引

在有的文檔里面講到過復合索引的創(chuàng)建規(guī)則:ESR原則:精確(Equal)匹配的字段放在最前面,排序(Sort)條件放中間,范圍(Range)匹配的字段放在最后面。接下來我們來探索一下該方法是否正確。

例子:存在員工表employees

mysql> show create table employees;
+-----------+-------------------------------
| Table  | Create Table                                                                   
+-----------+-------------------------------------
| employees | CREATE TABLE `employees` (
 `emp_no` int(11) NOT NULL,
 `birth_date` date NOT NULL,
 `first_name` varchar(14) NOT NULL,
 `last_name` varchar(16) NOT NULL,
 `gender` enum('M','F') NOT NULL,
 `hire_date` date NOT NULL,
 PRIMARY KEY (`emp_no`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+-----------+-------------------------------------

-- 數(shù)據(jù)量約30萬行
mysql> select count(*) from employees;
+----------+
| count(*) |
+----------+
| 300024 |
+----------+

 現(xiàn)在需要查詢1998年后入職的first_name為"Ebbe"員工,并按照出生日期升序排序。

其SQL語句如下:

select emp_no,birth_date,first_name,last_name,gender,hire_date 
from employees 
where hire_date >= '1998-01-01'
and  first_name = 'Ebbe'
order by birth_date;

 為了優(yōu)化該SQL語句的性能,需要在表上創(chuàng)建索引,為了保證where與order by都使用到索引,決定創(chuàng)建復合索引,有如下創(chuàng)建順序:

(A)hire_date,first_name,birth_date

(B)hire_date,birth_date,first_name

(C)first_name,hire_date,birth_date

(D)first_name,birth_date,hire_date

(E)birth_date,first_name,hire_date

(F)birth_date,hire_date,first_name

確認哪種順序創(chuàng)建索引是最優(yōu)的。

Note:

1.date類型占3個字節(jié)的空間,hire_date和 birth_date都占用3個字節(jié)的空間。

2.first_name是變長字段,多使用2個字節(jié),如果允許為NULL值,還需多使用1個字節(jié),占用16個字節(jié)

A選項:hire_date,first_name,birth_date

create index idx_a on employees(hire_date,first_name,birth_date);

其執(zhí)行計劃如下:

+----+-------------+-----------+------------+-------+---------------+-------+---------+------+------+----------+---------------------------------------+
| id | select_type | table  | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra         |
+----+-------------+-----------+------------+-------+---------------+-------+---------+------+------+----------+---------------------------------------+
| 1 | SIMPLE  | employees | NULL  | range | idx_a   | idx_a | 19  | NULL | 5678 | 10.00 | Using index condition; Using filesort |
+----+-------------+-----------+------------+-------+---------------+-------+---------+------+------+----------+---------------------------------------+

 這里key_len長度為19,令人不解,hire_date是非等值查詢,理論上key_len應(yīng)該為3,通過使用MySQL workbench查看執(zhí)行計劃,也可以發(fā)現(xiàn)索引只使用了hire_date列(如下圖)。為什么會是19而不是3呢?實在令人費解,思考了好久也沒有想明白,如有知道,望各位大神不吝解答。

 

B選項:hire_date,birth_date,first_name

為避免干擾,刪除上面創(chuàng)建的索引idx_a,然后創(chuàng)建idx_b。

create index idx_b on employees(hire_date,birth_date,first_name);

其執(zhí)行計劃如下:

+----+-------------+-----------+------------+-------+---------------+-------+---------+------+------+----------+---------------------------------------+
| id | select_type | table   | partitions | type | possible_keys | key  | key_len | ref | rows | filtered | Extra                 |
+----+-------------+-----------+------------+-------+---------------+-------+---------+------+------+----------+---------------------------------------+
| 1 | SIMPLE   | employees | NULL    | range | idx_b     | idx_b | 3    | NULL | 5682 |  10.00 | Using index condition; Using filesort |
+----+-------------+-----------+------------+-------+---------------+-------+---------+------+------+----------+---------------------------------------+

 這里key_len長度為3,hire_date是非等值查詢,導致后面的索引列無法使用到。

C選項:first_name,hire_date,birth_date

為避免干擾,刪除上面創(chuàng)建的索引idx_b,然后創(chuàng)建idx_c。

create index idx_c on employees(first_name,hire_date,birth_date);

其執(zhí)行計劃如下:

+----+-------------+-----------+------------+-------+---------------+-------+---------+------+------+----------+---------------------------------------+
| id | select_type | table   | partitions | type | possible_keys | key  | key_len | ref | rows | filtered | Extra                 |
+----+-------------+-----------+------------+-------+---------------+-------+---------+------+------+----------+---------------------------------------+
| 1 | SIMPLE   | employees | NULL    | range | idx_c     | idx_c | 19   | NULL |  5 |  100.00 | Using index condition; Using filesort |
+----+-------------+-----------+------------+-------+---------------+-------+---------+------+------+----------+---------------------------------------+

 這里key_len長度為19,first_name是等值查詢,可以繼續(xù)使用hire_date列,因為hire_date列是非等值查詢,導致索引無法繼續(xù)使用birth_date。

D選項:first_name,birth_date,hire_date

為避免干擾,刪除上面創(chuàng)建的索引idx_c,然后創(chuàng)建idx_d。

create index idx_d on employees(first_name,birth_date,hire_date);

其執(zhí)行計劃如下:

+----+-------------+-----------+------------+------+---------------+-------+---------+-------+------+----------+-----------------------+
| id | select_type | table   | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra         |
+----+-------------+-----------+------------+------+---------------+-------+---------+-------+------+----------+-----------------------+
| 1 | SIMPLE   | employees | NULL    | ref | idx_d     | idx_d | 16   | const | 190 |  33.33 | Using index condition |
+----+-------------+-----------+------------+------+---------------+-------+---------+-------+------+----------+-----------------------+

 這里key_len長度為16,first_name是等值查詢,在謂詞過濾中未使用birth_date,導致只有first_name列使用上索引,但是birth_date列用于排序,上面執(zhí)行計劃顯示SQL最終并沒有排序,說明數(shù)據(jù)是從索引按照birth_date有序取出的。

E選項:birth_date,first_name,hire_date

為避免干擾,刪除上面創(chuàng)建的索引idx_d,然后創(chuàng)建idx_e。

create index idx_e on employees(birth_date,first_name,hire_date);

其執(zhí)行計劃如下:

+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-----------------------------+
| id | select_type | table   | partitions | type | possible_keys | key | key_len | ref | rows  | filtered | Extra            |
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-----------------------------+
| 1 | SIMPLE   | employees | NULL    | ALL | NULL     | NULL | NULL  | NULL | 299468 |   3.33 | Using where; Using filesort |
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-----------------------------+

 這里未使用到索引,說明排序列放在復合索引的最前面是無法被使用到的。

F選項:birth_date,hire_date,first_name

為避免干擾,刪除上面創(chuàng)建的索引idx_e,然后創(chuàng)建idx_f。

create index idx_f on employees(birth_date,hire_date,first_name);

其執(zhí)行計劃如下:

+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-----------------------------+
| id | select_type | table   | partitions | type | possible_keys | key | key_len | ref | rows  | filtered | Extra            |
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-----------------------------+
| 1 | SIMPLE   | employees | NULL    | ALL | NULL     | NULL | NULL  | NULL | 299468 |   3.33 | Using where; Using filesort |
+----+-------------+-----------+------------+------+---------------+------+---------+------+--------+----------+-----------------------------+

 與E選項一樣,這里未使用到索引,說明排序列放在復合索引的最前面是無法被使用到的。

通過上面的6個索引測試,我們發(fā)現(xiàn),等值查詢列和范圍查詢列放在復合索引前面,復合索引都能被使用到,只是使用到的列可能不一樣。哪種方式創(chuàng)建索引最好呢?MySQL的查詢優(yōu)化器是基于開銷(cost)來選擇最優(yōu)的執(zhí)行計劃的,我們不妨來看看上面的6個索引的執(zhí)行開銷。

索引         開銷cost
----------   ------------
idx_a        8518
idx_b        8524
idx_c        13
idx_d        228
idx_e        78083
idx_f        78083

 通過上面的開銷,可以看到:

  • idx_a和idx_b:索引使用范圍查詢字段開頭,導致索引只能使用到第一列,無法消除排序,導致開銷較大;
  • idx_c和idx_d:索引使用等值查詢字段開頭,范圍查詢和排序位于后面,開銷是最小的;
  • idx_e和idx_f :索引使用排序字段開頭,導致索引無法被使用到,走的全表掃描,開銷巨大。

更進一步,idx_c和idx_d如何選擇呢?idx_c使用索引進行等值查詢+范圍查詢,然后對數(shù)據(jù)進行排序;idx_d使用索引進行等值查詢+索引條件下推查詢,然后按照順序直接獲取數(shù)據(jù)。兩種方式各有優(yōu)劣,我們不妨再來看一個例子:

把上面6個索引都加到表上,看看如下SQL會選擇哪個索引。

mysql> show index from employees;
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table   | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| employees |     0 | PRIMARY |      1 | emp_no   | A     |   299468 | NULL   | NULL  |   | BTREE   |     |        |
| employees |     1 | idx_a  |      1 | hire_date  | A     |    5355 | NULL   | NULL  |   | BTREE   |     |        |
| employees |     1 | idx_a  |      2 | first_name | A     |   290745 | NULL   | NULL  |   | BTREE   |     |        |
| employees |     1 | idx_a  |      3 | birth_date | A     |   299468 | NULL   | NULL  |   | BTREE   |     |        |
| employees |     1 | idx_b  |      1 | hire_date  | A     |    6237 | NULL   | NULL  |   | BTREE   |     |        |
| employees |     1 | idx_b  |      2 | birth_date | A     |   297591 | NULL   | NULL  |   | BTREE   |     |        |
| employees |     1 | idx_b  |      3 | first_name | A     |   299468 | NULL   | NULL  |   | BTREE   |     |        |
| employees |     1 | idx_c  |      1 | first_name | A     |    1260 | NULL   | NULL  |   | BTREE   |     |        |
| employees |     1 | idx_c  |      2 | hire_date  | A     |   293517 | NULL   | NULL  |   | BTREE   |     |        |
| employees |     1 | idx_c  |      3 | birth_date | A     |   299468 | NULL   | NULL  |   | BTREE   |     |        |
| employees |     1 | idx_d  |      1 | first_name | A     |    1218 | NULL   | NULL  |   | BTREE   |     |        |
| employees |     1 | idx_d  |      2 | birth_date | A     |   294525 | NULL   | NULL  |   | BTREE   |     |        |
| employees |     1 | idx_d  |      3 | hire_date  | A     |   298095 | NULL   | NULL  |   | BTREE   |     |        |
| employees |     1 | idx_e  |      1 | birth_date | A     |    4767 | NULL   | NULL  |   | BTREE   |     |        |
| employees |     1 | idx_e  |      2 | first_name | A     |   292761 | NULL   | NULL  |   | BTREE   |     |        |
| employees |     1 | idx_e  |      3 | hire_date  | A     |   299468 | NULL   | NULL  |   | BTREE   |     |        |
| employees |     1 | idx_f  |      1 | birth_date | A     |    4767 | NULL   | NULL  |   | BTREE   |     |        |
| employees |     1 | idx_f  |      2 | hire_date  | A     |   297864 | NULL   | NULL  |   | BTREE   |     |        |
| employees |     1 | idx_f  |      3 | first_name | A     |   299468 | NULL   | NULL  |   | BTREE   |     |        |
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

SQL1

mysql> explain select emp_no,birth_date,first_name,last_name,gender,hire_date 
from  employees 
where  hire_date >= '1998-01-01'
and   first_name = 'Ebbe'
order by birth_date;
+----+-------------+-----------+------------+-------+-------------------------+-------+---------+------+------+----------+---------------------------------------+
| id | select_type | table   | partitions | type | possible_keys      | key  | key_len | ref | rows | filtered | Extra                 |
+----+-------------+-----------+------------+-------+-------------------------+-------+---------+------+------+----------+---------------------------------------+
| 1 | SIMPLE   | employees | NULL    | range | idx_a,idx_b,idx_c,idx_d | idx_c | 19   | NULL |  5 |  100.00 | Using index condition; Using filesort |
+----+-------------+-----------+------------+-------+-------------------------+-------+---------+------+------+----------+---------------------------------------+

 這里MySQL自動選擇了idx_c,是因為first_name+hire_date兩個字段已經(jīng)將數(shù)據(jù)過濾了只有5行,由于數(shù)據(jù)少,排序非???。反之,如果選擇idx_d,則需要先通過first_name字段過濾出符合條件的190行數(shù)據(jù),然后再使用hire_date篩選數(shù)據(jù),工作量較大。

SQL2

mysql> explain select emp_no,birth_date,first_name,last_name,gender,hire_date 
from  employees 
where  hire_date >= '1980-01-01'
and   first_name = 'Ebbe'
order by birth_date;
+----+-------------+-----------+------------+------+-------------------------+-------+---------+-------+------+----------+-----------------------+
| id | select_type | table   | partitions | type | possible_keys      | key  | key_len | ref  | rows | filtered | Extra         |
+----+-------------+-----------+------------+------+-------------------------+-------+---------+-------+------+----------+-----------------------+
| 1 | SIMPLE   | employees | NULL    | ref | idx_a,idx_b,idx_c,idx_d | idx_d | 16   | const | 190 |  50.00 | Using index condition |
+----+-------------+-----------+------------+------+-------------------------+-------+---------+-------+------+----------+-----------------------+

 如果選擇idx_c,first_name+hire_date兩個字段通過索引過濾數(shù)據(jù)之后,數(shù)據(jù)量較大,導致排序非常慢。MySQL自動選擇了idx_d,通過索引的first_name列過濾數(shù)據(jù),并通過索引條件下推過濾hire_date字段,然后從索引中有序的取出數(shù)據(jù),相對來說,由于使用idx_d無需排序,速度會更快。

 (四)復合索引總結(jié)

1.復合索引的創(chuàng)建,如果存在多個等值查詢,則將選擇性好的列放在最前面,選擇性差的列放在后面;

2.復合索引的創(chuàng)建,如果涉及到等值查詢和范圍查詢,不管非等值查詢的列的選擇性如何好,等值查詢的字段要放在非等值查詢的前面;

3.復合索引的創(chuàng)建,如果涉及到等值查詢和范圍查詢和排序(order by、group by),則等值查詢放在索引最前面,范圍查詢和排序哪個在前,哪個在后,需要根據(jù)實際場景決定。如果范圍查詢在前,則無法使用到索引的有序性,需filesort,適用于返回結(jié)果較少的SQL,因為結(jié)果少則排序開銷?。蝗绻判蛟谇?,則可以使用到索引的有序性,但是需要回表(或者索引條件下推)去查詢數(shù)據(jù),適用于返回結(jié)果較多的SQL,因為無需排序,直接取出數(shù)據(jù)。

4.復合索引的創(chuàng)建,一定不能把order by、group by的列放在索引的最前面,因為查詢中總是where先于order by執(zhí)行;

5.使用索引進行范圍查詢會導致后續(xù)索引字段無法被使用,如果有排序,無法消除filesort排序。例子:a_b_c索引,where a>? and b = ? order by c,則a可以被使用到,b無法被使用,c字段需filesort。

總結(jié)

到此這篇關(guān)于MySQL復合索引的文章就介紹到這了,更多相關(guān)MySQL復合索引內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:
  • MySQL 索引和數(shù)據(jù)表該如何維護
  • MySQL索引知識的一些小妙招總結(jié)
  • MySQL創(chuàng)建高性能索引的全步驟
  • MySQL創(chuàng)建索引需要了解的
  • MySQL查詢?nèi)哂嗨饕臀词褂眠^的索引操作
  • MySQL 普通索引和唯一索引的區(qū)別詳解
  • 淺談Mysql哪些字段適合建立索引
  • mysql 添加索引 mysql 如何創(chuàng)建索引
  • MySQL索引類型總結(jié)和使用技巧以及注意事項
  • MySQL 創(chuàng)建索引(Create Index)的方法和語法結(jié)構(gòu)及例子
  • mysql性能優(yōu)化之索引優(yōu)化
  • MySQL 主鍵與索引的聯(lián)系與區(qū)別分析
  • MySQL如何構(gòu)建數(shù)據(jù)表索引

標簽:荊州 滄州 甘南 隨州 資陽 錦州 黑河 吉林

巨人網(wǎng)絡(luò)通訊聲明:本文標題《MySQL復合索引的深入探究》,本文關(guān)鍵詞  MySQL,復合,索引,的,深入,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《MySQL復合索引的深入探究》相關(guān)的同類信息!
  • 本頁收集關(guān)于MySQL復合索引的深入探究的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    91久久精品国产| 91丨九色丨尤物| 国产欧美一区二区三区在线看| 丝袜亚洲另类丝袜在线| 丰满岳妇乱一区二区三区| 啪啪导航网站| 欧美最猛性xxxxx免费| 精品国产二区在线| 欧美在线高清| 亚洲精品一区二区三区四区| 国产综合香蕉五月婷在线| 成年人免费视频观看| 国产精品嫩草影院在线看| 国产精品久久久久久久久久久不卡| 日日干天夜夜| 99re6在线视频精品免费| 国产精品免费区二区三区观看| 欧美3p在线观看| 国内自拍视频在线播放| 国产精品sm| 国产精品久久久精品| 国产成年人在线观看| 99热在线只有精品| 国产欧美一区二区| 久久国产精品成人免费观看的软件| 国产freexxxx性播放麻豆| 男人的天堂av网站| 最新中文字幕在线观看| 亚洲美女视频一区| 性一爱一乱一交一视频| 中国精品一区二区| 成人精品影视| 国产在线视频卡一卡二| 黄色国产在线观看| 麻豆国产一区二区| 免费看日韩精品| 国产精品嫩草影视| 国产一区二区三区不卡av| 在线观看三级视频| 欧美妇女性影城| 精品久久久久久久久久久久久久久久久久| 欧美日韩中字| 国产一区二区三区四区尤物| 色噜噜狠狠色综合网| 国产三级精品网站| 成年女人色毛片免费| 日韩一区二区三区视频| jizz性欧美10| 亚洲高清福利| 欧洲精品乱码久久久久蜜桃| 美女精品在线| 欧美亚洲国产视频小说| 网站黄色在线观看| xxx在线免费观看| 美女91精品| 高清一区二区三区四区五区| 黄色大片在线看| 久久国产手机看片| 天天射夜夜骑| 美女精品视频一区| 在线免费黄色毛片| 日韩精品亚洲精品| 日韩美女一区二区三区在线观看| 日韩片电影在线免费观看| 亚洲福利视频一区| 欧美—级在线免费片| 蜜桃av麻豆av天美av免费| 免费观看成人www动漫视频| 亚洲九九九在线观看| аⅴ成人天堂中文在线| 精品国产免费久久久久久尖叫| 国产三级香港三韩国三级| 欧洲乱码伦视频免费| 国产在线精品一区二区夜色| 尤物视频在线观看网站| 国产精品日韩在线一区| 欧美午夜片在线看| 亚洲第一会所| 中文字幕精品视频在线| 高h放荡受浪受bl| 成人性生交大片免费看96| 国产精品第9页| 国产在线1区| www.欧美精品一二区| 高清美女视频一区| 亚洲图区综合网| 久久午夜电影网| 青青视频免费在线观看| 无码国精品一区二区免费蜜桃| 久久久久久久久久久久91| 中文字幕乱码日本亚洲一区二区| 麻豆视频官网| av综合网址| 久久99久久99精品蜜柚传媒| 欧美欧美午夜aⅴ在线观看| 7777久久香蕉成人影院| 亚洲人妖在线| 99久久国产宗和精品1上映| 精品国产a毛片| 成年人看的免费视频| 丁香婷婷深情五月亚洲| 久久精品aⅴ无码中文字字幕重口| 91精品国产综合久久婷婷香蕉| 成人av在线播放| 成年人黄色在线观看| 自拍日韩亚洲一区在线| 中文字幕乱码人妻无码久久| 成人在线观看毛片| 五十路亲子中出在线观看| 91一区在线| 日韩成人视屏| 伊人成综合网伊人222| 黄色在线观看免费| 精品999日本久久久影院| 亚洲精品一区二区三区在线观看| 嫩草成人www欧美| 爱爱永久免费视频| 欧洲女同同性吃奶| 欧美成a人片免费观看久久五月天| 9色视频在线观看| 国产肥老妇视频| 国产精品sss在线观看av| 亚洲激情网站免费观看| 粉嫩绯色av一区二区在线观看| 男女性色大片免费观看一区二区| 亚洲av熟女国产一区二区性色| 久久久久日韩精品久久久男男| 伊人天天久久大香线蕉av色| 亚洲av成人精品一区二区三区| 日韩极品在线观看| 亚洲乱码国产乱码精品精可以看| 欧美激情一区二区三区四区| 欧美精品亚洲一区二区在线播放| 国产精品久久一| 国产亚洲综合色| 亚洲三级一区| 999视频精品| 蜜臀精品一区二区三区| 北岛玲一区二区三区四区| 一级黄色片在线看| 一本一本久久a久久精品综合妖精| 97人人模人人爽视频一区二区| 亚洲天堂视频在线播放| 欧美在线关看| 国产在线拍揄自揄拍无码视频| 亚洲视频 欧美视频| 国产乱码一区二区| 精品少妇一区二区| 性欧美xxxx大乳国产app| 天堂a中文在线| 日韩xxxxxxxxx| 青青草原播放器| 日本免费无人高清| 国产精品区在线| 欧美亚洲日本在线| 国产精品久久久久9999吃药| 色一情一乱一伦一区二区三区| 日本视频在线观看一区二区三区| xxxxaaa欧美另类| 国产精品久久a| 免费在线看一区| 成人福利网站在线观看| 亚洲第一区第二区第三区| 国产1区2区在线观看| 亚洲欧美综合在线观看| 中文字幕在线不卡一区二区三区| 免费国产成人看片在线| 久久久国产精品入口麻豆| 中文字幕av专区| 激情六月丁香婷婷| 国产亚洲精品久久久久久777| 久久国产精品99久久人人澡| 亚洲无码精品在线播放| 最新国产在线拍揄自揄视频| 好吊色一区二区| 一级特黄性色生活片| 久久精品蜜桃| 中文字幕亚洲精品在线| 国产小视频免费在线网址| 亚洲视频1区2区| 日韩欧美国产综合一区| 国产精品一区二区亚洲| 欧美激情日韩| 91高清在线观看视频| 亚洲欧洲日本一区二区三区| 日韩成年人视频| 日韩精品视频在线播放| aaaa一级片| 亚洲人成电影| 欧美日韩国产另类一区| 婷婷在线精品视频| 一区二区在线中文字幕电影视频| 成av人片一区二区| 成年人午夜视频在线观看| 国产男女猛烈无遮挡a片漫画| 中文字幕视频网站| 99视频资源网| 国产精品美女久久久久高潮| 欧美一卡二卡三卡| 韩国中文字幕在线| 久久精品日产第一区二区三区| 综合干狼人综合首页| 欧美一级黑人aaaaaaa做受| 91麻豆国产自产在线观看亚洲| 无码熟妇人妻av| 欧美亚洲免费在线| 久久婷婷国产综合精品青草| 香蕉久久夜色精品国产使用方法| 欧美a v在线播放| 日韩成人影视| 亚洲精品一区二区三区在线| 国产精品欧美日韩一区二区| 在线观看视频免费一区二区三区| 国产区在线观看| 亚洲成人一区在线| 日本在线播放视频| 日本一级理论片在线大全| 日韩网站在线播放| 999热精品视频| 囯产精品一品二区三区| 娇妻高潮浓精白浆xxⅹ| 国产美女做爰免费视频软件| 国产精品福利一区二区三区| 久久亚洲电影| 青青草视频一区| 欧美日韩成人在线视频| 国产综合av一区二区三区| 日韩精品极品| 亚洲电影免费| 中文字幕在线看片| 一二三四区在线观看| av小说在线播放| 色综合天天狠狠| 国产精品白丝一区二区三区| 国产无遮挡又黄又爽又色视频| 综合久久久久久久| 蜜桃麻豆91| 亚洲经典一区二区三区| 久久丫精品国产亚洲av不卡| 国产在线观看免费一区| 不卡免费追剧大全电视剧网站| 97久久国产精品| 欧洲成人免费aa| 97netav| 午夜精品福利在线| 蜜臀精品一区二区三区| 亚洲插插视频| 巨大黑人video| 缅甸午夜性猛交xxxx| 亚洲成人精品视频| 欧美特黄一级大片| 视频在线一区二区| 国产成人av网址| 麻豆国产91在线播放| 国产成人亚洲综合| 国产成人亚洲精品狼色在线| 国产又粗又猛又爽| 成人av在线播放观看| www 久久久| 91久久夜色精品国产按摩| 黄p免费网站| 男人天堂欧美日韩| 黄漫在线观看| 黄色激情网址| 久久久亚洲午夜电影| 2020国产精品久久精品美国| 日本欧美一区| 嫩草国产精品入口| 久久久久久12| 国产一区在线视频| 亚洲不卡1卡2卡三卡2021麻豆| 亚洲国产精品日韩专区av有中文| 精品亚洲男同gayvideo网站| 制服诱惑一区二区| 久久久不卡网国产精品二区| 亚洲欧美精品在线| 国产亚洲一区在线播放| 国产精品国产亚洲精品看不卡| 日本最黄视频| 在线观看中文字幕的网站| 国产一区二区三区久久| 国产精品美女久久久久久久久| 91精品国产自产在线丝袜啪| 正在播放一区二区| 国产无遮挡在线视频免费观看| 国产91在线视频蝌蚪| 美女又爽又黄免费动漫| 国产精品美女久久福利网站| 自拍偷拍欧美专区| 91免费精品视频| 人妻中文字幕一区| 午夜亚洲性色视频| 国产一区欧美二区三区| 欧美成a人片在线观看久| 91美女视频网站| 欧美体内谢she精2性欧美| 在线精品视频免费播放| 午夜福利视频一区二区| 日韩av二区在线播放| 日韩在线网址| 免费不卡在线观看av| a视频免费在线观看| 偷偷要色偷偷| 91成人小视频| 欧美精品久久久久久久久久丰满| 久久综合精品国产一区二区三区| 亚洲高清一二三区| 岛国中文字幕在线| 欧美视频久久久| 天堂va欧美va亚洲va老司机| 国产乱码午夜在线视频| 精品国产乱码久久久久久免费| 亚洲少妇中文字幕| 亚欧色一区w666天堂| 一区二区国产精品视频| 国产精品免费免费| 高清一级毛片视频| 亚洲都市激情| 国产伦精品免费视频| 国产精品国三级国产av| 亚洲高清一二三区| 精品一区二区三区免费毛片| 国产v日产∨综合v精品视频| 五月天久久网站| 亚洲第一导航| av天在线播放| 欧美a在线观看| 日本不卡不码高清免费观看|