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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

MySQL进阶篇(03):合理的使用索引结构和查询

發(fā)布時間:2025/3/16 12 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL进阶篇(03):合理的使用索引结构和查询 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本文源碼:GitHub·點(diǎn)這里 || GitEE·點(diǎn)這里

一、高性能索引

1、查詢性能問題

在MySQL使用的過程中,所謂的性能問題,在大部分的場景下都是指查詢的性能,導(dǎo)致查詢緩慢的根本原因是數(shù)據(jù)量的不斷變大,解決查詢性能的最常見手段是:針對查詢的業(yè)務(wù)場景,設(shè)計(jì)合理的索引結(jié)構(gòu)。

2、索引使用原則

索引的使用并不是越多越好,而是針對業(yè)務(wù)下的查詢場景,不斷的改進(jìn)和優(yōu)化,例如電商系統(tǒng)中用戶訂單的場景,假設(shè)存在如下表結(jié)構(gòu):

CREATE TABLE `ds_user` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵id',`user_name` varchar(20) DEFAULT NULL,PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用戶表';CREATE TABLE `ds_order` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵id',`user_id` int(11) NOT NULL COMMENT '用戶ID',`order_no` varchar(60) NOT NULL COMMENT '訂單號',`product_name` varchar(50) DEFAULT NULL COMMENT '產(chǎn)品名稱',`number` int(11) DEFAULT '1' COMMENT '個數(shù)',`unit_price` decimal(10,2) DEFAULT '0.00' COMMENT '單價',`total_price` decimal(10,2) DEFAULT '0.00' COMMENT '總價',`order_state` int(2) DEFAULT '1' COMMENT '1待支付,2已支付,3已發(fā)貨,4已簽收',`order_remark` varchar(50) DEFAULT NULL COMMENT '訂單備注',`create_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時間',PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='訂單表';

用戶和訂單管理表,在電商的業(yè)務(wù)中很常見,可以通過對該業(yè)務(wù)分析,看看常用的索引結(jié)構(gòu):

用戶方:

  • 基于用戶的查詢,多數(shù)是基于用戶ID(user_id);
  • 基于訂單號(order_no),查看物流的信息;

運(yùn)營方:

  • 基于時間段的流水明細(xì)(create_time)或排序;
  • 基于訂單狀態(tài)的篩選(order_state)和統(tǒng)計(jì);
  • 基于產(chǎn)品(product_name)的數(shù)據(jù)統(tǒng)計(jì)分析;

這樣一個流程分析走下來,即可以在開發(fā)初期,確定哪些結(jié)構(gòu)是查詢必須用到的,預(yù)先做好索引結(jié)構(gòu),避免數(shù)據(jù)量龐大到影響性能時再去考慮使用索引。

有些時候會考慮放棄一些查詢條件,例如基于產(chǎn)品名稱的數(shù)據(jù)統(tǒng)計(jì),走定時任務(wù)的方式,用來緩解表的查詢壓力,處理的方式是多樣的。

優(yōu)秀的索引設(shè)計(jì),都是建立在對業(yè)務(wù)數(shù)據(jù)的理解上,考慮業(yè)務(wù)數(shù)據(jù)的查詢方式,提高查詢效率。

二、索引創(chuàng)建

1、單列索引

單列索引,即索引建立在表的一個字段上,一個表可以有多個單列索引,使用起來相對比較簡單:

CREATE INDEX user_id_index ON ds_order(user_id) USING BTREE;

主鍵索引,或者上述的user_id_index都是單列索引。

業(yè)務(wù)場景:基于用戶自己對訂單查詢,和管理系統(tǒng),訂單和用戶的關(guān)聯(lián)查詢,所以訂單表的user_id需要一個索引。

2、組合索引

組合索引包含兩個或兩個以上的列,組合索引相比單列索引復(fù)雜很多,如何建立組合索引,和業(yè)務(wù)關(guān)聯(lián)度非常高,在使用組合索引時,還需要考慮查詢條件的順序。

CREATE INDEX state_create_time_index ON `ds_order`(`create_time`,`order_state`);

