精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Christina問我:你都是如何設計索引的?

數(shù)據(jù)庫 MySQL
數(shù)據(jù)庫系列更新到現(xiàn)在我想大家對所有的概念都已有個大概認識了,這周我在看評論的時候我發(fā)現(xiàn)有個網(wǎng)友的提問我覺得很有意思:帥丙如何設計一個索引?你們都是怎么設計索引的?怎么設計更高效?

 前言

數(shù)據(jù)庫系列更新到現(xiàn)在我想大家對所有的概念都已有個大概認識了,這周我在看評論的時候我發(fā)現(xiàn)有個網(wǎng)友的提問我覺得很有意思:帥丙如何設計一個索引?你們都是怎么設計索引的?怎么設計更高效?

我一想索引我寫過很多了呀,沒道理讀者還不會啊,但是我一回頭看完,那確實,我就寫了索引的概念,優(yōu)劣勢,沒提到怎么設計,那這篇文章又這樣應運而生了。

本文

還是會有很多之前寫過的重復概念,但是也是為了大家能更好的理解MySQL中幾種索引設計的原理。

正文我們知道,索引是一個基于鏈表實現(xiàn)的樹狀Tree結構,能夠快速的檢索數(shù)據(jù),目前幾乎所RDBMS數(shù)據(jù)庫都實現(xiàn)了索引特性,比如MySQL的B+Tree索引,MongoDB的BTree索引等。

在業(yè)務開發(fā)過程中,索引設計高效與否決定了接口對應SQL的執(zhí)行效率,高效的索引可以降低接口的Response Time,同時還可以降低成本,我們要現(xiàn)實的目標是:索引設計->降低接口響應時間->降低服務器配置->降低成本,最終要落實到成本上來,因為老板最關心的是成本。

今天就跟大家聊聊MySQL中的索引以及如何設計索引,使用索引才能提降低接口的RT,提高用戶體檢。

MySQL中的索引

MySQL中的InnoDB引擎使用B+Tree結構來存儲索引,可以盡量減少數(shù)據(jù)查詢時磁盤IO次數(shù),同時樹的高度直接影響了查詢的性能,一般樹的高度維持在 3~4 層。

B+Tree由三部分組成:根root、枝branch以及Leaf葉子,其中root和branch不存儲數(shù)據(jù),只存儲指針地址,數(shù)據(jù)全部存儲在Leaf Node,同時Leaf Node之間用雙向鏈表鏈接,結構如下:


從上面可以看到,每個Leaf Node是三部分組成的,即前驅指針p_prev,數(shù)據(jù)data以及后繼指針p_next,同時數(shù)據(jù)data是有序的,默認是升序ASC,分布在B+tree右邊的鍵值總是大于左邊的,同時從root到每個Leaf的距離是相等的,也就是訪問任何一個Leaf Node需要的IO是一樣的,即索引樹的高度Level + 1次IO操作。

我們可以將MySQL中的索引可以看成一張小表,占用磁盤空間,創(chuàng)建索引的過程其實就是按照索引列排序的過程,先在sort_buffer_size進行排序,如果排序的數(shù)據(jù)量大,sort_buffer_size容量不下,就需要通過臨時文件來排序,最重要的是通過索引可以避免排序操作(distinct,group by,order by)。

聚集索引

MySQL中的表是IOT(Index Organization Table,索引組織表),數(shù)據(jù)按照主鍵id順序存儲(邏輯上是連續(xù),物理上不連續(xù)),而且主鍵id是聚集索引(clustered index),存儲著整行數(shù)據(jù),如果沒有顯示的指定主鍵,MySQL會將所有的列組合起來構造一個row_id作為primary key,例如表users(id, user_id, user_name, phone, primary key(id)),id是聚集索引,存儲了id, user_id, user_name, phone整行的數(shù)據(jù)。

輔助索引


