版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、查詢優(yōu)化學(xué)習(xí)心得Mysql性能優(yōu)化有兩個方面,一個是邏輯查詢,一個是物理查詢。邏輯查詢主要從連接的等價轉(zhuǎn)換,連接消除,條件下推等方式對語句進行簡化。子查詢是邏輯優(yōu)化過程中需要重點關(guān)注的對象,子查詢用的不好,往往會造成過多的表掃描。關(guān)于子查詢的優(yōu)化,需要注意以下幾點:,在執(zhí)行計劃中出現(xiàn)subQuery, Depented SubQuery的查詢方式,說明子查詢語句不能優(yōu)化,查詢語句按默認從內(nèi)外往執(zhí)行。先執(zhí)行子查詢語句,得到一個中間結(jié)果集,再執(zhí)行外層語句。這種情況主要出現(xiàn)于非spj的子查詢語句中,比如含有distinct ,group by 聚合函數(shù),order by limit,union.和相
2、關(guān)子查詢。,可以進行優(yōu)化的子查詢語句表現(xiàn)為 嵌套循環(huán)Nested Loop算法,連接方式可以是內(nèi)聯(lián)接(inner join)或者是半聯(lián)接(anti-semi-join)如果說在mysql中,內(nèi)聯(lián)接的Nested Loop屬于子查詢展開的話,那么半聯(lián)接類型的子查詢一般是不能夠展開的,屬于半聯(lián)接的運算符有exists,not exists,in,not in,半聯(lián)接是一種查找算法,只要查找到等值數(shù)據(jù)立刻退出本次循環(huán),not exists,not in則不同,需要全表掃描。對于嵌套循環(huán)Nested Loop,mysql的一種優(yōu)化方式是Materialized,對子查詢語句先進行物化,再與外表進行Ne
3、sted Loop在執(zhí)行計劃中,看到derived的查詢類型,說明在Nested Loop中,該表作為驅(qū)動表,根據(jù)Nested Loop運算符,先遍歷驅(qū)動表的每一行,針對每一行記錄,再到內(nèi)表中查找對應(yīng)的記錄。驅(qū)動表為全表掃描的外表。3,對于循套嵌套Nested loop算法,驅(qū)動表的索引并不重要,但查找的內(nèi)表字段最好有索引,如果有索引,子查詢將會優(yōu)化成簡單查詢(simple),也許,這就是子查詢最優(yōu)的解法吧(轉(zhuǎn)成了簡單查詢).4,>all,>any,>some運算符雖然是ansi聯(lián)接標準,但是由于這些運算符在語義上并不直觀,而且,這些運算符在查詢優(yōu)化階段也會被轉(zhuǎn)換成對應(yīng)max
4、,min運算符。所以實際并不常用。所以這類運算符也不能被優(yōu)化。=all,=some,=any 屬于等值聯(lián)接,它們可以被優(yōu)化。在sqlserver中,子查詢都轉(zhuǎn)換為嵌套循環(huán)Nested Loop.其性能受Nested Loop算法約束。5,在實際生產(chǎn)環(huán)境中,最常見的子查詢優(yōu)化是not in,not exists子查詢,一般會將其轉(zhuǎn)換成left join + where column is null。再一個就是注意子查詢和父查詢的相應(yīng)索引的使用。當(dāng)然,并非子查詢就是不好的:對于兩個表都比較小,使用子查詢,較低的查找開銷比聯(lián)結(jié)更優(yōu)勝.匹配只返回一個值,使用子查詢,與必須聯(lián)結(jié)整張表相比,只找錄一條記錄
5、并替換它花費的開銷要少很多匹配只返回相當(dāng)少的值,而且查詢列上沒有索引,使用子查詢,通常,單獨的一次或者甚至數(shù)次查找所花費的開銷都比散列聯(lián)結(jié)少另,子查詢也是必不可少,很多業(yè)務(wù)邏輯必須要用子查詢來實現(xiàn)。一些實驗的例子:相關(guān)子查詢 select * from t4 where t4.id4 = any ( select t5.id5 from t5 where t5.b5 = t4.b4); 非相關(guān)子查詢 select * from t1 where a1 = any (select a2 from t2 where t2.a2 = 10); IN 操作符 SELECT column_name(s)
6、 FROM table_name WHERE column_name IN (value1,value2,.)select * from t4 where t4.id4 in (1,3); ALLANYSOME操作符select * from t5 where t5.id5 > any ( select id4 from t4 where t4.id4>5); select * from t5 where t5.id5 > ALL ( select id4 from t4 where t4.id4>5); EXISTS操作符select * from t5 where
7、exists ( select * from t4 where t4.id4>t5.id5); 轉(zhuǎn)化成同義的IN語句: select * from t5 where id5 in ( select id5 from t4 where t4.id4>t5.id5); SPJ查詢: 選擇:select * from t4 where t4.id4=1; 投影: select id4, b4 from t4; 連接:select * from t4, t5 where t4.id4 = t5.id5;group by子查詢:SELECT Customer,SUM(OrderPrice)
8、FROM Orders GROUP BY Customer TOP-N : SELECT TOP 50 PERCENT * FROM Customers; mysql 不支持 等價于Mysql中 select * from t4 limit 10; LIMIT & order by: select * from t4 order by id4 desc limit 2,5; select n1,n2,n3 from ta inner join tb on ta.n1= ta.n2 &
9、#160; 現(xiàn)有表a name hot a 12
10、160; b 10 c 15 表b: &
11、#160; name hot d 12 e &
12、#160;10 f 10 g 8
13、 表a左連接表b,查詢hot相同的數(shù)據(jù) select a.*,b.* from a left join b on a.hot = b.hot 查詢結(jié)果:
14、 name hot name hot a 12 d 12
15、60; b 10 e 10 b 10 f 10
16、 c 15 null null 從上面可以看出,查詢結(jié)果表a的列都存在,表b的數(shù)據(jù)只顯示符合條件的項目 &
17、#160; 再如表b左連接表a,查詢hot相同的數(shù)據(jù) select a.*,b.* from b left join a on a.hot = b.hot 查詢結(jié)果為:
18、; name hot name hot d 12 a 12 &
19、#160; e 10 b 10 f 10 b 10
20、 g 8 null null 再如表a右連接表b,查詢hot相同的數(shù)據(jù) select a.*
21、,b.* from a right join b on a.hot = b.hot 查詢結(jié)果和上面的b left join a一樣優(yōu)化的另一個方面是物理查詢。在物理查詢方面,主要影響性能的地方是IO和cpu使用資源。對于優(yōu)化物理查詢,有一些建議:1,在保證實現(xiàn)功能的基礎(chǔ)上,盡量減少對數(shù)據(jù)庫的訪問次數(shù)(可以用緩存保存查詢結(jié)果,減少查詢次數(shù));2,通過搜索參數(shù),盡量減少對表的訪問行數(shù),最小化結(jié)果集, 從而減輕網(wǎng)絡(luò)負
22、擔(dān);3,能夠分開的操作盡量分開處理,提高每次的響應(yīng)速度;4,在數(shù)據(jù)窗口使用SQL時,盡量把使用的索引放在選擇的首列;5,算法的結(jié)構(gòu)盡量簡單;6,在 查詢時,不要過多地使用通配符如SELECT * FROM T1語句,要用到幾列就選擇幾列如:SELECTCOL1,COL2 FROM T1;7,在可能的情況下盡量限制盡量結(jié)果集行數(shù)如:SELECT TOP 300 COL1,COL2,COL3 FROM T1,因為某些情況下用戶是不需要那么多的數(shù)據(jù)的。在沒有建索引的情況下,數(shù)據(jù)庫查找某一條數(shù)據(jù),就必須進行全表掃描了,對所有數(shù)據(jù)進行一次遍歷,查找出符合條件的記錄。在數(shù)據(jù)量比較小的情況下,也許看不出明顯
23、的差別,但是當(dāng)數(shù)據(jù)量大的情況下,這種情況就是極為糟糕的了。所以,優(yōu)化查詢最重要的就是,盡量使語句符合查詢優(yōu)化器的規(guī)則避免全表掃描而使用索引查詢。具體要注意的:1.應(yīng)盡量避免在 where 子句中對字段進行 null 值判斷,否則將導(dǎo)致引擎放棄使用索引而進行全表掃描,如:select id from t where num is null可以在num上設(shè)置默認值0,確保表中num列沒有null值,然后這樣查詢:select id from t where num=02.應(yīng)盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。優(yōu)化器將無法通過索引來確
24、定將要命中的行數(shù),因此需要搜索該表的所有行。3.應(yīng)盡量避免在 where 子句中使用 or 來連接條件,否則將導(dǎo)致引擎放棄使用索引而進行全表掃描,如:select id from t where num=10 or num=20可以這樣查詢:select id from t where num=10union allselect id from t where num=204.in 和 not in 也要慎用,因為IN會使系統(tǒng)無法使用索引,而只能直接搜索表中的數(shù)據(jù)。如:select id from t where num in(1,2,3)對于連續(xù)的數(shù)值,能用 between 就不要用 in
25、了:select id from t where num between 1 and 35.盡量避免在索引過的字符數(shù)據(jù)中,使用非打頭字母搜索。這也使得引擎無法利用索引。關(guān)于物理查詢的優(yōu)化,重點放在索引的創(chuàng)建上。索引對查詢的速度有著至關(guān)重要的影響,索引也是進行數(shù)據(jù)庫性能調(diào)優(yōu)的起點。比如,數(shù)據(jù)庫中一個表有106條記錄,DBMS的頁面大小為 4K,并存儲100條記錄。如果沒有索引,查詢將對整個表進行掃描,最壞的情況下,如果所有數(shù)據(jù)頁都不在內(nèi)存,需要讀取104個頁面,如果這104個 頁面在磁盤上隨機分布,需要進行104次I/O,假設(shè)磁盤每次I/O時間為10ms(忽略數(shù)據(jù)傳輸時間),則總共需要100s(
26、但實際上要好很多很 多)。如果建立B-Tree索引,則只需要進行l(wèi)og100(106)=3次頁面讀取,最壞情況下耗時30ms。當(dāng)應(yīng)用程序進行SQL查詢速度很慢時,想想是否可以建索引。MySQL支持很多數(shù)據(jù)類型,選擇合適的數(shù)據(jù)類型存儲數(shù)據(jù)對性能有很大的影響。(1) 越小的數(shù)據(jù)類型通常更好:越小的數(shù)據(jù)類型通常在磁盤、內(nèi)存和CPU緩存中都需要更少的空間,處理起來更快。(2) 簡單的數(shù)據(jù)類型更好:整型數(shù)據(jù)比起字符,處理開銷更小,因為字符串的比較更復(fù)雜。在MySQL中,應(yīng)該用內(nèi)置的日期和時間數(shù)據(jù)類型,而不是用字符串來存儲時間;以及用整型數(shù)據(jù)類型存儲IP地址。(3) 盡量避免NULL:應(yīng)該指定列為NOT
27、NULL,除非你想存儲NULL。在MySQL中,含有空值的列很難進行查詢優(yōu)化,因為它們使得索引、索引的統(tǒng)計信息以及比較運算更加復(fù)雜。你應(yīng)該用0、一個特殊的值或者一個空串代替空值。索引的特性:1, 如果對多列進行索引(組合索引),MySQL僅能對索引最左邊的前綴進行有效的查找。比如:存在組合索引it1c1c2(c1,c2),查詢語句select * from t1 where c1=1 and c2=2能夠使用該索引。查詢語句select * from t1 where c1=1也能夠使用該索引。但是,查詢語句select * from t1 where c2=2不能夠使用該索引,因為沒有組合索
28、引的引導(dǎo)列,即,要想使用c2列進行查找,必需出現(xiàn)c1等于某值。建立索引的原則:1.合理使用索引一個Table在一次query中只能使用一個索引,使用EXPLAIN語句來檢驗優(yōu)化程序的操作情況使用analyze幫助優(yōu)化程序?qū)λ饕氖褂眯Ч龀龈鼫蚀_的預(yù)測2.索引應(yīng)該創(chuàng)建在搜索、排序、歸組等操作所涉及的數(shù)據(jù)列上3.盡量將索引建立在重復(fù)數(shù)據(jù)少的數(shù)據(jù)列中,唯一所以最好例如:生日列,可以建立索引,但性別列不要建立索引4.盡量對比較短的值進行索引降低磁盤IO操作,索引緩沖區(qū)中可以容納更多的鍵值,提高命中率如果對一個長的字符串建立索引,可以指定一個前綴長度5.合理使用多列索引如果多個條件經(jīng)常需要組合起來查詢
29、,則要使用多列索引(因為一個表一次查詢只能使用一個索引,建立多個單列索引也只能使用一個)6.充分利用最左前綴也就是要合理安排多列索引中各列的順序,將最常用的排在前面7.不要建立過多的索引只有經(jīng)常應(yīng)用于where,order by,group by中的字段需要建立索引.8.利用慢查詢?nèi)罩静檎页雎樵?log-slow-queries, long_query_time)使用索引的一些建議:1.盡量比較數(shù)據(jù)類型相同的數(shù)據(jù)列2.盡可能地讓索引列在比較表達式中獨立, WHERE mycol < 4 / 2 使用索引,而WHERE mycol * 2 < 4不使用3.盡可能不對查詢字段加函數(shù),
30、如WHERE YEAR(date_col) < 1990改造成WHERE date_col < 1990-01-01WHERE TO_DAYS(date_col) - TO_DAYS(CURDATE() < cutoff 改造成WHERE date_col < DATE_ADD(CURDATE(), INTERVAL cutoff DAY)4.在LIKE模式的開頭不要使用通配符5.使用straight join可以強制優(yōu)化器按照FROM子句的次序來進行聯(lián)結(jié),可以select straight join,強制所有聯(lián)結(jié),也可以select * from a straight
31、 join b強制兩個表的順序.6.使用force index強制使用指定的索引.如 select * from song_lib force index(song_name) order by song_name比不用force index效率高7.盡量避免使用MySQL自動類型轉(zhuǎn)換,否則將不能使用索引.如將int型的num_col用where num_col=5MySQL中,有兩種方式生成有序結(jié)果集:一是使用filesort,二是按索引順序掃描。利用索引進行排序操作是非??斓?,而且可以利用同一索引同時進 行查找和排序操作。當(dāng)索引的順序與ORDER BY中的列順序相同且所有的列是同一方向(全
32、部升序或者全部降序)時,可以使用索引來排序。如果查詢是連接多個表,僅當(dāng)ORDER BY中的所有列都是第一個表的列時才會使用索引。其它情況都會使用filesort。 當(dāng)MySQL不能使用索引進行排序時,就會利用自己的排序算法(快速排序算法)在內(nèi)存(sort buffer)中對數(shù)據(jù)進行排序,如果內(nèi)存裝載不下,它會將磁盤上的數(shù)據(jù)進行分塊,再對各個數(shù)據(jù)塊進行排序,然后將各個塊合并成有序的結(jié)果集(實際上就是 外排序)。對于filesort,MySQL有兩種排序算法。create table actor(actor_id int unsigned NOT NULL AUTO_INCRE
33、MENT,name varchar(16) NOT NULL DEFAULT '',password varchar(16) NOT NULL DEFAULT '',PRIMARY KEY(actor_id), KEY (name) ENGINE=InnoDBinsert into actor(name,password) values('cat01
34、9;,'1234567');insert into actor(name,password) values('cat02','1234567');insert into actor(name,password) values('ddddd','1234567');insert into actor(name,password) values('aaaaa','1234567');mysql> explain select actor_id from actor order by
35、 actor_id G* 1. row * id: 1 select_type: SIMPLE table: actor type: indexpossible_keys: NULL key: PRIMARY key_len: 4 ref: NULL rows: 4 Extra: Using index1 row in set (0.00 sec) mysql> explain select
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年分期付款旅游套餐協(xié)議
- 導(dǎo)演與設(shè)計師2025年度合作協(xié)議3篇
- 2025年人事代理授權(quán)服務(wù)協(xié)議
- 二零二五版奶茶店財務(wù)審計與風(fēng)險控制服務(wù)合同
- 2025年代理權(quán)益保護協(xié)議書案例展示總結(jié)介紹案例
- 2025年在線購物消費者協(xié)議
- 2025年銀行間市場協(xié)議存款居間業(yè)務(wù)合作合同范本6篇
- 2025年超額保險合同保險合同保險范圍協(xié)議
- 復(fù)習(xí)課件蘇聯(lián)的社會主義建設(shè)人教版
- 2025年度新能源技術(shù)研發(fā)個人技術(shù)服務(wù)合同4篇
- 書籍小兵張嘎課件
- 藝術(shù)哲學(xué):美是如何誕生的學(xué)習(xí)通超星期末考試答案章節(jié)答案2024年
- 北京海淀區(qū)2025屆高三下第一次模擬語文試題含解析
- 量子醫(yī)學(xué)治療學(xué)行業(yè)投資機會分析與策略研究報告
- 多重耐藥菌病人的管理-(1)課件
- (高清版)TDT 1056-2019 縣級國土資源調(diào)查生產(chǎn)成本定額
- 環(huán)境監(jiān)測對環(huán)境保護的意義
- 2023年數(shù)學(xué)競賽AMC8試卷(含答案)
- 神經(jīng)外科課件:神經(jīng)外科急重癥
- 2023年十天突破公務(wù)員面試
- 《瘋狂動物城》中英文對照(全本臺詞)
評論
0/150
提交評論