想要對一條查詢語句進行優化,首先要對其進行分析,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...