輔助索引也稱為二級索引,索引中除了存儲索引列外,還存儲了主鍵id,對于user_name的索引idx_user_name(user_name)而言,其實等價于idx_user_name(user_name, id),MySQL會自動在輔助索引的最后添加上主鍵id,熟悉Oracle數(shù)據(jù)庫的都知道,索引里除了索引列還存儲了row_id(代表數(shù)據(jù)的物理位置,由四部分組成:對象編號+數(shù)據(jù)文件號+數(shù)據(jù)塊號+數(shù)據(jù)行號),我們在創(chuàng)建輔助索引也可以顯示添加主鍵id。

  1. -- 創(chuàng)建user_name列上的索引 
  2. mysql> create index idx_user_name on users(user_name); 
  3. -- 顯示添加主鍵id創(chuàng)建索引 
  4. mysql> create index idx_user_name_id on users(user_name,id); 
  5. -- 對比兩個索引的統(tǒng)計數(shù)據(jù) 
  6. mysql> select a.space as tbl_spaceid, a.table_id, a.name as table_name, row_format, space_type,  b.index_id , b.name as index_name, n_fields, page_no, b.type as index_type  from information_schema.INNODB_TABLES a left join information_schema.INNODB_INDEXES b  on a.table_id =b.table_id where a.name = 'test/users'
  7. +-------------+----------+------------+------------+------------+----------+------------------+----------+------ 
  8. | tbl_spaceid | table_id | table_name | row_format | space_type | index_id | index_name       | n_fields | page_no | index_type | 
  9. +-------------+----------+------------+------------+------------+----------+------------------+----------+------ 
  10. |         518 |     1586 | test/users | Dynamic    | Single     |     1254 | PRIMARY          |        9 |       4 |          3 | 
  11. |         518 |     1586 | test/users | Dynamic    | Single     |     4003 | idx_user_name    |        2 |       5 |          0 | 
  12. |         518 |     1586 | test/users | Dynamic    | Single     |     4004 | idx_user_name_id |        2 |      45 |          0 | 
  13. mysql> select index_name, last_update, stat_name, stat_value, stat_description from mysql.innodb_index_stats where index_name in ('idx_user_name','idx_user_name_id'); 
  14. +------------------+---------------------+--------------+------------+-----------------------------------+ 
  15. | index_name       | last_update         | stat_name    | stat_value | stat_description                  | 
  16. +------------------+---------------------+--------------+------------+-----------------------------------+    
  17. | idx_user_name    | 2021-01-02 17:14:48 | n_leaf_pages |       1358 | Number of leaf pages in the index | 
  18. | idx_user_name    | 2021-01-02 17:14:48 | size         |       1572 | Number of pages in the index      | 
  19. | idx_user_name_id | 2021-01-02 17:14:48 | n_leaf_pages |       1358 | Number of leaf pages in the index | 
  20. | idx_user_name_id | 2021-01-02 17:14:48 | size         |       1572 | Number of pages in the index      | 

對比一下兩個索引的結果,n_fields表示索引中的列數(shù),n_leaf_pages表示索引中的葉子頁數(shù),size表示索引中的總頁數(shù),通過數(shù)據(jù)比對就可以看到,輔助索引中確實包含了主鍵id,也說明了這兩個索引時完全一致。

索引回表

上面證明了輔助索引包含主鍵id,如果通過輔助索引列去過濾數(shù)據(jù)有可能需要回表,舉個例子:業(yè)務需要通過用戶名user_name去查詢用戶表users的信息,業(yè)務接口對應的SQL:

  1. select  user_id, user_name, phone from users where user_name = 'Laaa'

我們知道,對于索引idx_user_name而言,其實就是一個小表idx_user_name(user_name, id),如果只查詢索引中的列,只需要掃描索引就能獲取到所需數(shù)據(jù),是不需要回表的,如下SQL語句:

SQL 1: select id, user_name from users where user_name = 'Laaa';

SQL 2: select id from users where user_name = 'Laaa';

  1. mysql> explain select id, name from users where name = 'Laaa'
  2. +----+-------------+-------+------------+------+---------------+---------------+---------+-------+------+------- 
  3. | id | select_type | table | partitions | type | possible_keys | key           | key_len | ref   | rows | filtered | Extra       | 
  4. +----+-------------+-------+------------+------+---------------+---------------+---------+-------+------+------- 
  5. |  1 | SIMPLE      | users | NULL       | ref  | idx_user_name | idx_user_name | 82      | const |    1 |   100.00 | Using index | 
  6. mysql> explain select id from users where name = 'Laaa'
  7. +----+-------------+-------+------------+------+---------------+---------------+---------+-------+------+------- 
  8. | id | select_type | table | partitions | type | possible_keys | key           | key_len | ref   | rows | filtered | Extra       | 
  9. +----+-------------+-------+------------+------+---------------+---------------+---------+-------+------+------- 
  10. |  1 | SIMPLE      | users | NULL       | ref  | idx_user_name | idx_user_name | 82      | const |    1 |   100.00 | Using index | 

SQL 1和SQL 2的執(zhí)行計劃中的Extra=Using index 表示使用覆蓋索引掃描,不需要回表,再來看上面的業(yè)務SQL:

select user_id, user_name, phone from users where user_name = 'Laaa';

可以看到select后面的user_id,phone列不在索引idx_user_name中,就需要通過主鍵id進行回表查找,MySQL內部分如下兩個階段處理:

Section 1:select **id** from users where user_name = 'Laaa' //id = 100101

Section 2: select user_id, user_name, phone from users where id = 100101;

將Section 2的操作稱為回表,即通過輔助索引中的主鍵id去原表中查找數(shù)據(jù)。

索引高度

MySQL的索引時B+tree結構,即使表里有上億條數(shù)據(jù),索引的高度都不會很高,通常維持在3-4層左右,我來計算下索引idx_name的高度,從上面知道索引信息:index_id = 4003, page_no = 5,它的偏移量offset就是page_no x innodo_page_size + 64 = 81984,通過hexdump進行查看

  1. $hexdump -s 81984 -n 10 /usr/local/var/mysql/test/users.ibd 
  2. 0014040 00 02 00 00 00 00 00 00 0f a3                   
  3. 001404a 

其中索引的PAGE_LEVEL為00,即idx_user_name索引高度為1,0f a3 代表索引編號,轉換為十進制是4003,正是index_id。

數(shù)據(jù)掃描方式

全表掃描