如上就是組合索引,實(shí)際包含的是2個索引 (create_time) (create_time,order_state),這樣查詢就涉及到最左前綴的原則,必須按照順序來查詢,這里下面詳說。

業(yè)務(wù)場景:首先單說這里組合索引,在業(yè)務(wù)開發(fā)中,常見訂單狀態(tài)的統(tǒng)計(jì),基于統(tǒng)計(jì)結(jié)果做運(yùn)營分析,另外就是在運(yùn)營系統(tǒng)中,基于創(chuàng)建時間段的篩選條件是默認(rèn)存在的,避免全部數(shù)據(jù)實(shí)時掃描;一些其他的常見查詢也都是條件加時間段的查詢模式。

3、前綴索引

如果需要加索引的列是很長的字符串,那么索引會變的龐大臃腫,起到的效果可能并不是很明顯。這時候可以截取列的前面一部分,創(chuàng)建索引,節(jié)省空間,這樣可能會出現(xiàn)索引的選擇性下降,即基于前綴索引查詢出的相似數(shù)據(jù)可能很多:

ALTER TABLE ds_order ADD KEY (order_no(30)) ;

這里由于訂單號太長,所以選擇前面30位作為前綴索引,用作訂單號的查詢,當(dāng)然這里涉及到一個非常經(jīng)典的業(yè)務(wù)場景,訂單號機(jī)制。

業(yè)務(wù)場景:前綴索引一個典型的應(yīng)用場景就是處理訂單號,一個看似很長的訂單號,其實(shí)包含的信息非常多:

  • 時間點(diǎn):就是訂單生成的時間,年月日時分秒;
  • 標(biāo)識位:即一個唯一的UID,保證訂全單號唯一;
  • 埋點(diǎn)一:在很多業(yè)務(wù)中,在訂單號記錄產(chǎn)品類目;
  • 埋點(diǎn)二:通常會標(biāo)識產(chǎn)品屬性,例如顏色,口味等;
  • 錯位符:防止訂單號被分析,會隨機(jī)一段錯位符號;

如此一段分析下來,實(shí)際訂單號是非常長的,所以需要引入前綴索引機(jī)制,前綴索引期望使用的索引長度可以篩選整個列的基數(shù),例如上面的訂單號:

  • 大部分業(yè)務(wù)基于時間節(jié)點(diǎn)篩選足夠,即索引長度14位;
  • 如果是并發(fā)業(yè)務(wù),很多時間節(jié)點(diǎn)相同,則索引長度是時間點(diǎn)+標(biāo)識位;

注意:如果業(yè)務(wù)允許的情況下,一般要求前綴索引的長度有唯一性,例如上面的時間和標(biāo)示位。

4、其他索引

例如全文索引等,這些用到的場景不多,如果數(shù)據(jù)龐大,又需要檢索等,通常會選擇強(qiáng)大的搜索中間件來處理。顯式唯一索引,這種也會在程序上做規(guī)避,避免不友好的異常被拋出。

三、索引查詢

如何創(chuàng)建最優(yōu)的索引,是一件不容易的事情,同樣在查詢的時候,是否使用索引也是一件難度極大的事情,經(jīng)驗(yàn)之談:多數(shù)是性能問題暴露的時候,才會回頭審視查詢的SQL語句,針對性能問題,做相應(yīng)的查詢優(yōu)化。

1、單列查詢

這里直接查詢主鍵索引,MySQL的主鍵一般選擇自增,所以速度非??臁?/p> EXPLAIN SELECT * FROM ds_order WHERE id=2; EXPLAIN SELECT * FROM ds_order WHERE id=1+1; EXPLAIN SELECT * FROM ds_order WHERE id+1=1;

這里,id=2,id=1+1,MySQL都可以自動解析,但是id+1是在索引列上執(zhí)行運(yùn)算,直接導(dǎo)致主鍵索引失效。這里有一個基本策略,如果非要在單列索引上做操作,可以將該邏輯放在程序中,到MySQL層面,SQL語句越干凈利落越好。

2、前綴索引查詢

前綴索引的查詢,可以基于Like對特定長度篩選,或者全訂單號查詢。

