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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

数据库

MySQL性能分析工具

發(fā)布時(shí)間:2024/3/13 数据库 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL性能分析工具 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

第一節(jié) 統(tǒng)計(jì)SQL執(zhí)行成本

統(tǒng)計(jì)SQL的查詢成本: last_query_cost
一條SQL查詢語(yǔ)句在執(zhí)行前需要確定查詢執(zhí)行計(jì)劃,如果存在多種執(zhí)行計(jì)劃的話,MySQL會(huì)計(jì)算每個(gè)執(zhí)行計(jì)劃所需要的成本,從中選擇成本最小的一個(gè)作為最終執(zhí)行的執(zhí)行計(jì)劃。
如果我們想要查看某條SQL語(yǔ)句的查詢成本,可以在執(zhí)行完這條SQL語(yǔ)句之后,通過(guò)查看當(dāng)前會(huì)話中的last_query_cost變量值來(lái)得到當(dāng)前查詢的成本。它通常也是我們?cè)u(píng)價(jià)一個(gè)查詢的執(zhí)行效率的一個(gè)常用指標(biāo)。這個(gè)查詢成本對(duì)應(yīng)的是SQL語(yǔ)句所需要讀取的頁(yè)的數(shù)量。
SQL查詢是一個(gè)動(dòng)態(tài)的過(guò)程,從頁(yè)加載的角度來(lái)看,我們可以得到以下兩點(diǎn)結(jié)論:

  • 位置決定效率。如果頁(yè)就在數(shù)據(jù)庫(kù)緩沖池中,那么效率是最高的,否則還需要從磁盤(pán)中進(jìn)行讀取,當(dāng)然針對(duì)單個(gè)頁(yè)的讀取來(lái)說(shuō),如果頁(yè)存在于內(nèi)存中,會(huì)比在磁盤(pán)中讀取效率高很多。
  • 批量決定效率。如果我們從磁盤(pán)中對(duì)單一頁(yè)進(jìn)行隨機(jī)讀,那么效率是很低的(差不多10ms),而采用順序讀取的方式,批量對(duì)頁(yè)進(jìn)行讀取,平均一頁(yè)的讀取效率就會(huì)提升很多,甚至要快于單個(gè)頁(yè)面在內(nèi)存中的隨機(jī)讀取。
    所以說(shuō),遇到I/O并不用擔(dān)心,方法找對(duì)了,效率還是很高的。我們首先要考慮數(shù)據(jù)存放的位置,如果是經(jīng)常使用的數(shù)據(jù)就要盡量放到緩沖池中,其次我們可以充分利用磁盤(pán)的吞吐能力,一次性批量讀取數(shù)據(jù),這樣單個(gè)頁(yè)的讀取效率也就得到了提升。
  • 第二節(jié) 分析查詢語(yǔ)句:EXPLAIN

    2.1 基本語(yǔ)法

    如果我們想看看某個(gè)查詢的執(zhí)行計(jì)劃的話,可以在具體的查詢語(yǔ)句前邊加一個(gè) EXPLAIN ,就像這樣:

    EXPLAIN SELECT 1;

    EXPLAIN 語(yǔ)句輸出的各個(gè)列的作用如下:

    列名描述
    id在一個(gè)大的查詢語(yǔ)句中每個(gè)SELECT關(guān)鍵字都對(duì)應(yīng)一個(gè) 唯一的id
    select_typeSELECT關(guān)鍵字對(duì)應(yīng)的那個(gè)查詢的類型
    table表名
    partitions匹配的分區(qū)信息
    type☆針對(duì)單表的訪問(wèn)方法
    possible_keys可能用到的索引
    key實(shí)際上使用的索引
    key_len ☆實(shí)際使用到的索引長(zhǎng)度
    ref當(dāng)使用索引列等值查詢時(shí),與索引列進(jìn)行等值匹配的對(duì)象信息
    rows ☆預(yù)估的需要讀取的記錄條數(shù)
    filtered某個(gè)表經(jīng)過(guò)搜索條件過(guò)濾后剩余記錄條數(shù)的百分比
    Extra ☆一些額外的信息

    2.2 詳細(xì)解釋

    為了讓大家有比較好的體驗(yàn),下面調(diào)整了下 EXPLAIN 輸出列的順序。

    2.2.1 table

    不論我們的查詢語(yǔ)句有多復(fù)雜,里邊兒包含了多少個(gè)表 ,到最后也是需要對(duì)每個(gè)表進(jìn)行 單表訪問(wèn)的,所以MySQL規(guī)定EXPLAIN語(yǔ)句輸出的每條記錄都對(duì)應(yīng)著某個(gè)單表的訪問(wèn)方法,該條記錄的table列代表著該表的表名(有時(shí)不是真實(shí)的表名字,可能是簡(jiǎn)稱)。

    2.2.2 id

    我們寫(xiě)的查詢語(yǔ)句一般都以 SELECT 關(guān)鍵字開(kāi)頭,比較簡(jiǎn)單的查詢語(yǔ)句里只有一個(gè) SELECT 關(guān)鍵字,比如下邊這個(gè)查詢語(yǔ)句:

    SELECT * FROM s1 WHERE key1 = 'a'; mysql> EXPLAIN SELECT * FROM s1 WHERE key1 = 'a’;


    稍微復(fù)雜一點(diǎn)的連接查詢中也只有一個(gè) SELECT 關(guān)鍵字,比如:

    SELECT * FROM s1 INNER JOIN s2 ON s1.key1 = s2.key1 WHERE s1.common_field = 'a'; mysql> EXPLAIN SELECT * FROM s1 INNER JOIN s2;

    mysql> EXPLAIN SELECT * FROM s1 WHERE key1 IN (SELECT key1 FROM s2) OR key3 = 'a';

    mysql> EXPLAIN SELECT * FROM s1 WHERE key1 IN (SELECT key2 FROM s2 WHERE common_field= 'a');


    查看mysql優(yōu)化后的sql:

    EXPLAIN EXTENDED SELECT * FROM s1 WHERE key1 IN (SELECT key2 FROM s2 WHERE common_field= 'a'); SHOW WARNINGS;

    小結(jié):
    id如果相同,可以認(rèn)為是一組,從上往下順序執(zhí)行
    在所有組中,id值越大,優(yōu)先級(jí)越高,越先執(zhí)行
    關(guān)注點(diǎn):id號(hào)每個(gè)號(hào)碼,表示一次獨(dú)立的查詢, 一個(gè)sql的查詢次數(shù)越少越好

    2.2.3 select_type

    名稱描述
    SIMPLE簡(jiǎn)單查詢(不使用UNION或子查詢)
    PRIMARY最外層的查詢
    UNIONUNION中第二個(gè)語(yǔ)句或后面的語(yǔ)句
    UNION RESULTUNION每個(gè)結(jié)果集的取出來(lái)后,進(jìn)行合并操作
    dependentSubquery子查詢中的第一個(gè) SELECT,依賴了外面的查詢
    derived派生表,子查詢?cè)?FROM子句中


    SIMPLE
    SIMPLE,最簡(jiǎn)單的查詢方式。

    EXPLAIN SELECT * FROM `sys_user`

    primary、union、union result
    PRIMARY,主查詢。
    UNION,UNION中第二個(gè)語(yǔ)句或后面的語(yǔ)句。
    UNION RESULT,UNION每個(gè)結(jié)果集的取出來(lái)后,進(jìn)行合并操作。

    EXPLAIN select * from sys_user where user_id=1 union select * from sys_user where user_id=2

    Subquery
    子查詢:#如果包含子查詢的查詢語(yǔ)句不能夠轉(zhuǎn)為對(duì)應(yīng)的semi-join(多表連接)的形式,并且該子查詢是不相關(guān)子查詢。#該子查詢的第一個(gè)SELECT'關(guān)鍵字代表的那個(gè)查詢的select type '就是SUBQUERY

    EXPLAIN SELECT* FROMcoupon_give_gift WHEREcoupon_id = ( SELECT coupon_id FROM coupon WHERE id = '111);

    EXPLAIN SELECT* FROMcoupon_give_gift WHEREcoupon_id in ( SELECT coupon_id FROM coupon WHERE id = '111);


    查詢優(yōu)化器把in換成關(guān)聯(lián)查詢

    dependentSubquery
    DEPENDENT SUBQUERY,子查詢中內(nèi)層的第一個(gè)SELECT,依賴于外部查詢的結(jié)果集。

    EXPLAIN SELECT* FROMcoupon_give_gift WHEREcoupon_id = (SELECT sub_title FROM coupon WHERE coupon_give_gift.coupon_id = coupon.coupon_id );


    derived
    DERIVED,派生表,子查詢?cè)?FROM子句中。

    explain select * from ( select user_id,count(*) from sys_user group by user_id ) user1

    2.2.4 partitions

    EXPLAIN SELECT * FROM user_partitions WHERE id>200;

    查詢id大于200(200>100,p1分區(qū))的記錄,查看執(zhí)行計(jì)劃,partitions是p1,符合我們的分區(qū)規(guī)則。

    2.2.5 type

    完整的訪問(wèn)方法如下: system , const , eq_ref , ref , fulltext , ref_or_null ,index_merge , unique_subquery , index_subquery , range , index , ALL 。

    system : 該表只有一行(相當(dāng)于系統(tǒng)表),system是const類型的特例
    const:當(dāng)我們根據(jù)主鍵或者唯一二級(jí)索引列與常數(shù)進(jìn)行等值匹配時(shí),對(duì)單表的訪問(wèn)方法就是`const ’

    mysql> EXPLAIN SELECT * FROM interests where interests_id = 'CRDB951AF8FE05641140FA8FC6638A2B62D20210113016’;


    eq_ref:#在連接查詢時(shí),如果被驅(qū)動(dòng)表是通過(guò)主鍵或者唯一二級(jí)索引列等值匹配的方式進(jìn)行訪問(wèn)的(如果該主鍵或者唯一二級(jí)索引是聯(lián)合索引的話,所有的索引列都必須進(jìn)行等值比較),則對(duì)該被驅(qū)動(dòng)表的訪問(wèn)方法就是eq _ref。

    EXPLAIN SELECT * FROM coupon c LEFT JOIN coupon_put_rule cpr on c.coupon_id = cpr.id;


    ref:當(dāng)通過(guò)普通的二級(jí)索引列與常量進(jìn)行等值匹配時(shí)來(lái)查詢某個(gè)表,那么對(duì)該表的訪問(wèn)方法就可能是`ref’,聯(lián)合索引時(shí)只匹配部分字段也為ref。

    EXPLAIN SELECT * FROM coupon_store where coupon_id = 'C5BE9A420C9C26F07580DA1EB13D6A28' and store_id = '3570012;


    ref_or_null:當(dāng)對(duì)普通二級(jí)索引進(jìn)行等值匹配查詢,該索引列的值也可以是NULL值時(shí),那么對(duì)該表的訪問(wèn)方法就是‘ref or null`

    EXPLAIN SELECT * FROM coupon where promotion_id = 'C5BE9A420C9C26F07580DA1EB13D6A28' or promotion_id is null;


    index_merge:此類型表示使用了索引合并優(yōu)化,表示一個(gè)查詢里面用到了多個(gè)索引

    EXPLAIN SELECT * FROM coupon where promotion_id = 'C5BE9A420C9C26F07580DD6A28' or coupon_id = 'C5BE9A42DA1EB13D6A8';


    unique subquery :是針對(duì)在一些包含’IN子查詢的查詢語(yǔ)句中,如果查詢優(yōu)化器決定將IN子查詢轉(zhuǎn)換為EXISTS子查詢,而且子查詢可以使用到主鍵進(jìn)行等值匹配的話,那么該子查詢執(zhí)行計(jì)劃的 type '列的值就是unique_subquery

    EXPLAIN SELECT* FROMcoupon_give_gift WHEREcoupon_id in (SELECT id FROM coupon WHERE coupon_give_gift.coupon_id = coupon.coupon_id ) or give_quantity = 1;


    range:表示使用了范圍類型的查詢,一般出現(xiàn)在使用了<>, >, >=, <, <=, IS NULL, <=>, BETWEEN, LIKE, 貨 IN() 之類的字句和常量值作比較時(shí)

    EXPLAIN SELECT * FROM coupon where coupon_id in ('111','222','333','444')

    index:當(dāng)我們可以使用索引覆蓋,但需要掃描全部的索引記錄時(shí),該表的訪問(wèn)方法就是index。

    EXPLAIN SELECT coupon_id FROM coupon_give_gift where give_coupon_id = '111';

    ALL:全表掃描。
    上述分析的過(guò)程為從上至下,效率一次降低。

    2.2.6 possible_keys和key

    在EXPLAIN語(yǔ)句輸出的執(zhí)行計(jì)劃中,possible_keys列表示在某個(gè)查詢語(yǔ)句中,對(duì)某個(gè)表執(zhí)行單表查詢時(shí)可能用到的索引有哪些。一般查詢涉及到的字段上若存在索引,則該索引將被列出,但不一定被查詢使用。key列表示實(shí)際用到的索引有哪些,如果為NULL,則沒(méi)有使用索引。比方說(shuō)下邊這個(gè)查詢:

    EXPLAIN SELECT coupon_id FROM coupon WHERE coupon_id = '111' and promotion_id = '111;

    EXPLAIN SELECT coupon_id FROM coupon WHERE coupon_id = '111’or promotion_id = '111';

    2.2.7 key_len

    實(shí)際使用到的索引長(zhǎng)度(即:字節(jié)數(shù))#幫你檢查是否充分的利用上了索引,同一個(gè)索引`值越大越好’,主要針對(duì)聯(lián)合索引。

    列類型KEY_LEN備注
    id intkey_len = 4+1int為4bytes,允許為NULL,加1byte(1字節(jié)用來(lái)記錄是否為null)
    id bigint not nullkey_len=8bigint為8bytes
    user char(30) utf8key_len=30*3+1utf8每個(gè)字符為3bytes,允許為NULL,加1byte
    user varchar(30) not null utf8key_len=30*3+2utf8每個(gè)字符為3bytes,變長(zhǎng)數(shù)據(jù)類型,加2bytes(2字節(jié)用來(lái)記錄實(shí)際長(zhǎng)度)
    user varchar(30) utf8key_len=30*3+2+1utf8每個(gè)字符為3bytes,允許為NULL,加1byte,變長(zhǎng)數(shù)據(jù)類型,加2bytes
    EXPLAIN SELECT * FROM s1 WHERE id = 1;EXPLAIN SELECT * FROM s1 WHERE key2 = 2;EXPLAIN SELECT * FROM s1 WHERE key1 = 'a';EXPLAIN SELECT * FROM s1 WHERE key_part1 = 'a';EXPLAIN SELECT * FROM s1 WHERE key_part1 = 'a' AND key_part2 = 'b';

    2.2.8 ref

    當(dāng)使用索引列等值查詢時(shí),與索引列進(jìn)行等值匹配的對(duì)象信息。比如只是一個(gè)常數(shù)或者是某個(gè)列。

    EXPLAIN SELECT coupon_id FROM coupon WHERE coupon_id = '111';

    EXPLAIN SELECT* FROMcoupon inner JOINcoupon_give_gift on coupon_give_gift.coupon_id = coupon.coupon_id;

    2.2.9 rows

    預(yù)估的需要讀取的記錄條數(shù),值越小越好。

    EXPLAIN SELECT * FROM coupon WHERE id < 100;

    2.2.10 filtered

    某個(gè)表經(jīng)過(guò)搜索條件過(guò)濾后剩余記錄條數(shù)的百分比。如果使用的是索引執(zhí)行的單表掃描,那么計(jì)算時(shí)需要估計(jì)出滿足除使用到對(duì)應(yīng)索引的搜索條件外的其他搜索條件的記錄有多少條。

    EXPLAIN SELECT * FROM coupon WHERE id < 100 and campaign_coupon_code = '202007071120';

    2.2.11 Extra

    顧名思義,Extra列是用來(lái)說(shuō)明一些額外信息的,包含不適合在其他列中顯示但十分重要的額外信息。我們可以通過(guò)這些額外信息來(lái)更準(zhǔn)確的理解MySQL到底將如何執(zhí)行給定的查詢語(yǔ)句。MySQL提供的額外信息有好幾十個(gè),我們就不一個(gè)一個(gè)介紹了,所以只挑比較重要的額外信息介紹給大家。

  • No tables used 當(dāng)查詢語(yǔ)句的沒(méi)有FROM子句時(shí)將會(huì)提示該額外信息。
  • EXPLAIN SELECT 1;


    2. Impossible where 查詢語(yǔ)句的WHERE子句永遠(yuǎn)為FALSE時(shí)將會(huì)提示該額外信息

    EXPLAIN SELECT * FROM s1 WHERE 1 != 1;


    3. Using where 當(dāng)我們使用全表掃描來(lái)執(zhí)行對(duì)某個(gè)表的查詢,并且該語(yǔ)句的where 子句中有針對(duì)該表的搜索條件時(shí),在Extra列中會(huì)提示上述額外信息。當(dāng)使用索引訪問(wèn)來(lái)執(zhí)行對(duì)某個(gè)表的查詢,并且該語(yǔ)句的WHERE子句中有除了該索引包含的列之外的其他搜索條件時(shí),在`Extra '列中也會(huì)提示上述額外信息。

    EXPLAIN SELECT * FROM coupon WHERE campaign_coupon_code = '111’; EXPLAIN SELECT * FROM coupon WHERE coupon_id = '111' and campaign_coupon_code = '111;


    4. Using index 當(dāng)我們查詢列表以及搜索條件中只包含屬于某個(gè)索引的列,也就是在可以使用覆蓋索引的情況下,在Extra列將會(huì)提示該額外信息。比方說(shuō)下邊這個(gè)查詢中只需要用到‘coupon_id’而不需要回表操作:

    EXPLAIN SELECT coupon_id FROM coupon WHERE coupon_id = '111;


    5. Using index condition 搜索條件中出現(xiàn)了索引列,按最左匹配原則無(wú)法匹配上,但是用到了索引下推。

    EXPLAIN SELECT * FROM s1 WHERE key_part1 = 'a' AND key_part3 = 'b';


    6. Using join buffer 在連接查詢執(zhí)行過(guò)程中,當(dāng)被驅(qū)動(dòng)表不能有效的利用索引加快訪問(wèn)速度,MySQL一般會(huì)為其分配一塊名叫`join buffer '的內(nèi)存塊來(lái)加快查詢速度,也就是我們所講的‘基于塊的嵌套循環(huán)算法’

    EXPLAIN SELECT * FROM s1 INNER JOIN s2 ON s1.common_field = s2.common_field;


    7. Using union 表示需要進(jìn)行索引合并的索引名稱,如果出現(xiàn)了’Using union(…)提示,說(shuō)明準(zhǔn)備使用union索引合并的方式執(zhí)行查詢; 出現(xiàn)了Using sort union(…)提示,說(shuō)明準(zhǔn)備使用’sort-Union `索引合并的方式執(zhí)行查詢。

    EXPLAIN SELECT * FROM s1 WHERE key1 = 'a' or key3 = 'a';

  • Using filesort 很多情況下排序操作無(wú)法使用到索引,只能在內(nèi)存中(記錄較少的時(shí)候)或者磁盤(pán)中(記錄較多的時(shí)候)進(jìn)行排序,Mysql把這種在內(nèi)存中或者磁盤(pán)上進(jìn)行排序的方式統(tǒng)稱為文件排序(英文名: ‘filesort’)。如果某個(gè)查詢需要使用文件排序的方式執(zhí)行查詢,就會(huì)在執(zhí)行計(jì)劃的Extra列中顯示’Using filesort `提示。
  • EXPLAIN SELECT * FROM s1 ORDER BY common_field LIMIT 10;

  • Using temporary 在許多查詢的執(zhí)行過(guò)程中,MySQL可能會(huì)借助臨時(shí)表來(lái)完成一些功能,比如去重、排序之類的,比如我們?cè)趫?zhí)行許多包含DISTINCT '、GROUP BY'、‘UNION等子句的查詢過(guò)程中,如果不能有效利用索引來(lái)完成查詢,MysQL很有可能尋求通過(guò)建立內(nèi)部的臨時(shí)表來(lái)執(zhí)行查詢。如果查詢中使用到了內(nèi)部的臨時(shí)表,在執(zhí)行#計(jì)劃的‘Extra列將會(huì)顯示Using temporary`提示。
  • EXPLAIN SELECT DISTINCT common_field FROM s1;

    2.3 擴(kuò)展

    2.3.1 最左匹配原則

    最左優(yōu)先,以最左邊的為起點(diǎn)任何連續(xù)的索引都能匹配上。同時(shí)遇到范圍查詢(>、<、between、like)就會(huì)停止匹配。
    為什么最左匹配:是因?yàn)閙ysql創(chuàng)建聯(lián)合索引時(shí),首先會(huì)對(duì)最左邊字段排序,也就是第一個(gè)字段,然后再在保證第一個(gè)字段有序的情況下,再排序第二個(gè)字段,以此類推。所以聯(lián)合索引最左列是絕對(duì)有序的,其他字段無(wú)序。舉個(gè)例子:可以把聯(lián)合索引看成“通訊錄”,姓名作為聯(lián)合索引,姓是第一列,名是第二列,當(dāng)查找人名時(shí),是先確定這個(gè)人姓再根據(jù)名確定人。只有名沒(méi)有姓就查不到。

    2.3.2 索引下推

    什么是索引下推
    索引下推(Index Condition Pushdown,簡(jiǎn)稱ICP),是MySQL5.6版本的新特性,它能減少回表查詢次數(shù),提高查詢效率。MySQL服務(wù)層負(fù)責(zé)SQL語(yǔ)法解析、生成執(zhí)行計(jì)劃等,并調(diào)用存儲(chǔ)引擎層去執(zhí)行數(shù)據(jù)的存儲(chǔ)和檢索。索引下推的下推其實(shí)就是指將部分上層(服務(wù)層)負(fù)責(zé)的事情,交給了下層(引擎層)去處理。

    索引下推優(yōu)化的原理
    先來(lái)看一下MySQL的大致框架

  • 不使用ICP索引掃描的過(guò)程


    如上圖所示:
    storage層:只將滿足index key條件的索引記錄對(duì)應(yīng)的整行記錄取出,返回給server層
    server 層:對(duì)返回的數(shù)據(jù),使用后面的where條件過(guò)濾,直至返回最后一行。

  • 使用ICP掃碼的過(guò)程

    如圖所示:
    storage層:首先將index key條件滿足的索引記錄區(qū)間確定,然后在索引上使用index filter進(jìn)行過(guò) 濾。將滿足的index filter條件的索引記錄才去回表取出整行記錄返回server層。不滿足index filter條件的索引記錄丟棄,不回表、也不會(huì)返回server層。
    server 層:對(duì)返回的數(shù)據(jù),使用table filter條件做最后的過(guò)濾。

  • 使用前后的成本差別
    使用ICP前,存儲(chǔ)層多返回了需要被index filter過(guò)濾掉的整行記錄。使用ICP后,直接就去掉了不滿足index filter條件的記錄,省去了他們回表和傳遞到server層的成本。ICP的 加速效果 取決于在存儲(chǔ)引擎內(nèi)通過(guò) ICP篩選 掉的數(shù)據(jù)的比例。

    使用ICP條件
    ① 只能用于二級(jí)索引(secondary index)
    ② explain顯示的執(zhí)行計(jì)劃中type值(join 類型)為 range 、ref 、eq_ref 或者 ref_or_null 。
    ③ 并非全部where條件都可以用ICP篩選,如果where條件的字段不在索引列中,還是要讀取整表的記錄到server端做where過(guò)濾。
    ④ ICP可以用于MyISAM和InnnoDB存儲(chǔ)引擎
    ⑤ MySQL 5.6版本的不支持分區(qū)表的ICP功能,5.7版本的開(kāi)始支持。
    ⑥ 當(dāng)SQL使用覆蓋索引時(shí),不支持ICP優(yōu)化方法

    2.3.2 前綴索引

    什么是前綴索引?
    前綴索引也叫局部索引,比如給身份證的前 10 位添加索引,類似這種給某列部分信息添加索引的方式叫做前綴索引。
    為什么要用前綴索引?
    前綴索引能有效減小索引文件的大小,讓每個(gè)索引頁(yè)可以保存更多的索引值,從而提高了索引查詢的速度。但前綴索引也有它的缺點(diǎn),不能在 order by 或者 group by 中觸發(fā)前綴索引,也不能把它們用于覆蓋索引。
    索引選擇性是什么?
      索引的選擇性,指的是不重復(fù)的索引值(基數(shù))和表記錄數(shù)的比值。選擇性是索引篩選能力的一個(gè)指標(biāo)。索引的取值范圍是 0—1 ,當(dāng)選擇性越大,索引價(jià)值也就越大。
      舉例說(shuō)明:假如有一張表格,總共有一萬(wàn)行的記錄,其中有一個(gè)性別列sex,這個(gè)列的包含選項(xiàng)就兩個(gè):男/女。那么,這個(gè)時(shí)候,這一列創(chuàng)建索引的話,索引的選擇性為萬(wàn)分之二,這時(shí)候,在性別這一列創(chuàng)建索引是沒(méi)有啥意義的。假設(shè)個(gè)極端情況,列內(nèi)的數(shù)據(jù)都是女,那么索引的選擇性為萬(wàn)分之一,其效率還不如直接進(jìn)行全表掃描。如果是主鍵索引的話,那么選擇性為1,索引價(jià)值比較大??梢灾苯痈鶕?jù)索引定位到數(shù)據(jù)。
    什么情況下適合使用前綴索引?
    當(dāng)字符串本身可能比較長(zhǎng),而且前幾個(gè)字符就開(kāi)始不相同,適合使用前綴索引;相反情況下不適合使用前綴索引,比如,整個(gè)字段的長(zhǎng)度為 20,索引選擇性為 0.9,而我們對(duì)前 10 個(gè)字符建立前綴索引其選擇性也只有 0.5,那么我們需要繼續(xù)加大前綴字符的長(zhǎng)度,但是這個(gè)時(shí)候前綴索引的優(yōu)勢(shì)已經(jīng)不明顯,就沒(méi)有創(chuàng)建前綴索引的必要了。
    索引選擇性怎么計(jì)算?
    首先我們可以通過(guò)如下 SQL 得到全列選擇性:

    SELECT COUNT(DISTINCT column_name) / COUNT(*) FROM table_name;

    例如:

    SELECT COUNT(DISTINCT coupon_id) / COUNT(*) FROM coupon;

    然后再通過(guò)如下 SQL 得到某一長(zhǎng)度前綴的選擇性:

    SELECT COUNT(DISTINCT LEFT(column_name, prefix_length)) / COUNT(*) FROM table_name;

    例如:

    SELECT COUNT(DISTINCT LEFT(coupon_id, 6)) / COUNT(*) FROM coupon; SELECT COUNT(DISTINCT LEFT(coupon_id, 8)) / COUNT(*) FROM coupon;

    總結(jié)

    以上是生活随笔為你收集整理的MySQL性能分析工具的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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