從左到右依次掃描整個B+Tree獲取數(shù)據(jù),掃描整個表數(shù)據(jù),IO開銷大,速度慢,鎖等嚴重,影響MySQL的并發(fā)。

對于OLAP的業(yè)務場景,需要掃描返回大量數(shù)據(jù),這時候全表掃描的順序IO效率更高。

索引掃描

通常來講索引比表小,掃描的數(shù)據(jù)量小,消耗的IO少,執(zhí)行速度塊,幾乎沒有鎖等,能夠提高MySQL的并發(fā)。

對于OLTP系統(tǒng),希望所有的SQL都能命中合適的索引總是美好的。

主要區(qū)別就是掃描數(shù)據(jù)量大小以及IO的操作,全表掃描是順序IO,索引掃描是隨機IO,MySQL對此做了優(yōu)化,增加了change buffer特性來提高IO性能。

索引優(yōu)化案例

分頁查詢優(yōu)化

業(yè)務要根據(jù)時間范圍查詢交易記錄,接口原始的SQL如下:

  1. select  * from trade_info where status = 0 and create_time >= '2020-10-01 00:00:00' and create_time <= '2020-10-07 23:59:59' order by id desc limit 102120, 20; 

表trade_info上有索引idx_status_create_time(status,create_time),通過上面分析知道,等價于索引**(status,create_time,id)**,對于典型的分頁limit m, n來說,越往后翻頁越慢,也就是m越大會越慢,因為要定位m位置需要掃描的數(shù)據(jù)越來越多,導致IO開銷比較大,這里可以利用輔助索引的覆蓋掃描來進行優(yōu)化,先獲取id,這一步就是索引覆蓋掃描,不需要回表,然后通過id跟原表trade_info進行關聯(lián),改寫后的SQL如下:

  1. select * from trade_info a , 
  2.  
  3. (select  id from trade_info where status = 0 and create_time >= '2020-10-01 00:00:00' and create_time <= '2020-10-07 23:59:59' order by id desc limit 102120, 20) as b   //這一步走的是索引覆蓋掃描,不需要回表 
  4.  where a.id = b.id; 

很多同學只知道這樣寫效率高,但是未必知道為什么要這樣改寫,理解索引特性對編寫高質量的SQL尤為重要。

分而治之總是不錯的

營銷系統(tǒng)有一批過期的優(yōu)惠卷要失效,核心SQL如下:

  1. -- 需要更新的數(shù)據(jù)量500w 
  2. update coupons set status = 1 where status =0 and create_time >= '2020-10-01 00:00:00' and create_time <= '2020-10-07 23:59:59'

在Oracle里更新500w數(shù)據(jù)是很快,因為可以利用多個cpu core去執(zhí)行,但是MySQL就需要注意了,一個SQL只能使用一個cpu core去處理,如果SQL很復雜或執(zhí)行很慢,就會阻塞后面的SQL請求,造成活動連接數(shù)暴增,MySQL CPU 100%,相應的接口Timeout,同時對于主從復制架構,而且做了業(yè)務讀寫分離,更新500w數(shù)據(jù)需要5分鐘,Master上執(zhí)行了5分鐘,binlog傳到了slave也需要執(zhí)行5分鐘,那就是Slave延遲5分鐘,在這期間會造成業(yè)務臟數(shù)據(jù),比如重復下單等。

優(yōu)化思路:先獲取where條件中的最小id和最大id,然后分批次去更新,每個批次1000條,這樣既能快速完成更新,又能保證主從復制不會出現(xiàn)延遲。

優(yōu)化如下

1.先獲取要更新的數(shù)據(jù)范圍內的最小id和最大id(表沒有物理delete,所以id是連續(xù)的)

  1. mysql> explain select min(id) min_id, max(id) max_id from coupons where status =0 and create_time >= '2020-10-01 00:00:00' and create_time <= '2020-10-07 23:59:59';  
  2. +----+-------------+-------+------------+-------+------------------------+------------------------+---------+--- 
  3. | id | select_type | table | partitions | type  | possible_keys          | key                    | key_len | ref  | rows   | filtered | Extra                    | 
  4. +----+-------------+-------+------------+-------+------------------------+------------------------+---------+--- 
  5. |  1 | SIMPLE      | users | NULL       | range | idx_status_create_time | idx_status_create_time | 6       | NULL | 180300 |   100.00 | Using where; Using index | 

Extra=Using where; Using index使用了索引idx_status_create_time,同時需要的數(shù)據(jù)都在索引中能找到,所以不需要回表查詢數(shù)據(jù)。

2.以每次1000條commit一次進行循環(huán)update,主要代碼如下:

  1. current_id = min_id; 
  2. for  current_id < max_id do 
  3.   update coupons set status = 1 where id >=current_id and id <= current_id + 1000;  //通過主鍵id更新1000條很快 
  4. commit
  5. current_id += 1000; 
  6. done 

這兩個案例告訴我們,要充分利用輔助索引包含主鍵id的特性,先通過索引獲取主鍵id走覆蓋索引掃描,不需要回表,然后再通過id去關聯(lián)操作是高效的,同時根據(jù)MySQL的特性使用分而治之的思想既能高效完成操作,又能避免主從復制延遲產生的業(yè)務數(shù)據(jù)混亂。