EXPLAIN SELECT * FROM ds_order WHERE order_no LIKE '202008011314158723628732871625%'; EXPLAIN SELECT * FROM ds_order WHERE order_no='20200801131415872362873287162572367';

3、組合索引查詢

查詢最麻煩的就是組合索引,或者說查詢條件組合起來,都使用了索引:

EXPLAIN SELECT * FROM ds_order WHERE create_time>'2020-08-01 00:00:00' AND order_state='1';

上述基于組合索引中列的順序,使用了組合索引:state_create_time_index。

EXPLAIN SELECT * FROM ds_order WHERE create_time>'2020-08-01 00:00:00';

上述只使用create_time列,也同樣使用了索引結(jié)構(gòu)。

EXPLAIN SELECT * FROM ds_order WHERE order_state='1';

上述如果只使用order_state條件,則結(jié)果顯示全表掃描。

EXPLAIN SELECT * FROM ds_order WHERE create_time>'2020-08-01 00:00:00' AND order_no LIKE '20200801%';

上述則基于組合索引的create_time列和單列索引order_no保證查詢條件都使用了索引。

通過上面幾個查詢案例,索引組合索引使用的注意事項(xiàng)如下:

  • 組合索引必須按索引最左列開始查詢;
  • 不能跳過組合字段查詢,這樣無法使用索引;

四、索引其他說明

1、索引的優(yōu)點(diǎn)

  • 基于注解或唯一索引保證數(shù)據(jù)庫表中數(shù)據(jù)的唯一性;
  • 索引通過減少掃描表的行數(shù)提高查詢的效率;

2、索引的缺點(diǎn)

  • 創(chuàng)建索引和維護(hù)索引,會耗費(fèi)空間和實(shí)際;
  • 查詢以外的操作增刪改等,都需要動態(tài)維護(hù)索引;

3、索引使用總結(jié)

索引機(jī)制在MySQL中真的非常復(fù)雜,非專業(yè)的DBA(就是指開發(fā)人員),基本要熟練常見的索引結(jié)構(gòu),待過兩年所謂的大廠,每個版本開發(fā)涉及的核心表SQL都是有專業(yè)DBA驗(yàn)收,復(fù)雜的查詢都是提交需求,DBA直接輸出查詢SQL,當(dāng)然在一般公司是沒有DBA,需要開發(fā)在開發(fā)的過程中不斷的思考,逐步優(yōu)化,這需要對業(yè)務(wù)數(shù)據(jù)有一定的敏感度,對核心接口有執(zhí)行監(jiān)控,當(dāng)發(fā)現(xiàn)稍微出現(xiàn)耗時情況,就可以不斷優(yōu)化,這個積累是個枯燥和進(jìn)步的過程。

五、源代碼地址

GitHub·地址 https://github.com/cicadasmile/mysql-data-base GitEE·地址 https://gitee.com/cicadasmile/mysql-data-base

推薦閱讀:MySQL數(shù)據(jù)庫系列

序號文章標(biāo)題
01MySQL基礎(chǔ):經(jīng)典實(shí)用查詢案例,總結(jié)整理
02MySQL基礎(chǔ):從五個維度出發(fā),審視表結(jié)構(gòu)設(shè)計(jì)
03MySQL基礎(chǔ):系統(tǒng)和自定義函數(shù)總結(jié),觸發(fā)器使用詳解
04MySQL基礎(chǔ):存儲過程和視圖,用法和特性詳解
05MySQL基礎(chǔ):邏輯架構(gòu)圖解和InnoDB存儲引擎詳解
06MySQL基礎(chǔ):事務(wù)管理,鎖機(jī)制案例詳解
07MySQL基礎(chǔ):用戶和權(quán)限管理,日志體系簡介
01MySQL進(jìn)階:基于多個維度,分析服務(wù)器性能
02MySQL進(jìn)階:索引體系劃分,B-Tree結(jié)構(gòu)說明

總結(jié)

以上是生活随笔為你收集整理的MySQL进阶篇(03):合理的使用索引结构和查询的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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