mysql查詢優化小技巧

2021-09-16 20:14:22 字數 4796 閱讀 7871

1. 開啟快取

mysql> show variables like 'query_cache%';

mysql> set global query_cache_type=1;

mysql> set global query_cache_size=1024*1024*32

注意:

查詢快取存在判斷是嚴格依據select語句本身的:嚴格保證sql一致。

如果查詢時包含動態資料,則不能被快取。

如果不想使用快取,可以使用 sql_no_cache 語法提示。

2. in型子查詢

select goods_id,cat_id,goods_name from good where cat_id in(select cat_id form category where parent_id=6);

這條語句執行會非常慢,因為它會掃瞄goods全表,逐行與category表對照

原因:mysql的查詢優化器,針對in型做了優化,優化成了exists的執行效果。

改進:用連線查詢代替子查詢

select goods_id,g.cat_id,g.goods_name from goods as g inner join (select cat_id from category where parent_id=6) as t;

3. from 子查詢

內層 from 語句查到的臨時表,沒有索引,所以from返回的內容要盡量少

4. count()優化

沒有查詢條件時count(*)非常快,不需要查表。但當有查詢條件時,速度將減慢。

可以使用縮小範圍的方法優化查詢。

eg.

需要統計good_id>100的總數時一般會寫為:

select count(*) form goods where good_id>100;

優化為:

slect (select count(*) from goods)-(select count(*) from goods where id<100);

這樣,就把範圍由無限大縮小到了100

5. group by 優化

預設情況下,mysql 對所有 group by col1, col2, …… 的字段進行排序。這與查詢中指定 order by col1,col2,…… 類似。因此,如果顯示包括乙個包含相同列的 order by 子句,則對 mysql 的實際執行效能沒有什麼影響。

如果查詢包括 group by 但使用者想要避免排序結果的消耗,則可以指定 order by null 禁止排序。

select col1 from table group by col2 order by null;
6. union 優化

union all 不過濾 效率提高,如非必須,請用union all

因為 union去重的代價非常高, 放在程式裡去重.

7. limit & 分頁優化

limit offset,n 當offset非常大時,效率極低。mysql並不是跳過offset行,然後單取n行,而是取offset+n行,返回放棄前offset行,返回n行。

優化:利用索引

id,name from goods inner join (select id from goods limit 5000000,10) as tmp using(id);

記錄上一次取出的最後一條資料,把 limit m, n 語句轉化為 limit n。

8. 消除msyql內部臨時表

在一些sql請求中,mysql會建立臨時表,可能建立到記憶體中,也可能由記憶體中轉存到磁碟。

會建立臨時表的查詢:

group by 的列沒有索引,必建立臨時表

order by 與 group by 為不同列時,或多表聯查時order by,group by 包含的列不是第一張表的列,必產生臨時表。

distinct 與 order by 一起使用可能會產生臨時表

union合併查詢時會用到臨時表

9. 大批量插入資料

對於 myisam 引擎

如果是空的 myisam 表,預設就是先導入資料才建立索引的,不存在優化問題。

對於非空的 myisam 表,在一次性插入大量資料時,可以通過設定 disable keys 和 enable keys 來提高匯入的效率。

# 假設給 test 表一次性插入大量資料  

alert table test disable keys;

loading the data ……

alert table test enable keys;

對於 innodb 引擎

disable keys 的方式適用於 myisam 引擎,但不適用於 innodb 引擎。

因為 innodb 型別的表是按照主鍵的順序儲存的,所以將匯入的資料按照主鍵的順序排列,可以有效的提高匯入資料的效率。

在匯入資料前執行 set unique_checks=0 , 關閉唯一性校驗,在匯入結束後執行 set unique_checks=1,恢復唯一性校驗,可以提高匯入的效率。

如果應用使用自動提交的方式,建議在匯入前執行 set autocommit=0,關閉自動提交,匯入結束後再執行 set autocommit=1,開啟自動提交,也可以提高匯入的效率。

10. 優化 insert 語句

同一客戶端一次插入多行

使用多個值表的 insert 語句,可以減少客戶端與資料庫之間的連線、關閉等資源消耗

insert into test values (1,1),(2,2),(3,3)……
從不同客戶插入很多行,可以使用 insert delayed 語句得到更高的素的。

delayed 的含義是讓 insert 語句馬上執行,其實資料都被放在記憶體的佇列中,並沒有真正的寫入磁碟,這比每條土局分別插入要快的多;

low_priority 剛好相反,在所有其他使用者對錶的讀寫完成後才進行插入(比如記錄日誌的場景)

