二維碼
        企資網(wǎng)

        掃一掃關(guān)注

        當(dāng)前位置: 首頁(yè) » 企業(yè)資訊 » 行業(yè) » 正文

        解析MySQL數(shù)據(jù)庫(kù)_“SQL優(yōu)化”與“索引優(yōu)

        放大字體  縮小字體 發(fā)布日期:2022-06-17 03:54:58    作者:付妤萱    瀏覽次數(shù):39
        導(dǎo)讀

        一、索引優(yōu)化:1、like語(yǔ)句得前導(dǎo)模糊查詢不使用索引:select * from doc where title like '%XX'; --不能使用索引select * from doc where title like 'XX%'; --非前導(dǎo)模糊

        一、索引優(yōu)化:

        1、like語(yǔ)句得前導(dǎo)模糊查詢不使用索引:

        select * from doc where title like '%XX'; --不能使用索引select * from doc where title like 'XX%'; --非前導(dǎo)模糊查詢,可以使用索引

        2、負(fù)向條件查詢不能使用索引:

        負(fù)向條件有:!=、<>、not in、not exists、not like 等

        例如下面SQL語(yǔ)句:(假設(shè)status得取值為0、1、2、3、4)

        select * from doc where status != 1 and status != 2; --不能使用索引select * from doc where status in (0,3,4); --優(yōu)化為 in 查詢,可以使用索引

        3、范圍條件右邊得列不能使用索引(范圍列可以用到索引):

        范圍條件有:<、<=、>、>=、between等。

        索引最多用于一個(gè)范圍列,如果查詢條件中有兩個(gè)范圍列則無(wú)法全用到索引。

        假如有聯(lián)合索引 (emp_no 、title、from_date ),那么下面得 SQL 中 emp_no 可以用到索引,而title 和 from_date 則使用不到索引。

        select * from employees.titles where emp_no < 10010' and title='Senior Engineer'and from_date between '1986-01-01' and '1986-12-31'

        4、在索引列做任何操作(計(jì)算、函數(shù)、表達(dá)式)會(huì)導(dǎo)致索引失效而轉(zhuǎn)向全表掃描:

        select * from doc where YEAR(create_time) <= '2016'; -- 不能使用索引select * from doc where create_time<= '2016-01-01'; -- 可以使用索引select * from order where date < = CURDATE(); -- 不能使用索引select * from order where date < = '2018-01-2412:00:00'; -- 可以使用索引select id from t where substring(name,1,3)=’abc’ -- 不能使用索引select id from t where name like ‘a(chǎn)bc%’ -- 可以使用索引select id from t where num/2=100 -- 不能使用索引select id from t where num=100*2 -- 可以使用索引

        5、where 子句中索引列使用參數(shù),也會(huì)導(dǎo)致索引失效:

        因?yàn)镾QL只有在運(yùn)行時(shí)才會(huì)解析局部變量,但優(yōu)化程序不能將訪問(wèn)計(jì)劃得選擇推遲到運(yùn)行時(shí);它必須在編譯時(shí)進(jìn)行選擇。然而,如果在編譯時(shí)建立訪問(wèn)計(jì)劃,變量得值還是未知得,因而無(wú)法作為索引選擇得輸入項(xiàng)。如下面語(yǔ)句將進(jìn)行全表掃描:

        select id from t where num=等num -- 不能使用索引select id from t with(index(索引名)) where num=等num --可以改為強(qiáng)制查詢使用索引:

        6、強(qiáng)制類型轉(zhuǎn)換會(huì)導(dǎo)致全表掃描:

        字符串類型不加單引號(hào)會(huì)導(dǎo)致索引失效,因?yàn)閙ysql會(huì)自己做類型轉(zhuǎn)換,相當(dāng)于在索引列上進(jìn)行了操作。

        如果 phone 字段是 varchar 類型,則下面得 SQL 不能命中索引,因?yàn)閮?nèi)部發(fā)生得類型轉(zhuǎn)換。

        select * from user where phone=13800001234; -- 不能使用索引select * from user where phone='13800001234'; -- 可以使用索引

        7、is null, is not null 在無(wú)法使用索引,不過(guò)在mysql得高版本已經(jīng)做了優(yōu)化,允許使用索引

        select id from t where num is null; -- mysql低版本不能使用索引select id from t where num=0; -- 可以在num上設(shè)置默認(rèn)值0,確保表中num列沒(méi)有null值,然后這樣查詢

        8、使用組合索引時(shí),要符合最左前綴原則:

        組合索引得字段數(shù)不允許超過(guò)5個(gè)。如果在a,b,c三個(gè)字段上建立聯(lián)合索引 index(a,b,c),那么他會(huì)自動(dòng)建立 a、(a,b)、(a,b,c) 三組索引。

        (1)建立聯(lián)合索引得時(shí)候,區(qū)分度蕞高得字段在最左邊:

        (2)存在等號(hào)和非等號(hào)混合判斷條件時(shí),在建立索引時(shí),把等號(hào)條件得列前置,如 where a > ? and b= ?,那么即使 a 得區(qū)分度更高,也必須把 b 放在索引得最前列。

        (3)最左前綴查詢時(shí),并不是指SQL語(yǔ)句得where順序要和聯(lián)合索引一致,但還是建議 where 條件得順序和聯(lián)合索引一致。

        (4)假如index(a,b,c), where a=3 and b like 'abc%' and c=4,a能用,b能用,c不能用。

        9、利用覆蓋索引來(lái)進(jìn)行查詢操作,避免回表,減少select * 得使用 :

        覆蓋索引:被查詢列要被所建得索引覆蓋,被查詢列得數(shù)據(jù)能從索引中直接取得,不用通過(guò)行定位符 再到 row 上獲取,加速查詢速度。

        例如登錄業(yè)務(wù)需求,SQL語(yǔ)句如下。

        Select uid, login_time from user where login_name=? and passwd=?

        可以建立(login_name, passwd, login_time)得聯(lián)合索引,由于 login_time 已經(jīng)建立在索引中了,被查詢得 uid 和 login_time 就不用去 row 上獲取數(shù)據(jù)了,從而加速查詢。

        10、利用索引下推減少回表得次數(shù):

        索引下推是Mysql5.6版本推出得功能,用于優(yōu)化查詢。

      1. 不使用索引下推得情況下,在使用非主鍵索引進(jìn)行查詢時(shí),存儲(chǔ)引擎通過(guò)索引檢索到數(shù)據(jù),然后返回給MySQL服務(wù)層,服務(wù)層然后判斷數(shù)據(jù)是否符合條件 。
      2. 使用索引下推得情況下,如果存在某些被索引得列得判斷條件時(shí),MySQL服務(wù)層將這一部分判斷條件傳遞給存儲(chǔ)引擎,然后由存儲(chǔ)引擎通過(guò)判斷索引是否符合MySQL服務(wù)層傳遞得條件,只有當(dāng)索引符合條件時(shí)才會(huì)將數(shù)據(jù)檢索出來(lái)返回給MySQL服務(wù)層。

        所以,索引下推就是存儲(chǔ)引擎查詢數(shù)據(jù)時(shí),根據(jù)查詢條件過(guò)濾掉一些記錄,減少回表得次數(shù),也可以減少M(fèi)ySQL服務(wù)層從存儲(chǔ)引擎接收數(shù)據(jù)量。

        11、使用前綴索引:

        短索引不僅可以提高查詢性能而且可以節(jié)省磁盤(pán)空間和I/O操作,減少索引文件得維護(hù)開(kāi)銷,但缺點(diǎn)是不能用于 ORDER BY 和 GROUP BY 操作,也不能用于覆蓋索引。比如有一個(gè)varchar(255)得列,如果該列在前10個(gè)或20個(gè)字符內(nèi),可以做到既使前綴索引得區(qū)分度接近全列索引,那么就不要對(duì)整個(gè)列進(jìn)行索引。為了減少key_len,可以考慮創(chuàng)建前綴索引,即指定一個(gè)前綴長(zhǎng)度,可以使用count(distinct leftIndex(列名, 索引長(zhǎng)度))/count(*) 來(lái)計(jì)算前綴索引得區(qū)分度(計(jì)算前綴索引得區(qū)分度在文章第三部分會(huì)介紹)。

        12、order by、group by后面得列如果有索引,可以利用索引得有序性可以消除排序帶來(lái)得CPU開(kāi)銷。

        (1)order by 最后得字段是組合索引得一部分,并且放在索引組合順序得最后,避免出現(xiàn)file_sort 得情況,影響查詢性能。例如對(duì)于語(yǔ)句 where a= ? and b= ? order by c,可以建立聯(lián)合索引(a,b,c)。

        (2)如果索引中有范圍查找,那么索引有序性無(wú)法利用,如 WHERe a > 10 ORDER BY b; 索引(a,b)無(wú)法排序。

        (3)如果是前綴索引,是不能消除排序得

        (4)order by排序字段順序,即asc/desc升降要跟索引保持一致,充分利用索引得有序性來(lái)消除排序帶來(lái)得CPU開(kāi)銷

        12、進(jìn)行join聯(lián)表查詢得字段需要建立索引,join蕞好不要超過(guò)三個(gè)表,需要 join 得字段,數(shù)據(jù)類型必須一致:

        多表關(guān)聯(lián)查詢時(shí),保證被關(guān)聯(lián)得字段需要有索引。left join是由左邊決定得,左邊得數(shù)據(jù)一定都有,所以右邊是我們得關(guān)鍵點(diǎn),建立索引要建右邊得。當(dāng)然如果索引在左邊,可以用right join。

        13、單表索引建議控制在5個(gè)以內(nèi)。

        索引不是越多越好,索引固然可以提高相應(yīng)得 select 得效率,但同時(shí)也降低了 insert 及 update 得效率,因?yàn)?insert 或 update 時(shí)有可能會(huì)重建索引,同時(shí)也會(huì)暫用空間。一個(gè)表得索引數(shù)較好不要超過(guò)5個(gè)。

        14、SQL 性能優(yōu)化 explain 中得 type:至少要達(dá)到 range 級(jí)別,要求是 ref 級(jí)別,如果可以是 consts 蕞好。

        consts:?jiǎn)伪碇凶疃嘀挥幸粋€(gè)匹配行(主鍵或者唯一索引),在優(yōu)化階段即可讀取到數(shù)據(jù)。

        ref:使用普通得索引

        range:對(duì)索引進(jìn)行范圍檢索。

        當(dāng) type=index 時(shí),索引物理文件全掃,速度非常慢。

        15、業(yè)務(wù)上具有唯一特性得字段,即使是多個(gè)字段得組合,也必須建成唯一索引,防止臟數(shù)據(jù)產(chǎn)生:

        不要以為唯一索引影響了 insert 速度,這個(gè)速度損耗可以忽略,但提高查找速度是明顯得。另外,即使在應(yīng)用層做了非常完善得校驗(yàn)控制,只要沒(méi)有唯一索引,根據(jù)墨菲定律,必然。

        16、更新十分頻繁、數(shù)據(jù)區(qū)分度不高得列不宜建立索引:

        數(shù)據(jù)更新會(huì)變更 B+ 樹(shù),在更新頻繁得字段建立索引會(huì)大大降低數(shù)據(jù)庫(kù)性能。類似于“性別”這種區(qū)分度不大得屬性,建立索引是沒(méi)有什么意義得,不能有效過(guò)濾數(shù)據(jù),性能與全表掃描類似。一般區(qū)分度在80%以上得時(shí)候就可以建立索引,區(qū)分度可以使用 count(distinct(列名))/count(*) 來(lái)計(jì)算。

        二、SQL語(yǔ)句優(yōu)化:

        1、減少請(qǐng)求得數(shù)據(jù)量:

        (1)只返回必要得列,用具體得字段列表代替 select * 語(yǔ)句

        MySQL數(shù)據(jù)庫(kù)是按照行得方式存儲(chǔ),而數(shù)據(jù)存取操作都是以一個(gè)頁(yè)大小進(jìn)行IO操作得,每個(gè)IO單元中存儲(chǔ)了多行,每行都是存儲(chǔ)了該行得所有字段。所以無(wú)論取一個(gè)字段還是多個(gè)字段,實(shí)際上數(shù)據(jù)庫(kù)在表中需要訪問(wèn)得數(shù)據(jù)量其實(shí)是一樣得。但是如果查詢得字段都在索引中,也就是覆蓋索引,那么可以直接從索引中獲取對(duì)應(yīng)得內(nèi)容直接返回,不需要進(jìn)行回表,減少IO操作。除此之外,當(dāng)存在 order by 操作得時(shí)候,select 子句中得字段多少會(huì)在很大程度上影響到我們得排序效率。

        (2)只返回必要得行,使用 Limit 語(yǔ)句來(lái)限制返回得數(shù)據(jù)。如果不使用 Limit 得話,MySQL將會(huì)一行一行得將全部結(jié)果按照順序查找,最后返回結(jié)果,借助 Limit 可以實(shí)現(xiàn)當(dāng)找到指定行數(shù)時(shí),直接返回查詢結(jié)果,提高效率

        2、優(yōu)化深度分頁(yè)得場(chǎng)景:利用延遲關(guān)聯(lián)或者子查詢

        對(duì)于 limit m, n 得分頁(yè)查詢,越往后面翻頁(yè)(即m越大得情況下)SQL得耗時(shí)會(huì)越來(lái)越長(zhǎng),對(duì)于這種應(yīng)該先取出主鍵id,然后通過(guò)主鍵id跟原表進(jìn)行Join關(guān)聯(lián)查詢。因?yàn)镸ySQL 并不是跳過(guò) offset 行,而是取 offset+N 行,然后放棄前 offset 行,返回 N 行,那當(dāng) offset 特別大得時(shí)候,效率就非常得低下,要么控制返回得總頁(yè)數(shù),要么對(duì)超過(guò)特定閾值得頁(yè)數(shù)進(jìn)行 SQL 改寫(xiě)。

        延遲關(guān)聯(lián)示例如下,先快速定位需要獲取得 id 段,然后再關(guān)聯(lián):

        # 延遲關(guān)聯(lián):通過(guò)使用覆蓋索引查詢返回需要得主鍵,再根據(jù)主鍵關(guān)聯(lián)原表獲得需要得數(shù)據(jù)# 覆蓋索引:select得數(shù)據(jù)列只用從索引中就能夠得到,不用回表查詢select a.* from 表1 a,(select id from 表1 where 條件 limit 100000,20) b where a.id=b.id;

        但對(duì)于深度分頁(yè)得情況,蕞好還是將上次遍歷到得最末尾得數(shù)據(jù)傳給數(shù)據(jù)庫(kù),然后直接定位到該處 再 往后面遍歷數(shù)據(jù)

        3、分解大連接查詢:

        將一個(gè)大連接查詢分解成對(duì)每一個(gè)表進(jìn)行一次單表查詢,然后在應(yīng)用程序中進(jìn)行關(guān)聯(lián),這樣做得好處有:

      3. (1)減少鎖競(jìng)爭(zhēng);
      4. (2)讓緩存更高效。對(duì)于連接查詢,如果其中一個(gè)表發(fā)生變化,那么整個(gè)查詢緩存就無(wú)法使用。而分解后得多個(gè)查詢,即使其中一個(gè)表發(fā)生變化,對(duì)其它表得查詢緩存依然可以使用。
      5. (3)分解成多個(gè)單表查詢,這些單表查詢得緩存結(jié)果更可能被其它查詢使用到,從而減少冗余記錄得查詢。
      6. (4)在應(yīng)用層進(jìn)行連接,可以更容易對(duì)數(shù)據(jù)庫(kù)進(jìn)行拆分,從而更容易做到高性能和可伸縮。
      7. (5)查詢本身效率也可能會(huì)有所提升。比如使用 IN() 代替連接查詢,可以讓 MySQL 按照 順序進(jìn)行查詢,這可能比隨機(jī)得連接要更高效。

        4、避免使用select得內(nèi)聯(lián)子查詢:

        在select后面有子查詢得情況稱為內(nèi)聯(lián)子查詢,SQL返回多少行,子查詢就需要執(zhí)行過(guò)多少次,嚴(yán)重影響SQL性能。

        5、盡量使用Join代替子查詢:

        由于MySQL得優(yōu)化器對(duì)于子查詢得處理能力比較弱,所以不建議使用子查詢,可以改寫(xiě)成Inner Join,之所以 join 連接效率更高,是因?yàn)?MySQL不需要在內(nèi)存中創(chuàng)建臨時(shí)表

        select b.member_id,b.member_type, a.create_time,a.device_model from member_operation_log a inner join (select member_id,member_type from member_base_info where `status` = 1) as b on a.member_id = b.member_id;

        6、多張大數(shù)據(jù)量得表進(jìn)行JOIN連接查詢,蕞好先過(guò)濾在JOIN:

        在多個(gè)表進(jìn)行 join 連接查詢得時(shí)候,蕞好先在一個(gè)表上先過(guò)濾好數(shù)據(jù),然后再用過(guò)濾好得結(jié)果集與另外得表 Join,這樣可以盡可能多得減少不必要得 IO 操作,大大節(jié)省 IO 操作所消耗得時(shí)間

        7、避免在使用or來(lái)連接查詢條件:

        如果一個(gè)字段有索引,一個(gè)字段沒(méi)有索引,將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描。

        8、union、in、or 都能夠命中索引,但推薦使用 in:

        (1)union:能夠命中索引,并且MySQL 耗費(fèi)得 CPU 最少

        select * from doc where status=1union allselect * from doc where status=2;

        (2)in:能夠命中索引,查詢優(yōu)化耗費(fèi)得 CPU 比 union all 多,但可以忽略不計(jì)

        select * from doc where status in (1, 2);

        (3)or:新版得 MySQL 能夠命中索引,但是如果一個(gè)字段有建立索引、一個(gè)字段沒(méi)有建立索引,那么將導(dǎo)致索引失效而進(jìn)行全表掃描,or 查詢優(yōu)化耗費(fèi)得 CPU 比 in 多

        select * from doc where status = 1 or status = 2

        對(duì)于上面三種關(guān)鍵詞:union all 分兩步執(zhí)行,而 in 和 or 只用了一步,效率高一點(diǎn)。用 or 得執(zhí)行時(shí)間比 in 時(shí)間長(zhǎng)。因?yàn)槭褂?or 條件查詢,會(huì)先判斷一個(gè)條件進(jìn)行篩選,再判斷 or 中另外得條件再篩選,而 in 查詢直接一次在 in 得集合里篩選,并且or 查詢優(yōu)化耗費(fèi)得 CPU 比 in 多,所以推薦使用in

        9、對(duì)于連續(xù)得數(shù)值,能用 between 就不要用 in:

        10、小表驅(qū)動(dòng)大表,即小得數(shù)據(jù)集驅(qū)動(dòng)大得數(shù)據(jù)集:

        in 和 exists 都可以用于子查詢,那么 MySQL 中 in 和 exists 有什么區(qū)別呢?

      8. (1)使用exists時(shí)會(huì)先進(jìn)行外表查詢,將查詢到得每行數(shù)據(jù)帶入到內(nèi)表查詢中看是否滿足條件;使用in一般會(huì)先進(jìn)行內(nèi)表查詢獲取結(jié)果集,然后對(duì)外表查詢匹配結(jié)果集,返回?cái)?shù)據(jù)。
      9. (2)in在內(nèi)表查詢或者外表查詢過(guò)程中都會(huì)用到索引;exists僅在內(nèi)表查詢時(shí)會(huì)用到索引
      10. (3)一般來(lái)說(shuō),當(dāng)子查詢得結(jié)果集比較大,外表較小使用exist效率更高;當(dāng)子查詢得結(jié)果集較小,外表較大時(shí),使用in效率更高。
      11. (4)對(duì)于 not in 和 not exists,not exists 效率比 not in 得效率高,與子查詢得結(jié)果集無(wú)關(guān),因?yàn)?not in 對(duì)于內(nèi)外表都進(jìn)行了全表掃描,沒(méi)有使用到索引。not exists得子查詢中可以用到表上得索引。

        11、使用union all 替換 union:

        當(dāng)SQL語(yǔ)句需要union兩個(gè)查詢結(jié)果集合時(shí),這兩個(gè)結(jié)果集合會(huì)以u(píng)nion all得方式被合并,然后再輸出最終結(jié)果前進(jìn)行排序。如果用union all替代union,這樣排序就不是不要了,效率就會(huì)因此得到提高.。需要注意得是,UNIOn ALL 將重復(fù)輸出兩個(gè)結(jié)果集合中相同記錄。

        12、優(yōu)化Group by,使用where子句替換Having子句:

        避免使用having子句,having只會(huì)在檢索出所有記錄之后才會(huì)對(duì)結(jié)果集進(jìn)行過(guò)濾,這個(gè)處理需要排序分組,如果能通過(guò)where子句提前過(guò)濾查詢得數(shù)目,就可以減少這方面得開(kāi)銷。

        on、where、having這三個(gè)都可以加條件得子句,on是最先執(zhí)行,where次之,having最后。

        提高GROUP BY 語(yǔ)句得效率, 可以通過(guò)將不需要得記錄在GROUP BY 之前過(guò)濾掉。

        低效: SELECt JOB, AVG(SAL) FROM EMP GROUP by JOB HAVINg JOB = ‘PRESENT' OR JOB = ‘MANAGER'高效: SELECt JOB, AVG(SAL) FROM EMP WHERe JOB =

        13、盡量使用數(shù)字型字段:

        若只含數(shù)值信息得字段盡量不要設(shè)計(jì)為字符型,這會(huì)降低查詢和連接得性能。引擎在處理查詢和連接時(shí)會(huì)逐個(gè)比較字符串中每一個(gè)字符,而對(duì)于數(shù)字型而言只需要比較一次就夠了。

        14、寫(xiě)出統(tǒng)一得SQL語(yǔ)句:

        對(duì)于以下兩句SQL語(yǔ)句,很多人都認(rèn)為是相同得。不過(guò)數(shù)據(jù)庫(kù)查詢優(yōu)化器則認(rèn)為是不同得,雖然只是大小寫(xiě)不同,但必須進(jìn)行兩次解析,生成2個(gè)執(zhí)行計(jì)劃。所以應(yīng)該保證相同得查詢語(yǔ)句在任何地方都一致,多一個(gè)空格都不行。

        select * from dualselect * From dual

        15、使用復(fù)合索引須遵守最左前綴原則:

        復(fù)合索引必須使用到最左邊字段作為條件時(shí)才能保證系統(tǒng)使用該索引,否則該索引將不會(huì)被使用,并且應(yīng)盡可能得讓字段順序與索引順序相一致。

        16、當(dāng)需要全表刪除且無(wú)需回滾時(shí),使用Truncate替代delete

        17、使用表得別名

        當(dāng)在SQL語(yǔ)句中連接多個(gè)表時(shí), 使用表得別名并把別名前綴用于每個(gè)Column上,這樣可以減少解析得時(shí)間并減少那些由Column歧義引起得語(yǔ)法錯(cuò)誤。

        18、避免使用耗費(fèi)資源得操作:

        帶有DISTINCT,UNIOn,MINUS,INTERSECT,ORDER BY得SQL語(yǔ)句,會(huì)啟動(dòng)SQL引擎執(zhí)行耗費(fèi)資源得排序功能,DISTINCT需要一次排序操作,而其他得至少需要執(zhí)行兩次排序。通常。帶有UNIOn, MINUS , INTERSECT得SQL語(yǔ)句都可以用其他方式重寫(xiě),如果你得數(shù)據(jù)庫(kù)得SORT_AREA_SIZE調(diào)配得好, 使用UNIOn , MINUS, INTERSECT也是可以考慮得, 畢竟它們得可讀性很強(qiáng)。

        19、Update 語(yǔ)句,如果只更改1、2個(gè)字段,不要Update全部字段,否則頻繁調(diào)用會(huì)引起明顯得性能消耗,同時(shí)帶來(lái)大量日志。

        20、應(yīng)盡可能得避免更新聚簇索引數(shù)據(jù)列,因?yàn)榫鄞厮饕龜?shù)據(jù)列得順序就是表記錄得物理存儲(chǔ)順序,一旦該列值改變將導(dǎo)致整個(gè)表記錄得順序得調(diào)整,會(huì)耗費(fèi)相當(dāng)大得資源。

        21、盡量使用表變量來(lái)代替臨時(shí)表。

        22、考慮使用“臨時(shí)表”暫存中間結(jié)果。臨時(shí)表并不是不可使用,適當(dāng)?shù)厥褂盟鼈兛梢允鼓承┎樵兏行В纾?dāng)需要重復(fù)引用大型表或常用表中得某個(gè)數(shù)據(jù)集時(shí)。將臨時(shí)結(jié)果暫存在臨時(shí)表,后面得查詢就在臨時(shí)表中查詢了,這可以避免程序中多次掃描主表,也大大減少了程序執(zhí)行中“共享鎖”阻塞“更新鎖”,減少了阻塞,提高了并發(fā)性能。但是,對(duì)于一次性事件,較好使用導(dǎo)出表。

        23、在新建臨時(shí)表時(shí),如果一次性插入數(shù)據(jù)量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果數(shù)據(jù)量不大,為了緩和系統(tǒng)表得資源,應(yīng)先create table,然后insert。

        24、如果使用到了臨時(shí)表,在存儲(chǔ)過(guò)程得最后務(wù)必將所有得臨時(shí)表顯式刪除,先 truncate table ,然后 drop table ,這樣可以避免系統(tǒng)表得較長(zhǎng)時(shí)間鎖定。

        25、避免頻繁創(chuàng)建和刪除臨時(shí)表,以減少系統(tǒng)表資源得消耗。

        26、盡量避免使用游標(biāo),因?yàn)橛螛?biāo)得效率較差。與臨時(shí)表一樣,游標(biāo)并不是不可使用。對(duì)小型數(shù)據(jù)集使用 FAST_FORWARD 游標(biāo)通常要優(yōu)于其他逐行處理方法,尤其是在必須引用幾個(gè)表才能獲得所需得數(shù)據(jù)時(shí)。在結(jié)果集中包括“合計(jì)”得例程通常要比使用游標(biāo)執(zhí)行得速度快。

        27、在所有得存儲(chǔ)過(guò)程和觸發(fā)器得開(kāi)始處設(shè)置 SET NOCOUNT ON ,在結(jié)束時(shí)設(shè)置 SET NOCOUNT OFF 。

        28、盡量避免大事務(wù)操作,提高系統(tǒng)并發(fā)能力。

        29、在運(yùn)行代碼中,盡量使用PreparedStatement來(lái)查詢,不要用Statement。

        三、索引得選擇性與前綴索引:

        既然索引可以加快查詢速度,那么是不是只要是查詢語(yǔ)句需要,就建上索引?答案是否定得。因?yàn)樗饕m然加快了查詢速度,但索引也是有代價(jià)得:索引文件本身要消耗存儲(chǔ)空間,同時(shí)索引會(huì)加重插入、刪除和修改記錄時(shí)得負(fù)擔(dān),另外,MySQL在運(yùn)行時(shí)也要消耗資源維護(hù)索引,因此索引并不是越多越好。一般兩種情況下不建議建索引。

        第壹種情況是表記錄比較少,沒(méi)必要建索引,讓查詢做全表掃描就好了。

        第二種情況是索引得選擇性較低。所謂索引得選擇性,是指 不重復(fù)得索引值 與 表記錄數(shù)量 得比值:

        顯然選擇性得取值范圍為(0, 1],選擇性越高得索引價(jià)值越大,這是由B+Tree得性質(zhì)決定得。

        例如,employees.titles表,如果title字段經(jīng)常被單獨(dú)查詢,是否需要建索引,我們看一下它得選擇性:

        SELECT count(DISTINCT(title))/count(*) AS Selectivity FROM employees.titles;+-------------+| Selectivity |+-------------+| 0.0000 |+-------------+

        title得選擇性不足0.0001(精確值為0.00001579),所以實(shí)在沒(méi)有什么必要為其單獨(dú)建索引。

        有一種與索引選擇性有關(guān)得索引優(yōu)化策略叫做前綴索引,就是用列得前綴代替整個(gè)列作為索引key,當(dāng)前綴長(zhǎng)度合適時(shí),可以做到既使得前綴索引得選擇性接近全列索引,同時(shí)因?yàn)樗饕齥ey變短而減少了索引文件得大小和維護(hù)開(kāi)銷。下面以employees.employees表為例介紹前綴索引得選擇和使用。

        假設(shè)employees表只有一個(gè)索引<emp_no>,那么如果我們想按名字搜索一個(gè)人,就只能全表掃描了:

        EXPLAIN SELECT * FROM employees.employees WHERe first_name='Eric' AND last_name='Anido';+----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+| 1 | SIMPLE | employees | ALL | NULL | NULL | NULL | NULL | 300024 | Using where |+----+-------------+-----------+------+---------------+------+---------+------+--------+-------------+

        如果頻繁按名字搜索員工,這樣顯然效率很低,因此我們可以考慮建索引。有兩種選擇,建<first_name>或<first_name, last_name>,看下兩個(gè)索引得選擇性:

        SELECT count(DISTINCT(first_name))/count(*) AS Selectivity FROM employees.employees;+-------------+| Selectivity |+-------------+| 0.0042 |+-------------+SELECT count(DISTINCT(concat(first_name, last_name)))/count(*) AS Selectivity FROM employees.employees;+-------------+| Selectivity |+-------------+| 0.9313 |+-------------+

        <first_name>顯然選擇性太低,<first_name, last_name>選擇性很好,但是first_name和last_name加起來(lái)長(zhǎng)度為30,有沒(méi)有兼顧長(zhǎng)度和選擇性得辦法?可以考慮用first_name和last_name得前幾個(gè)字符建立索引,例如<first_name, left(last_name, 3)>,看看其選擇性:

        SELECT count(DISTINCT(concat(first_name, left(last_name, 3))))/count(*) AS Selectivity FROM employees.employees;+-------------+| Selectivity |+-------------+| 0.7879 |+-------------+

        選擇性還不錯(cuò),但離0.9313還是有點(diǎn)距離,那么把last_name前綴加到4:

        SELECT count(DISTINCT(concat(first_name, left(last_name, 4))))/count(*) AS Selectivity FROM employees.employees;+-------------+| Selectivity |+-------------+| 0.9007 |+-------------+

        這時(shí)選擇性已經(jīng)很理想了,而這個(gè)索引得長(zhǎng)度只有18,比<first_name, last_name>短了接近一半,我們把這個(gè)前綴索引建上:

        ALTER TABLE employees.employeesADD INDEX `first_name_last_name4` (first_name, last_name(4));

        此時(shí)再執(zhí)行一遍按名字查詢,比較分析一下與建索引前得結(jié)果:

        SHOW PROFILES;+----------+------------+---------------------------------------------------------------------------------+| Query_ | Duration | Query |+----------+------------+---------------------------------------------------------------------------------+| 87 | 0.11941700 | SELECT * FROM employees.employees WHERe first_name='Eric' AND last_name='Anido' || 90 | 0.00092400 | SELECt * FROM employees.employees WHERe first_name='Eric' AND last_name='Anido' |+----------+------------+---------------------------------------------------------------------------------+

        性能得提升是顯著得,查詢速度提高了120多倍。

        前綴索引兼顧索引大小和查詢速度,但是其缺點(diǎn)是不能用于ORDER BY和GROUP BY操作,也不能用于覆蓋索引

        :張維鵬

        原文鏈接:blog.csdn/a745233700/article/details/84455241

      12.  
        (文/付妤萱)
        免責(zé)聲明
        本文僅代表作發(fā)布者:付妤萱?zhèn)€人觀點(diǎn),本站未對(duì)其內(nèi)容進(jìn)行核實(shí),請(qǐng)讀者僅做參考,如若文中涉及有違公德、觸犯法律的內(nèi)容,一經(jīng)發(fā)現(xiàn),立即刪除,需自行承擔(dān)相應(yīng)責(zé)任。涉及到版權(quán)或其他問(wèn)題,請(qǐng)及時(shí)聯(lián)系我們刪除處理郵件:weilaitui@qq.com。
         

        Copyright ? 2016 - 2025 - 企資網(wǎng) 48903.COM All Rights Reserved 粵公網(wǎng)安備 44030702000589號(hào)

        粵ICP備16078936號(hào)

        微信

        關(guān)注
        微信

        微信二維碼

        WAP二維碼

        客服

        聯(lián)系
        客服

        聯(lián)系客服:

        在線QQ: 303377504

        客服電話: 020-82301567

        E_mail郵箱: weilaitui@qq.com

        微信公眾號(hào): weishitui

        客服001 客服002 客服003

        工作時(shí)間:

        周一至周五: 09:00 - 18:00

        反饋

        用戶
        反饋

        最近高清中文在线字幕在线观看| 亚洲高清无码专区视频| 4hu亚洲人成人无码网www电影首页 | 熟妇人妻中文a∨无码| 老司机亚洲精品影院无码| 亚洲中文字幕无码久久精品1 | 中文字幕一区二区三区精彩视频 | 久久精品99无色码中文字幕| 日韩精品专区AV无码| 日韩欧美中文在线| 精品人无码一区二区三区| 久久亚洲2019中文字幕| 久久久久无码中| 亚洲精品无码久久久久久| 中文字幕丰满伦子无码 | 亚洲国产精品无码久久久蜜芽| 一本大道久久东京热无码AV| 亚洲精品无码MV在线观看| 久久久中文字幕| 天堂无码在线观看| 色欲A∨无码蜜臀AV免费播 | 亚洲日韩激情无码一区| 日本一区二区三区精品中文字幕| 久久精品aⅴ无码中文字字幕重口| 中文字幕在线观看亚洲日韩| 国产高清无码视频| 无码精品日韩中文字幕| 日韩亚洲欧美中文高清在线| 中文字幕乱码免费视频| 国产精品久久久久无码av| 亚洲精品无码专区久久久| 中文字幕视频在线| 中文无码成人免费视频在线观看| 成人av片无码免费天天看 | 中文字幕手机在线观看| 中文字幕乱妇无码AV在线| 国产激情无码一区二区三区| 日韩AV无码精品人妻系列| 亚洲日韩精品一区二区三区无码| 麻豆aⅴ精品无码一区二区| 最好看更新中文字幕|