MySQL查詢語句優化

2021-09-24 09:15:01 字數 3321 閱讀 9966

想要對一條查詢語句進行優化,首先要對其進行分析,mysql提供了這個機制, 可以通過explain sql或者desc sql的語法去獲取mysql對某一條語句的執行計畫(mysql優化之後的),explain的用法這裡就不再贅述了,在另外一篇文章中有詳細的解讀.

對一條sql的優化可以分為兩部分,第一部分是對語句的優化,比如將子查詢改寫為join等,第二部分是與索引相關的優化,在這一階段可能會修改語句以讓查詢盡可能的命中索引,甚至會通過修改索引來達到這個目的.

與索引相關的優化

首先我們需要讓查詢盡可能的命中索引,通常情況下在一張表上會有各種花裡胡哨的查詢,我們很難讓每乙個查詢都完美命中,因此我們假設認為我們在為bad case 做優化,不考慮對其他的查詢造成的影響.

最左字首

在使用聯合索引的時候,要想多字段命中索引,需要遵循最左字首原則.

假如現在表上有school_age的聯合索引,那麼下面的語句是可以使用索引的:

# 根據school查詢

select * from user where school = '卡塞爾'

# 根據scholl和age進行查詢

select * from user where school = '卡塞爾' and age = 12

而直接通過age的查詢是無法命中索引的,select * from school where age = 10,這一點可以通過explain來證實.

無法命中索引的一些操作

查詢條件中使用不等於操作符!=

非字首使用like like 『%gaga%』.

or操作符必須每個欄位都建立索引

where語句中有數**算或者函式.

盡量的使用覆蓋索引

在查詢語句中,如果返回的字段較少,那麼應該盡量的使需要的所有字段包含在索引中,這樣可以使用覆蓋索引來加快查詢速度.

檢查語句

查詢語句優化的第一步,首先從大的層面上分析一下語句,得到以下問題的答案:

是否請求了不需要的資料?

這個最常出現的是請求了過多的列,也就是select *,此外還有查詢了10000行但是在拿到前10行之後就扔掉了其他的資料.

是否掃瞄了過多的資料?

在理想的情況下,我們希望能到做到掃瞄的資料行數和需要返回的資料行數是一樣的,但是在實際操作中比較困難,但是我們首先應該檢查這一項,已確定當前掃瞄的行數是必要的.

拆分複雜查詢

當乙個語句太過於複雜的時候,我們總是難以掌握它的效能,因此我們可以將乙個複雜的查詢拆分成多個查詢,然後在應用程式中進行關聯.

改寫子查詢

子查詢想必關聯查詢,效能一般是較差的,因此可以將子查詢改為關聯表查詢.

優化count()

count()函式需要掃面大量的資料,在myisam中速度是比較快的,但是在其他儲存引擎卻不是,對count()語句可以有以下的優化策略.

確定是否真的需要數量

曾經見過乙個count(*)的語句,但是對結果的使用僅僅是判斷結果是否大於0,這時語句可以大大的減少掃面的數量來達到相同的作用:

select 1 from user where age = 100 limit 1.
這樣僅需要掃瞄一行資料就可以達到相同的作用.

使用近似值

當表中資料量非常大的時候,很多的count查詢是不需要精確計數的,此時可以使用其他近似值,比如explain中的行數,比如information_schema.tables中的行數等.

新增彙總表

如果需要經常的進行count,那麼我們應該額外新增一張表或者一列來記錄這個數值,而不是每次進行查詢.

優化關聯查詢

確保on/where語句中的列上有索引.

確保order by / group by 只根據乙個表上的字段進行,這樣才有使用索引進行排序分組的可能性.

優化limit語句

limit offset,limit中的offset值很大時,查詢的效能會直線下降

使用hint優化查詢

mysql提供了一些用於我們"提示"mysql伺服器應該怎樣進行這個查詢,需要注意的是,使用hint很有可能不會給你的程式帶來效能上的提公升,反而可能是效能下降,因此在使用前請確保自己了解該hint的作用.這裡列舉一些常用的hint的作用.

sql_no_cache

該提示讓mysql不對這條資料的結果進行快取.select sql_no_cache ***, yyy from table;

sql_calhe

告訴mysql這條語句的結果需要快取.select sql_calhe * from table;

high_priority

告訴mysql這條資料的優先順序很高,在競爭一些互斥的資源時,這條語句將最先獲得資源,select high_priority * from table;

low_priority

與上面乙個相反.

delayed

該hint會在insert和replace的時候使用,可以是的mysql伺服器立即返回結果,但是插入操作則在表空閒的時候進行.insert delayed into .....

straight_join

該hint告訴mysql按照語句中的順序進行多個表的關聯操作,不要進行"優化".select straight_join * from table1 join table2.

sql_buffer_result

該hint告訴mysql,將查詢結果放入到臨時表中,然後盡快釋放表鎖.select sql_buffer_result * from table ...;

sql_big_result和sql_small_result

這兩個hint只可以在select語句使用,它告訴mysql結果集很大/很小.因此mysql可以使用記憶體/檔案進行排序等操作.select sql_big_result * from table ...;

force index和ignore index
這兩個hint告訴mysql此查詢語句強制使用或者不使用哪個索引.select * from table force index (field) ...;完。

MYSQL查詢語句優化

一 日期查詢優化 在mysql中速度最慢的不是in查詢,而是date format以及from unixtime兩個函式的日期時間轉換,執行時間可能超過兩秒,造成 巨卡 用php的函式代替mysql的函式來完成將會大大的縮減時間 今日 from unixtime lastplaytime,y m d...

MySQL查詢優化語句 explain

一 mysql 查詢優化器是如何工作的 mysql 查詢優化器有幾個目標,但是其中最主要的目標是盡可能地使用索引,並且使用最嚴格的索引來消除盡可能多的資料行。最終目標是提交 select 語句查詢資料行,而不是排除資料行。優化器試圖排除資料行的原因在於它排除資料行的速度越快,那麼找到與條件匹配的資料...

mysql具體優化查詢語句

1 應盡量避免全表掃瞄。首先應考慮在where以及order by涉及的列上建立索引,相對於使用給定索引,全表掃瞄很耗時。2 應盡量避免在where子句中對字段進行null值判斷,任何where子句在使用is null或 is not null 的語句優化器都是不允許使用損索引的 3 盡量避免在wh...