MySQL索引設計

熟悉了索引的特性之后,就可以在業(yè)務開發(fā)過程中設計高質量的索引,降低接口的響應時間。

前綴索引

對于使用REDUNDANT或者COMPACT格式的InnoDB表,索引鍵前綴長度限制為767字節(jié)。如果TEXT或VARCHAR列的列前綴索引超過191個字符,則可能會達到此限制,假定為utf8mb4字符集,每個字符最多4個字節(jié)。

可以通過設置參數(shù)innodb_large_prefix來開啟或禁用索引前綴長度的限制,即是設置為OFF,索引雖然可以創(chuàng)建成功,也會有一個警告,主要是因為index size會很大,效率大量的IO的操作,即使MySQL優(yōu)化器命中了該索引,效率也不會很高。

  1. -- 設置innodb_large_prefix=OFF禁用索引前綴限制,雖然可以創(chuàng)建成功,但是有警告。 
  2. mysql> create index idx_nickname on users(nickname);    // `nickname` varchar(255) 
  3. Records: 0  Duplicates: 0  Warnings: 1 
  4. mysql> show warnings; 
  5. +---------+------+---------------------------------------------------------+ 
  6. Level   | Code | Message                                                 | 
  7. +---------+------+---------------------------------------------------------+ 
  8. | Warning | 1071 | Specified key was too long; max key length is 767 bytes | 

業(yè)務發(fā)展初期,為了快速實現(xiàn)功能,對一些數(shù)據(jù)表字段的長度定義都比較寬松,比如用戶表users的昵稱nickname定義為varchar(128),而且有業(yè)務接口需要通過nickname查詢,系統(tǒng)運行了一段時間之后,查詢users表最大的nickname長度為30,這個時候就可以創(chuàng)建前綴索引來減小索引的長度提升性能。

  1. -- `nickname` varchar(128) DEFAULT NULL定義的執(zhí)行計劃 
  2. mysql> explain select * from users where nickname = 'Laaa'
  3. +----+-------------+-------+------------+------+---------------+--------------+---------+-------+------+-------- 
  4. | id | select_type | table | partitions | type | possible_keys | key          | key_len | ref   | rows | filtered | Extra | 
  5. +----+-------------+-------+------------+------+---------------+--------------+---------+-------+------+-------- 
  6. |  1 | SIMPLE      | users | NULL       | ref  | idx_nickname  | idx_nickname | 515     | const |    1 |   100.00 | NULL  | 

key_len=515,由于表和列都是utf8mb4字符集,每個字符占4個字節(jié),變長數(shù)據(jù)類型+2Bytes,允許NULL額外+1Bytes,即128 x 4 + 2 + 1 = 515Bytes。創(chuàng)建前綴索引,前綴長度也可以不是當前表的數(shù)據(jù)列最大值,應該是區(qū)分度最高的那部分長度,一般能達到90%以上即可,例如email字段存儲都是類似這樣的值xxxx@yyy.com,前綴索引的最大長度可以是xxxx這部分的最大長度即可。

  1. -- 創(chuàng)建前綴索引,前綴長度為30 
  2. mysql> create index idx_nickname_part on users(nickname(30)); 
  3. -- 查看執(zhí)行計劃 
  4. mysql> explain select * from users where nickname = 'Laaa'
  5. +----+-------------+-------+------------+------+--------------------------------+-------------------+---------+- 
  6. | id | select_type | table | partitions | type | possible_keys                  | key               | key_len | ref   | rows | filtered | Extra       | 
  7. +----+-------------+-------+------------+------+--------------------------------+-------------------+---------+- 
  8. |  1 | SIMPLE      | users | NULL       | ref  | idx_nickname_part,idx_nickname | idx_nickname_part | 123     | const |    1 |   100.00 | Using where | 

可以看到優(yōu)化器選擇了前綴索引,索引長度為123,即30 x 4 + 2 + 1 = 123 Bytes,大小不到原來的四分之。

前綴索引雖然可以減小索引的大小,但是不能消除排序。

  1. mysql> explain select gender,count(*) from users where nickname like 'User100%' group by nickname limit 10; 
  2. +----+-------------+-------+------------+-------+--------------------------------+--------------+---------+----- 
  3. | id | select_type | table | partitions | type  | possible_keys                  | key          | key_len | ref  | rows | filtered | Extra                 | 
  4. +----+-------------+-------+------------+-------+--------------------------------+--------------+---------+----- 
  5. |  1 | SIMPLE      | users | NULL       | range | idx_nickname_part,idx_nickname | idx_nickname | 515     | NULL |  899 |   100.00 | Using index condition | 
  6. --可以看到Extra= Using index condition表示使用了索引,但是需要回表查詢數(shù)據(jù),沒有發(fā)生排序操作。 
  7. mysql> explain select gender,count(*) from users where nickname like  'User100%' group by nickname limit 10; 
  8. +----+-------------+-------+------------+-------+-------------------+-------------------+---------+------+------ 
  9. | id | select_type | table | partitions | type  | possible_keys     | key               | key_len | ref  | rows | filtered | Extra                        | 
  10. +----+-------------+-------+------------+-------+-------------------+-------------------+---------+------+------ 
  11. |  1 | SIMPLE      | users | NULL       | range | idx_nickname_part | idx_nickname_part | 123     | NULL |  899 |   100.00 | Using where; Using temporary | 
  12. --可以看到Extra= Using where; Using temporaryn表示在使用了索引的情況下,需要回表去查詢所需的數(shù)據(jù),同時發(fā)生了排序操作。 

