mysql 查詢優化

2021-08-31 22:56:55 字數 3608 閱讀 1315

mysql查詢優化學習---1 使用索引

2011-11-15 20:30

索 引是提高查詢速度的最重要的工具。當然還有其它的一些技術可供使用,但是一般來說引起最大效能差異的都是索引的正確使用。在mysql郵件列表中,人們經 常詢問那些讓查詢執行得更快的方法。在大多數情況下,我們應該懷疑資料表上有沒有索引,並且通常在新增索引之後立即解決了問題。當然,並不總是這樣簡單就 可以解決問題的,因為優化技術本來就並非總是簡單的。然而,如果沒有使用索引,在很多情況下,你試圖使用其它的方法來提高效能都是在浪費時間。首先使用索 引來獲取最大的效能提高,接著再看其它的技術是否有用。

這一部分講述了索引是什麼以及索引是怎麼樣提高查詢效能的。它還討論了在某些環境中索引可能降低效能,並為你明智地選擇資料表的索引提供了一些 指導方針。在下一部分中我們將討論mysql查詢優化器,它試圖找到執行查詢的效率最高的方法。了解一些優化器的知識,作為對如何建立索引的補充,對我們 是有好處的,因為這樣你才能更好地利用自己所建立的索引。某些編寫查詢的方法實際上讓索引不起作用,在一般情況下你應該避免這種情形的發生。

索引的優點

讓我們開始了解索引是如何工作的,首先有乙個不帶索引的資料表。不帶索引的表僅僅是乙個無序的資料行集合。例如,圖1顯示的ad表就是不帶索引的表,因 此如果需要查詢某個特定的公司,就必須檢查表中的每個資料行看它是否與目標值相匹配。這會導致一次完全的資料表掃瞄,這個過程會很慢,如果這個表很大,但 是只包含少量的符合條件的記錄,那麼效率會非常低。

圖1:無索引的ad表

圖2是同樣的一張資料表,但是增加了對ad表的company_num資料列的索引。這個索引包含了ad表中的每個資料行的條目,但是索引的條目是按照 company_num值排序的。現在,我們不是逐行檢視以搜尋匹配的資料項,而是使用索引。假設我們查詢公司13的所有資料行。我們開始掃瞄索引並找到 了該公司的三個值。接著我們碰到了公司14的索引值,它比我們正在搜尋的值大。索引值是排過序的,因此當我們讀取了包含14的索引記錄的時候,我們就知道 再也不會有更多的匹配記錄,可以結束查詢操作了。因此使用索引獲得的功效是:我們找到了匹配的資料行在哪兒終止,並能夠忽略其它的資料行。另乙個功效來自 使用定位演算法查詢第一條匹配的條目,而不需要從索引頭開始執行線性掃瞄(例如,二分搜尋就比線性掃瞄要快一些)。通過使用這種方法,我們可以快速地定位第 乙個匹配的值,節省了大量的搜尋時間。資料庫使用了多種技術來快速地定位索引值,但是在本文中我們不關心這些技術。重點是它們能夠實現,並且索引是個好東 西。

圖2:索引後的ad表

你可能要問,我們為什麼不對資料行進行排序從而省掉索引?這樣不是也能實現同樣的搜尋速度的改善嗎?是的,如果表只有乙個索引,這樣做也可能達到相同的 效果。但是你可能新增第二個索引,那麼就無法一次使用兩種不同方法對資料行進行排序了(例如,你可能希望在顧客名稱上建立乙個索引,在顧客id號或**號 碼上建立另外乙個索引)。把與資料行相分離的條目作為索引解決了這個問題,允許我們建立多個索引。此外,索引中的行一般也比資料行短一些。當你插入或刪除 新的值的時候,移動較短的索引值比移動較長資料行的排序次序更加容易。

不同的mysql儲存引擎的索引實現的具體細節資訊是不同的。 例如,對於myisam資料表,該錶的資料行儲存在乙個資料檔案中,索引值儲存在索引檔案中。乙個資料表上可能有多個索引,但是它們都被儲存在同乙個索引 檔案中。索引檔案中的每個索引都包含乙個排序的鍵記錄(它用於快速地訪問資料檔案)陣列。

與此形成對照的是,bdb和innodb存 儲引擎沒有使用這種方法來分離資料行和索引值,儘管它們也把索引作為排序後的值集合進行操作。在預設情況下,bdb引擎使用單個檔案儲存資料和索引值。 innodb使用單個資料表空間(tablespace),在表空間中管理所有innodb表的資料和索引儲存。我們可以把innodb配置為每個表都在 自己的表空間中建立,但是即使是這樣,資料表的資料和索引也儲存在同乙個表空間檔案中。

