日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL-索引优化篇(1)_安装演示库 [前缀索引、联合索引、覆盖索引] explain参数

發(fā)布時(shí)間:2025/3/21 数据库 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL-索引优化篇(1)_安装演示库 [前缀索引、联合索引、覆盖索引] explain参数 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 生猛干貨
  • 官方文檔
  • 安裝演示數(shù)據(jù)庫sakila
  • 索引優(yōu)化策略
    • 索引列上不能使用表達(dá)式或者函數(shù)
    • 前綴索引和索引列的選擇性
      • 前綴索引的創(chuàng)建
      • 索引列的選擇性
      • 前綴索引的優(yōu)缺點(diǎn)
    • 聯(lián)合索引
      • 如何選擇索引列的順序
    • 覆蓋索引
      • 定義
      • 優(yōu)點(diǎn)
      • 無法使用覆蓋索引的情況
      • 演示
  • explain的幾個(gè)參數(shù)的說明
  • 搞定MySQL

生猛干貨

帶你搞定MySQL實(shí)戰(zhàn),輕松對(duì)應(yīng)海量業(yè)務(wù)處理及高并發(fā)需求,從容應(yīng)對(duì)大場(chǎng)面試


官方文檔

https://dev.mysql.com/doc/

如果英文不好的話,可以參考 searchdoc 翻譯的中文版本

http://www.searchdoc.cn/rdbms/mysql/dev.mysql.com/doc/refman/5.7/en/index.com.coder114.cn.html


安裝演示數(shù)據(jù)庫sakila

[root@artisan ~]# wget http://downloads.mysql.com/docs/sakila-db.tar.gz ..... ..... ..... 2020-02-01 21:31:15 (2.74 KB/s) - ‘sakila-db.tar.gz’ saved [732161/732161][root@artisan ~]# tar -xvzf sakila-db.tar.gz sakila-db/ sakila-db/sakila-data.sql sakila-db/sakila-schema.sql sakila-db/sakila.mwb [root@artisan ~]# cd sakila-db [root@artisan sakila-db]# ls sakila-data.sql sakila.mwb sakila-schema.sql [root@artisan sakila-db]# mysql -uroot -p < sakila-schema.sql Enter password: [root@artisan sakila-db]# mysql -uroot -p < sakila-data.sql Enter password: [root@artisan sakila-db]#


索引優(yōu)化策略

索引列上不能使用表達(dá)式或者函數(shù)

舉個(gè)例子

select .... from t_order where to_days(out_date) - to_days(current_date) < = 30

即使我們?cè)趏ut_date建立了 B樹索引,因?yàn)槭褂昧撕瘮?shù)to_days,無法走索引。

那該如何改造呢? ------------> 如下

select .... from t_order where out_date <= data_add(current_date , interval 30 day) ;


前綴索引和索引列的選擇性

當(dāng)索引是很長(zhǎng)的字符序列(比如BLOB,TEXT,或者很長(zhǎng)的VARCHAR)時(shí),這個(gè)索引將會(huì)很占內(nèi)存,而且會(huì)很慢,這時(shí)候就會(huì)用到前綴索引了。所謂的前綴索引就是去索引的前面幾個(gè)字母作為索引,但是要降低索引的重復(fù)率,索引我們還必須要判斷前綴索引的重復(fù)率

前綴索引的創(chuàng)建

創(chuàng)建前綴索引

create index index_name on table(col_name(n));

注意建立索引的區(qū)別 col_name(n)

這個(gè)n的長(zhǎng)度,取悅于存儲(chǔ)引擎

  • innodb 最大767個(gè)字節(jié)

  • myIsam 最大1000個(gè)直接

索引列的選擇性

索引的選擇性是指不重復(fù)的索引值和表的記錄數(shù)的比值

選擇性越高,查詢效率越快。 因?yàn)檫x擇性高的索引可以讓MySQL在查找時(shí)過濾掉更多的行。唯一索引的選擇性是1,這是最好的索引選擇性,性能也是最好的。