復合索引

在單列索引不能很好的過濾數(shù)據(jù)的時候,可以結合where條件中其他字段來創(chuàng)建復合索引,更好的去過濾數(shù)據(jù),減少IO的掃描次數(shù),舉個例子:業(yè)務需要按照時間段來查詢交易記錄,有如下的SQL:

  1. select  * from trade_info where status = 1 and create_time >= '2020-10-01 00:00:00' and create_time <= '2020-10-07 23:59:59'

開發(fā)同學根據(jù)以往復合索引的設計的經驗:唯一值多選擇性好的列作為復合索引的前導列,所以創(chuàng)建復合索idx_create_time_status是高效的,因為create_time是一秒一個值,唯一值很多,選擇性很好,而status只有離散的6個值,所以認為這樣創(chuàng)建是沒問題的,但是這個經驗只適合于等值條件過濾,不適合有范圍條件過濾的情況,例如idx_user_id_status(user_id,status)這個是沒問題的,但是對于包含有create_time范圍的復合索引來說,就不適應了,我們來看下這兩種不同索引順序的差異,即idx_status_create_time和idx_create_time_status。

  1. -- 分別創(chuàng)建兩種不同的復合索引 
  2. mysql> create index idx_status_create_time on trade_info(status, create_time); 
  3. mysql> create index idx_create_time_status on trade_info(create_time,status); 
  4. -- 查看SQL的執(zhí)行計劃 
  5. mysql> explain select * from users where status = 1 and create_time >='2021-10-01 00:00:00' and create_time <= '2021-10-07 23:59:59'
  6. +----+-------------+-------+------------+-------+-----------------------------------------------+--------------- 
  7. | id | select_type | table | partitions | type  | possible_keys                                 | key                    | key_len | ref  | rows  | filtered | Extra                 | 
  8. +----+-------------+-------+------------+-------+-----------------------------------------------+--------------- 
  9. |  1 | SIMPLE      | trade_info | NULL       | range | idx_status_create_time,idx_create_time_status | idx_status_create_time | 6       | NULL | 98518 |   100.00 | Using index condition | 

從執(zhí)行計劃可以看到,兩種不同順序的復合索引都存在的情況,MySQL優(yōu)化器選擇的是idx_status_create_time索引,那為什么不選擇idx_create_time_status,我們通過optimizer_trace來跟蹤優(yōu)化器的選擇。

  1. -- 開啟optimizer_trace跟蹤 
  2. mysql> set session optimizer_trace="enabled=on",end_markers_in_json=on
  3. -- 執(zhí)行SQL語句 
  4. mysql> select * from trade_info where status = 1 and create_time >='2021-10-01 00:00:00' and create_time <= '2021-10-07 23:59:59'
  5. -- 查看跟蹤結果 
  6. mysql>SELECT trace FROM information_schema.OPTIMIZER_TRACE\G; 

 

對比下兩個索引的統(tǒng)計數(shù)據(jù),如下所示:

MySQL優(yōu)化器是基于Cost的,COST主要包括IO_COST和CPU_COST,MySQL的CBO(Cost-Based Optimizer基于成本的優(yōu)化器)總是選擇Cost最小的作為最終的執(zhí)行計劃去執(zhí)行,從上面的分析,CBO選擇的是復合索引idx_status_create_time,因為該索引中的status和create_time都能參與了數(shù)據(jù)過濾,成本較低;而idx_create_time_status只有create_time參數(shù)數(shù)據(jù)過濾,status被忽略了,其實CBO將其簡化為單列索引idx_create_time,選擇性沒有復合索引idx_status_create_time好。

復合索引設計原則

  1. 將范圍查詢的列放在復合索引的最后面,例如idx_status_create_time。
  2. 列過濾的頻繁越高,選擇性越好,應該作為復合索引的前導列,適用于等值查找,例如idx_user_id_status。

這兩個原則不是矛盾的,而是相輔相成的。

跳躍索引

一般情況下,如果表users有復合索引idx_status_create_time,我們都知道,單獨用create_time去查詢,MySQL優(yōu)化器是不走索引,所以還需要再創(chuàng)建一個單列索引idx_create_time。用過Oracle的同學都知道,是可以走索引跳躍掃描(Index Skip Scan),在MySQL 8.0也實現(xiàn)Oracle類似的索引跳躍掃描,在優(yōu)化器選項也可以看到skip_scan=on。

  1. | optimizer_switch             |use_invisible_indexes=off,skip_scan=on,hash_join=on | 