將索引檔案和資料檔案分在不同的磁碟上存放(利用建表中的選項)

如果進行批量插入,可以通過增加 bulk_insert_buffer_size 變數值的方法來提高速度,但是,這只能對 myisam 表使用。

當從乙個文字檔案裝載乙個表時,使用 load data infile 。這通常比使用很多 insert 語句快 20 倍。

11. 優化 order by 語句

mysql 的兩種排序方式

通過有序索引順序掃瞄直接返回有序資料,這種方式在使用 explain 分析查詢時顯示為 using index ,不需要額外的排序,操作效率極高。

通過對返回的資料行進行排序,也就是通常說的 filesort 排序,所有不是通過索引直接返回排序結果的排序都叫做 filesort 排序。filefort 並不代表通過磁碟檔案進行排序,而只是說明進行了乙個排序操作,至於排序操作是否使用了磁碟檔案或臨時表等,則取決於 mysql 伺服器對排序引數的設定和需要排序資料的大小。

優化思路

儘量減少額外的排序,通過索引直接返回有序資料。

where 條件和 order_by 使用相同的索引,並且 order_by 的順序和索引的順序相同,並且 order by 的字段都是公升序或者降序。否則肯定需要額外的排序操作,這樣就會出現 filesort 。

filesort 的優化

在某些不得不使用 filesort 的場景中,需要想辦法加快 filesort 的操作。對於 filesort ,mysql 有兩種排序演算法。

首先根據條件取出排序欄位和行指標資訊,之後在排序區 sort_buffer 中排序。如果排序區 sort buffer 不夠,則在臨時表 temporary table 彙總儲存排序結果,完成排序後根據行指標回表讀取記錄。這種演算法需要兩次訪問資料,第一次獲取排序欄位和行指標資訊,第二次根據行指標獲取記錄,尤其是第二次讀取操作可能導致大量隨機 i/o 操作;優點是排序的時候記憶體開銷較少

一次性取出滿足條件的行的所有字段,然後在排序區 sort buffer 中排序後直接輸出結果集,排序的時候記憶體開銷較大,但是排序效率比兩次掃瞄演算法要高。

mysql 通過比較系統變數 max_length_for_sort_data 的大小和 query 語句取出的字段總大小來判斷使用哪種排序演算法。如果 max_length_for_sort_data 更大,那麼使用第二種優化之後的演算法,否則使用第一種演算法。

適當加大系統變數 max_length_for_sort_data 的值,能夠讓 mysql 選擇更優化的 filesort 的排序演算法,當然,設定過大,會造成cpu利用率過低和磁碟 i/o 過高

適當加大 sort_buffer_size 排序區,盡量讓排序在記憶體中完成,而不是通過建立臨時表放在檔案中進行;當然也不能不限制加大 sort_buffer_size 排序區,因為 sort_buffer_size 引數時每個執行緒獨佔的,所以要考慮資料庫活動連線數和伺服器記憶體的大小來適當設定排序區。

盡量只使用必要的字段,select 具體的欄位名稱,而不是 select * 選擇所有字段,這樣可以減少排序區使用,提高 sql 效能。

12. 使用 sql 提示

sql 提示(sql hint) 是優化資料庫的乙個重要手段,簡單來說就是在 sql 語句中加入一些人為的提示來達到優化操作的目的。

select sql_buffer_results * from ……
這個語句將強制 mysql 生成乙個臨時結果集。只要臨時結果集生成後,所有表上的鎖定均被釋放。

這能再遇到表鎖定問題時或要花很長時間將結果傳給客戶端時有所幫助,因為可以盡快釋放鎖資源。

mysql優化小技巧

對mysql優化時乙個綜合性的技術,主要包括 a 表的設計合理化 符合3nf b 新增適當索引 index 四種 普通索引 主鍵索引 唯一索引unique 全文索引 c 分表技術 水平分割 垂直分割 d 讀寫 寫 update delete add 分離 e 儲存過程 模組化程式設計,可以提高速度 ...

Mysql優化小技巧

思夢php 2019 02 09 07 01 00 資料量和要求 優化技巧 先把每一條心得記錄在這裡,後面會進行實驗對其一一驗證。查詢資料總條數時,使用max id 而不是count 進行總量計數。當然,前提是id是從1開始自增長,並且沒有行被刪除過。對於常用的查詢字段建立索引。索引的速度優勢顯而易...

mysql查詢優化技巧

建立索引的幾個準則 一 count的優化 1 select count from world.city where id 5 2 select select count from world.city count from world.city where id 5 1語句當行數超過11行的時候需要...