舉個(gè)例子:

有4條記錄

如果前綴索引,我們創(chuàng)建的時(shí)候,長(zhǎng)度設(shè)置的是2 , 那么


不重復(fù)的索引為 2 ,總記錄數(shù)為4 , 索引選擇性 0.5


如果設(shè)置為 3 ,則

不重復(fù)的索引為 4 ,總記錄數(shù)為4 , 索引選擇性1 . 此時(shí),性能最高,因?yàn)椴挥眠^濾數(shù)據(jù)啊。

合理選擇,對(duì)提高查詢性能幫助很大


前綴索引的優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

  • 前綴索引是一種能使索引更小,更快的有效辦法 。

缺點(diǎn):

  • mysql無法使用其前綴索引做ORDER BY和GROUP BY,也無法使用前綴索引做覆蓋掃描。

聯(lián)合索引

如何選擇索引列的順序

  • 經(jīng)常會(huì)被使用到的列優(yōu)先,放到聯(lián)合索引的最左邊 。

    但也不是絕對(duì)的,舉個(gè)例子 有個(gè)狀態(tài) state,就幾個(gè)值, 選擇性很差(因?yàn)楦鶕?jù)每個(gè)state,篩選出來的數(shù)據(jù)太多了。。。)就不適合放到聯(lián)合索引的最左邊 ,放到了最左邊,mysql也不一定使用

  • 選擇性高的列優(yōu)先 。

    啥叫選擇性高的列? 比如根據(jù)這個(gè)列 經(jīng)過篩選后,能夠把大部分的數(shù)據(jù)都過濾掉,之剩下很少的數(shù)據(jù),那么就可以把這列稱為選擇性高的列。

  • 寬度小的列優(yōu)先

    當(dāng)然了有個(gè)前提,不違反選擇性。 寬度小意味著I/O 少,效率高


覆蓋索引

定義

覆蓋索引: 如果一個(gè)索引包含(或覆蓋)所有需要查詢的字段的值 ,簡(jiǎn)言之----->只需掃描索列而無須回表查非索引列的字段。


優(yōu)點(diǎn)

  • 可優(yōu)化緩存,減少磁盤I/O操作

    舉個(gè)例子: 一個(gè)表 15個(gè)字段, 索引字段 3個(gè), 我們就查詢這3個(gè)索引列的值,而不用回表,查詢的字段少,可以緩存更多的數(shù)據(jù),同時(shí)從內(nèi)存中獲取,可以極大的減少磁盤I/O操作

  • 可以減少隨機(jī)I/O, 變隨機(jī)I/O為順序I/O操作

  • 可以避免對(duì)Innodb主鍵索引的二次查詢

  • 可以避免MyISAM表進(jìn)行系統(tǒng)調(diào)用


無法使用覆蓋索引的情況

  • 有些存儲(chǔ)引擎不支持覆蓋索引
  • 如果查詢中使用了太多的列,尤其是那種查詢?nèi)孔侄蔚?#xff0c;或者 select * 的
  • 使用了雙% 號(hào)的like查詢

演示

我們用剛才導(dǎo)入的 sakila 數(shù)據(jù) 來演示下

select * 無法使用覆蓋索引的演示:

[root@artisan sakila-db]# mysql -uroot -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 63 Server version: 5.7.29-log MySQL Community Server (GPL) ....... ....... mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | artisan | | artisanBinLog | | data | | mysql | | performance_schema | | sakila | | sys | +--------------------+ 8 rows in set (0.01 sec)mysql> use sakila; No connection. Trying to reconnect... Connection id: 64 Current database: *** NONE ***Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -ADatabase changed mysql> show tables; +----------------------------+ | Tables_in_sakila | +----------------------------+ | actor | | actor_info | | address | | category | | city | | country | | customer | | customer_list | | film | | film_actor | | film_category | | film_list | | film_text | | inventory | | language | | nicer_but_slower_film_list | | payment | | rental | | sales_by_film_category | | sales_by_store | | staff | | staff_list | | store | +----------------------------+ 23 rows in set (0.00 sec)mysql> desc film; +----------------------+---------------------------------------------------------------------+------+-----+-------------------+-----------------------------+ | Field | Type | Null | Key | Default | Extra | +----------------------+---------------------------------------------------------------------+------+-----+-------------------+-----------------------------+ | film_id | smallint(5) unsigned | NO | PRI | NULL | auto_increment | | title | varchar(128) | NO | MUL | NULL | | | description | text | YES | | NULL | | | release_year | year(4) | YES | | NULL | | | language_id | tinyint(3) unsigned | NO | MUL | NULL | | | original_language_id | tinyint(3) unsigned | YES | MUL | NULL | | | rental_duration | tinyint(3) unsigned | NO | | 3 | | | rental_rate | decimal(4,2) | NO | | 4.99 | | | length | smallint(5) unsigned | YES | | NULL | | | replacement_cost | decimal(5,2) | NO | | 19.99 | | | rating | enum('G','PG','PG-13','R','NC-17') | YES | | G | | | special_features | set('Trailers','Commentaries','Deleted Scenes','Behind the Scenes') | YES | | NULL | | | last_update | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | +----------------------+---------------------------------------------------------------------+------+-----+-------------------+-----------------------------+ 13 rows in set (0.00 sec)# 查詢 索引列 language_id 重點(diǎn)看 Extra mysql> explain select language_id from film where language_id = 1 \G ; *************************** 1. row ***************************id: 1select_type: SIMPLEtable: filmpartitions: NULLtype: ref possible_keys: idx_fk_language_id -----> 可能用的索引 key: idx_fk_language_id ----------------> 實(shí)際使用的索引key_len: 1ref: constrows: 1000filtered: 100.00Extra: Using index ---------------->使用了索引,因?yàn)閮H查詢了索引列,這里就是覆蓋索引 1 row in set, 1 warning (0.07 sec)ERROR: No query specified# 查看執(zhí)行計(jì)劃 重點(diǎn)看 Extra mysql> explain select * from film where language_id = 1 \G ; *************************** 1. row ***************************id: 1select_type: SIMPLEtable: filmpartitions: NULLtype: ALL ----------------------> 連接類型 possible_keys: idx_fk_language_id -----> 可用的索引key: NULL ----------------> 實(shí)際的索引key_len: NULLref: NULLrows: 1000filtered: 100.00Extra: Using where --------------------> using where:表示優(yōu)化器需要通過索引回表查詢數(shù)據(jù); 1 row in set, 1 warning (0.00 sec)ERROR: No query specifiedmysql>

在來看個(gè)例子

mysql> show create table actor \G ; *************************** 1. row ***************************Table: actor Create Table: CREATE TABLE `actor` (`actor_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,`first_name` varchar(45) NOT NULL,`last_name` varchar(45) NOT NULL,`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`actor_id`),KEY `idx_actor_last_name` (`last_name`) ) ENGINE=InnoDB AUTO_INCREMENT=201 DEFAULT CHARSET=utf8mb4 1 row in set (0.00 sec)ERROR: No query specifiedmysql> explain select actor_id , last_name from actor where last_name = 'Joe' \G *************************** 1. row ***************************id: 1select_type: SIMPLEtable: actorpartitions: NULLtype: ref possible_keys: idx_actor_last_namekey: idx_actor_last_namekey_len: 182ref: constrows: 1filtered: 100.00Extra: Using index ------> using index 表示直接訪問索引就足夠獲取到所需要的數(shù)據(jù),不需要通過索引回表; 1 row in set, 1 warning (0.30 sec)