適合復合索引前導列唯一值少,后導列唯一值多的情況,如果前導列唯一值變多了,則MySQL CBO不會選擇索引跳躍掃描,取決于索引列的數(shù)據(jù)分表情況。

  1. mysql> explain select id, user_id,status, phone from users where create_time >='2021-01-02 23:01:00' and create_time <= '2021-01-03 23:01:00'
  2. +----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+---- 
  3. | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows   | filtered | Extra       | 
  4. +----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+---- 
  5. |  1 | SIMPLE      | users | NULL       | range  | idx_status_create_time          | idx_status_create_time | NULL    | NULL | 15636 |    11.11 | Using where; Using index for skip scan| 

也可以通過optimizer_switch='skip_scan=off'來關閉索引跳躍掃描特性。

總結

本位為大家介紹了MySQL中的索引,包括聚集索引和輔助索引,輔助索引包含了主鍵id用于回表操作,同時利用覆蓋索引掃描可以更好的優(yōu)化SQL。

同時也介紹了如何更好做MySQL索引設計,包括前綴索引,復合索引的順序問題以及MySQL 8.0推出的索引跳躍掃描,我們都知道,索引可以加快數(shù)據(jù)的檢索,減少IO開銷,會占用磁盤空間,是一種用空間換時間的優(yōu)化手段,同時更新操作會導致索引頻繁的合并分裂,影響索引性能,在實際的業(yè)務開發(fā)中,如何根據(jù)業(yè)務場景去設計合適的索引是非常重要的,今天就聊這么多,希望對大家有所幫助。

 

責任編輯:姜華 來源: 三太子敖丙
相關推薦

2012-11-30 16:38:37

面試

2014-01-14 10:18:02

智能硬件CES2014升級系統(tǒng)

2012-11-20 11:21:10

密碼加密

2025-03-06 08:21:23

2018-06-15 15:17:30

文章區(qū)塊鏈人工智能

2023-02-28 07:39:18

2025-01-13 08:27:58

AI提示詞量化標準

2020-11-18 07:47:09

ElasticSear Lucene搜索服務器

2021-01-05 08:59:01

InnoDB數(shù)據(jù)磁盤

2021-05-19 08:17:35

秒殺場景高并發(fā)

2020-08-26 08:18:39

數(shù)據(jù)索引查詢

2018-07-26 13:21:56

Dell

2022-10-09 18:39:46

分層代碼復用

2019-11-01 17:15:12

SQL數(shù)據(jù)開發(fā)

2023-02-08 10:45:23

2020-10-19 07:26:23

APP啟動面試官

2010-03-24 17:26:50

無線上網(wǎng)卡流量

2021-05-10 11:15:28

面試索引MySQL

2019-08-02 16:12:42

物聯(lián)網(wǎng)技術數(shù)據(jù)

2010-11-10 16:03:07

點贊
收藏

51CTO技術棧公眾號