前面的討論描述了單個表查詢環境下的索引的優點,在這種情 況下,通過減少對整個表的掃瞄,使用索引明顯地提高了搜尋的速度。當你執行涉及多表聯結(jion)查詢的時候,索引的價值就更高了。在單錶查詢中,你需 要在每個資料列上檢查的值的數量是表中資料行的數量。在多表查詢中,這個數量可能大幅度上公升,因為這個數量是這些表中資料行的數量所產生的。

假設你擁有三個未索引的表t1、t2和t3,每個表都分別包含資料列i1、i2和i3,並且每個表都包含了1000條資料行,其序號從1到1000。查詢某些值匹配的資料行組合的查詢可能如下所示:

select t1.i1, t2.i2, t3.i3

from t1, t2, t3

where t1.i1 = t2.i2 and t2.i1 = t3.i3;

假設你已經知道了建立索引的語法,但是語法不會告訴你資料表應該如何索引。這要求我們考慮資料表的使用方式。這一部分指導你如何識別出用於索引的備選資料列,以及如何最好地建立索引:

用於搜尋、排序和分組的索引資料列並不僅僅是用於輸出顯示的。換句話說,用於索引的最好的備選資料列是那些出現在where子句、join子句、 order by或group by子句中的列。僅僅出現在select關鍵字後面的輸出資料列列表中的資料列不是很好的備選列:

select

col_a

from

tbl1 left join tbl2

on tbl1.col_b = tbl2.col_c

where

col_d = expr;

state, city, zip

state, city

state

id < 30

weight between 100 and 150

· b樹索引可以用於高效率地執行精確的或者基於範圍(使用操作=、>、<>、!=和between)的比較。b樹索引也可以用於like模式匹配,前提是該模式以文字串而不是萬用字元開頭。

如果你使用的memory資料表只進行精確值查詢,雜湊索引是很好的選擇。這是memory表使用的預設的索引型別,因此你不需要特意指定。如果你希望 在memory表上執行基於範圍的比較,應該使用b樹索引。為了指定這種索引型別,需要給索引定義新增using btree。例如:

create table lookup

(id int not null,

name char(20),

primary key using btree (id)

) engine = memory;

如果你希望執行的語句的型別允許,單個memory表可以同時擁有雜湊索引和b樹索引,即使在同乙個資料列上。

有些型別的比較不能使用索引。如果你只是通過把值傳遞到函式(例如strcmp())中來執行比較操作,那麼對它進行索引就沒有價值。伺服器必須計算出每個資料行的函式值,它會排除資料列上索引的使用。

使用慢查詢(slow-query)日誌來識別執**況較差的查詢。這個日誌可以幫助你找出從索引中受益的查詢。你可以直接檢視日誌(它是文字檔案), 或者使用mysqldumpslow工具來統計它的內容。如果某個給定的查詢多次出現在"慢查詢"日誌中,這就是乙個線索,某個查詢可能沒有優化編寫。你 可以重新編寫它,使它執行得更快。你要記住,在評估"慢查詢"日誌的時候,"慢"是根據實際時間測定的,在負載較大的伺服器上"慢查詢"日誌中出現的查詢 會多一些。

查詢優化(MySQL優化查詢)

關聯查詢太多join 設計缺陷或不得已的需求 資料庫伺服器調優及各個引數設定不適當 緩衝 執行緒數等 慢查詢日誌 找出執行速度慢的sql語句 慢查詢的開啟並捕獲 explain 慢sql分析 show profile查詢sql在mysql伺服器裡面的執行細節和生命週期情況 sql資料庫伺服器的引數調...

mysql統計查詢優化 Mysql查詢優化

效能涉及的層面很多,但是在操作層面,主要有表結構設計優化 索引優化和查詢優化 查詢的生命週期大致可以分為,從客戶端 到服務端 在伺服器上解析 生成執行計畫 執行 返回結果給客戶端 sql執行流程 具體優化技巧 1.消除外連線 2.消除子查詢 盡量用join代替子查詢,雖說mysql查詢優化器會進行優...

MySQL優化 查詢優化

在每乙個消耗大量時間的查詢中,都能看到一些不必要的額外操作 某些操作被額外地重複了很多次 某些操作執行得太慢等。優化查詢的目的就是減少和消除這些操作所花費的時間。查詢效能低下最基本的原因是訪問的資料太多。所以需要考慮是否向資料庫請求了不需要的資料 1 多表關聯時,或獲取單錶資料時,盡量避免不加思考地...