主鍵 actor_id ,默認(rèn)就是索引 ,所以雖然增加了 actor_id , last_name也是索引列(創(chuàng)建primary key的時(shí)候肯定會(huì)創(chuàng)建一個(gè)unique index。),所以這個(gè)查詢也是使用了覆蓋索引。


explain的幾個(gè)參數(shù)的說明

id: 1select_type: SIMPLEtable: actorpartitions: NULLtype: ref possible_keys: idx_actor_last_namekey: idx_actor_last_namekey_len: 182ref: constrows: 1filtered: 100.00Extra: Using index
  • id

  • select_type: 查詢中每個(gè)select子句的類型

    (1) SIMPLE(簡(jiǎn)單SELECT,不使用UNION或子查詢等)

    (2) PRIMARY(查詢中若包含任何復(fù)雜的子部分,最外層的select被標(biāo)記為PRIMARY)

    (3) UNION(UNION中的第二個(gè)或后面的SELECT語句)

    (4) DEPENDENT UNION(UNION中的第二個(gè)或后面的SELECT語句,取決于外面的查詢)

    (5) UNION RESULT(UNION的結(jié)果)

    (6) SUBQUERY(子查詢中的第一個(gè)SELECT)

    (7) DEPENDENT SUBQUERY(子查詢中的第一個(gè)SELECT,取決于外面的查詢)

    (8) DERIVED(派生表的SELECT, FROM子句的子查詢)

    (9) UNCACHEABLE SUBQUERY(一個(gè)子查詢的結(jié)果不能被緩存,必須重新評(píng)估外鏈接的第一行)


  • type 代表連接類型

    常用的類型有: ALL, index, range, ref, eq_ref, const, system, NULL

    從左到右,性能從差到好 , ALL 最差, NULL最好

    ALL:Full Table Scan, MySQL將遍歷全表以找到匹配的行

    index: Full Index Scan,index與ALL區(qū)別為index類型只遍歷索引樹

    range:只檢索給定范圍的行,使用一個(gè)索引來選擇行

    ref: 表示上述表的連接匹配條件,即哪些列或常量被用于查找索引列上的值

    eq_ref: 類似ref,區(qū)別就在使用的索引是唯一索引,對(duì)于每個(gè)索引鍵值,表中只有一條記錄匹配,簡(jiǎn)單來說,就是多表連接中使用primary key或者 unique key作為關(guān)聯(lián)條件

    const、system: 當(dāng)MySQL對(duì)查詢某部分進(jìn)行優(yōu)化,并轉(zhuǎn)換為一個(gè)常量時(shí),使用這些類型訪問。如將主鍵置于where列表中,MySQL就能將該查詢轉(zhuǎn)換為一個(gè)常量,system是const類型的特例,當(dāng)查詢的表只有一行的情況下,使用system

    NULL: MySQL在優(yōu)化過程中分解語句,執(zhí)行時(shí)甚至不用訪問表或索引,例如從一個(gè)索引列里選取最小值可以通過單獨(dú)索引查找完成。


  • possible_keys: 可用的索引 ,實(shí)際不一定用

  • keys : MyQL實(shí)際的索引

  • key_len: 表示索引中使用的字節(jié)數(shù)

  • extra (需重點(diǎn)關(guān)注)
    1) using tempoaray : 中間使用了臨時(shí)表
    2) using index 表示直接訪問索引就足夠獲取到所需要的數(shù)據(jù),不需要通過索引回表;
    3) using index condition:5.6加入 ,會(huì)先條件過濾索引,過濾完索引后找到所有符合索引條件的數(shù)據(jù)行,隨后用 WHERE 子句中的其他條件去過濾這些數(shù)據(jù)行;
    4) using where: 未使用索引,通過where條件過濾


搞定MySQL

總結(jié)

以上是生活随笔為你收集整理的MySQL-索引优化篇(1)_安装演示库 [前缀索引、联合索引、覆盖索引] explain参数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。