免费av成人在线| 在线观看免费成人av| 综合五月激情网| 91精品入口| 日本乱人伦aⅴ精品| 在线视频不卡一区二区| 亚洲女同志亚洲女同女播放| 美女视频一区免费观看| www.欧美免费| 国产精品无码一区二区三区免费 | 久久久成人av| 99riav国产精品视频| 国产日韩另类视频一区| 亚洲永久免费视频| 日韩精品一区二区三区四区五区 | japanese23hdxxxx日韩| 亚洲品质自拍视频| 欧洲国产精品| 国内爆初菊对白视频| 秋霞电影一区二区| 97视频免费在线观看| a一级免费视频| 校园春色另类视频| 欧美成人一区二区| 国产日韩欧美久久| 在线黄色的网站| 亚洲精品美腿丝袜| 亚洲激情啪啪| 欧美另类自拍| 成人午夜免费电影| 97久草视频| 中文字幕无线码一区| 性感少妇一区| 69精品小视频| 免费在线观看黄视频| 97偷自拍亚洲综合二区| 亚洲欧美色婷婷| 中国一级特黄录像播放| 国产日韩一区二区三免费高清| 欧美视频一区在线| 欧美综合在线观看视频| 松下纱荣子在线观看| 亚洲综合一区在线| 热久久最新网址| 久久久久久久久免费视频| 国产精品嫩草影院av蜜臀| 欧美一区观看| 激情在线视频| 久久久久久久久久久久久女国产乱 | 国产曰批免费观看久久久| 国产精品美女在线观看| 精品一区二区无码| 久久一区中文字幕| 国产精品福利观看| 国产日韩久久久| 久久这里只有| 国产精品久久9| 中国黄色一级视频| 老司机一区二区| 国产精品中文久久久久久久| 亚洲视频一区二区三区四区| 美国欧美日韩国产在线播放| 91精品国产自产在线老师啪 | 国产黄大片在线观看| 一区二区三区国产豹纹内裤在线| 丁香色欲久久久久久综合网| 免费看一级大黄情大片| 国内精品在线视频| 久久久天堂av| 小说区图片区图片区另类灬| 在线a免费看| ...xxx性欧美| 一二三四中文字幕| 大桥未久在线视频| 91福利社在线观看| 欧美美女一级片| 久久综合偷偷噜噜噜色| 精品国产伦一区二区三区观看体验| 国产精品二区视频| 另类图片第一页| 亚洲色在线视频| 欧美色图17p| 综合激情婷婷| 久久久久久久亚洲精品| 日韩精品在线免费视频| 日韩不卡手机在线v区| 成人网在线视频| 六月婷婷综合网| 国产亚洲制服色| 2025韩国大尺度电影| 韩国日本一区| 在线观看中文字幕不卡| xxx中文字幕| 曰本一区二区三区视频| 日韩亚洲精品电影| 日韩成人在线免费视频| 秋霞av亚洲一区二区三| 国产成人看片| 国产黄在线看| 亚洲综合色自拍一区| 久草精品在线播放| 99精品美女视频在线观看热舞 | 免费成年人高清视频| 9l视频自拍蝌蚪9l视频成人| 亚洲精品综合久久中文字幕| 最新av电影网站| 在线视频日韩| 亚洲伊人一本大道中文字幕| 欧美女同网站| 亚洲成人动漫一区| 亚洲第一男人天堂| 国产在线观看免费播放| 成人毛片免费看| 性欧美xxxx交| 国产老妇伦国产熟女老妇视频| www.欧美.com| 国产一二三四五| 国产私拍福利精品视频二区| 精品乱人伦小说| 超碰人人人人人人人| 亚洲毛片网站| 4444kk亚洲人成电影在线| 高清av电影在线观看| 亚洲国产一区二区三区青草影视| 免费一级特黄录像| 香蕉久久精品日日躁夜夜躁| 欧美激情综合亚洲一二区| 91久久国语露脸精品国产高跟| 99精品在线观看视频| av磁力番号网| 九九热这里有精品| 亚洲欧美日韩第一区| 国产一级一片免费播放| 国产一区二区三区四| 亚洲欧美一区二区原创| 日韩免费福利视频| 精品亚洲国产成av人片传媒 | 亚洲一区二区欧美| 中文字幕在线视频精品| 成人一二三区| 国产精品吊钟奶在线| 偷拍25位美女撒尿视频在线观看| 一区二区免费视频| 天天色天天干天天色| 天天超碰亚洲| 成人在线观看视频网站| 91社区在线| 在线精品视频免费观看| 免费在线观看a视频| 日韩黄色免费电影| 日韩av电影免费在线观看| 不卡av播放| 亚洲男人的天堂在线播放| 天天综合天天干| 99久久亚洲一区二区三区青草| 免费无码毛片一区二三区| 久久久久观看| 欧美日韩一区二区免费在线观看| 欧美亚州一区二区三区| 国产熟女一区二区丰满| 综合婷婷亚洲小说| 国产农村妇女精品久久| 一区二区电影在线观看| 51国偷自产一区二区三区| 综合久久2019| 欧美精品一区二区三区蜜桃| 亚洲国产综合久久| 久久综合久久综合亚洲| 日本熟妇人妻xxxxx| 精品大片一区二区| 国产精品一区二区三区免费视频 | 免费在线观看亚洲视频| 性欧美xxxx免费岛国不卡电影| 国产91色在线播放| 欧美成人xxx| 精品久久一区二区三区| 亚洲日本韩国在线| 国产日韩欧美麻豆| 黄色小视频免费网站| 欧美精品观看| 精品一区二区国产| 高清在线一区| 欧美日本亚洲视频| 三级在线视频| 欧美人牲a欧美精品| 青青草免费av| 26uuu精品一区二区三区四区在线| 黄色片在线免费| 91精品二区| 久久另类ts人妖一区二区| 精品国模一区二区三区| 美女国内精品自产拍在线播放| 日本成人动漫在线观看| 欧美一a一片一级一片| 欧美精品色哟哟| 国产调教视频一区| 少妇熟女视频一区二区三区| 无码人妻aⅴ一区二区三区玉蒲团| 免费视频国产一区| 91天堂在线视频| 日韩激情电影免费看| www.午夜精品| 青青草观看免费视频在线| 91麻豆精品国产无毒不卡在线观看| 国产成人一区二区三区别| 免费在线一级视频| 欧美另类久久久品| 91浏览器在线观看| 国产精品福利av| 变态另类丨国产精品| 国产一区在线观看视频| 日本va中文字幕| 国内激情久久| 手机成人av在线| 久久99精品久久久久久园产越南| 亚洲一区二区中文字幕| 超碰这里只有精品| 91精品国产高清久久久久久| 2021国产在线| 在线视频亚洲欧美| 无码国产精品一区二区色情男同 | **性色生活片久久毛片| 自拍偷拍亚洲天堂| 成人美女视频在线观看| 黄色片免费网址| 久久国产欧美日韩精品| 国产无套内射久久久国产| 国产综合激情| 99久re热视频精品98| 婷婷综合视频| 中文字幕精品—区二区日日骚| 蜜桃国内精品久久久久软件9| 国产成人精品一区二区三区福利 | 亚洲中字黄色| 97碰在线视频| 欧美日韩国产一区精品一区| 咪咪色在线视频| 日韩av有码| 亚洲精品成人a8198a| 国产精品片aa在线观看| 欧美高清性xxxxhdvideosex| 日韩深夜福利| 久久综合久久久| 任你躁在线精品免费| 国产综合动作在线观看| 精品亚洲精品| 精品久久久久久中文字幕动漫| 成人精品毛片| 国产一区二区高清视频| 91精品国产自产在线丝袜啪| 国产99在线免费| 国产精品毛片久久久| 韩国精品一区二区三区六区色诱| 成人盗摄视频| 久久99国产精品99久久| 亚洲精品播放| 亚洲二区三区四区| 国产老女人乱淫免费| 午夜视频在线观看一区二区三区| 免费毛片在线播放免费| 亚洲一区二区三区影院| 日本少妇裸体做爰| 欧美色视频日本版| 色老头一区二区| 欧美美女黄视频| 99精品视频在线播放免费| 欧美一级在线观看| 欧美 日韩 国产 在线| 日韩国产精品一区| 999国产在线视频| 久久艳片www.17c.com| 五月花成人网| 欧美一区二区三区精品电影| 精品免费av在线| 国产在线999| aaa国产精品视频| 久久久久久亚洲精品不卡4k岛国 | 国产在线一二区| 精品国产福利视频| 一级一级黄色片| 91精品国产色综合久久不卡电影| 懂色av成人一区二区三区| 日韩精品一二三四区| aaa在线观看| 欧美激情手机在线视频| 写真福利精品福利在线观看| 国产欧美精品一区二区三区介绍| 亚洲精品在线国产| 欧美三日本三级少妇三99| 亚洲mv大片欧洲mv大片| 成人在线观看你懂的| 日韩精品五月天| 中文字幕在线播放一区二区| 久久久久久久久97黄色工厂| 青花影视在线观看免费高清| 欧美日韩激情美女| 97超碰人人模人人人爽人人爱| 亚洲精品mp4| 久久国产精品一区| 日韩av大片在线| 亚洲精选av| 一区二区三区四区视频在线| 99国产精品久久久久久久成人热 | 成人av资源网站| 国产精品www爽爽爽| 亚洲五码中文字幕| 一级黄色片免费| 国产丝袜一区二区| 国产又色又爽又黄刺激在线视频| 国产精品国产三级国产专播精品人 | 成人免费福利在线| 日韩美脚连裤袜丝袜在线| 中文字幕黄色大片| 久久午夜精品一区二区| 精品人妻人人做人人爽夜夜爽| 日本一区二区三区四区在线视频 | 91久久精品一区二区别| 欧美一级精品| 国产乱子夫妻xx黑人xyx真爽| 国产麻豆成人精品| av片在线免费看| 在线观看国产一区二区| 日韩一级片免费在线观看| 蜜臀久久99精品久久久无需会员| 香蕉成人影院| 另类欧美小说| 最新亚洲一区| 97精品人人妻人人| 一卡二卡三卡日韩欧美| 97精品久久人人爽人人爽| 亚洲欧洲日产国产网站| 忘忧草在线日韩www影院| 懂色av一区二区三区在线播放| 天天影视天天精品| 五月婷婷丁香色| 中文一区二区完整视频在线观看| 亚洲av中文无码乱人伦在线视色| 日韩精品免费在线视频观看| av老司机在线观看| 春色成人在线视频| 亚洲电影在线| 日本一区二区在线观看视频| 亚洲综合一区二区| 丰满人妻一区二区三区免费| 欧美人成在线视频| 高清日韩中文字幕| 国产精品裸体瑜伽视频| 国产1区2区3区精品美女| 久久久久久久蜜桃| 精品国产三级a在线观看| 国产丝袜在线播放| 国产精选一区二区| 亚洲大胆视频| 亚洲第九十七页| 色哟哟在线观看一区二区三区| 户外极限露出调教在线视频| 国产成人精品久久二区二区| 成人6969www免费视频| 中文字幕一区二区三区四区在线视频| 国产肉丝袜一区二区| 日韩乱码一区二区三区| 色偷偷偷综合中文字幕;dd| www.久久热| 97碰在线视频| 2020国产精品自拍| 中文字幕在线观看视频一区| 久久久精品久久| 97青娱国产盛宴精品视频| 日日鲁鲁鲁夜夜爽爽狠狠视频97| 久久久一区二区三区| 一本久道久久综合无码中文| 欧美成人免费全部观看天天性色| 激情小说一区| 日韩黄色片视频| 久久99久久人婷婷精品综合| 91精品久久久久久久久久入口| 精品国产精品久久一区免费式| 伊人成人222| 亚洲一区二区av在线| 青青草免费在线视频| 国产中文字幕亚洲| 国产综合精品| 日韩乱码人妻无码中文字幕久久| 欧美中文一区二区三区| 亚洲淫性视频| 麻豆精品传媒视频| 国内精品伊人久久久久av一坑| 精品处破女学生| 夜夜嗨av色一区二区不卡| 成人污版视频| 能在线观看的av| 综合色中文字幕| 日夜干在线视频| 91精品久久久久久久久久另类 | 中文字幕人妻互换av久久| 欧美夫妻性生活xx| 成人精品中文字幕| 国产麻豆xxxvideo实拍| 欧美日韩国产乱码电影| 国产在线精彩视频|