mysql分页 disti_MySql查询性能优化
慢查詢判定
1.開啟慢查詢?nèi)罩居涗泩?zhí)行時(shí)間超過long_query_time 秒的sql語句
2.通過show processlist命令查看線程執(zhí)行狀態(tài)
3.通過explain解析sql了解執(zhí)行狀態(tài)
慢查詢優(yōu)化
是否向服務(wù)器請求列不必要的數(shù)據(jù)
查詢不需要的記錄(limit),多表關(guān)聯(lián)返回全部列,總是取出全部列和重復(fù)io等
是否走索引
建立索引的原則:
最左前綴匹配原則,mysql會一直向右匹配直到遇到范圍查詢(>、 3 and d = 4 如果建立(a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到,a,b,d的順序可以任意調(diào)整
等值查詢(=和in)可以亂序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序,mysql查詢優(yōu)化器會優(yōu)化成索引為可識別的形式
模糊匹配like,“%”不能在第一個(gè)位置
選擇區(qū)分度高的列作為索引,區(qū)分度的公式是count(distinct col)/count(*),表示字段不重復(fù)的比例,比例越大掃描的記錄數(shù)越少,唯一鍵的區(qū)分度是1
索引列不能是表達(dá)式的一部分或者是函數(shù)的參數(shù)
盡量的擴(kuò)展索引,不要新建索引。比如表中已經(jīng)有a的索引,現(xiàn)在要加(a,b)的索引,那么只需要修改原來的索引即可
避免在where子句中對字段進(jìn)行NULL值判斷,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描
or改寫成in:or的效率是n級別,in的效率是log(n)級別,in的個(gè)數(shù)建議控制在200以內(nèi)
盡量避免在where子句中使用!=或<>操作符,否則將引擎放棄使用索引而進(jìn)行全表掃描
對于連續(xù)數(shù)值,使用between不用in
查詢sql是否合理
切分查詢
分解關(guān)聯(lián)查詢
將一個(gè)大的查詢分解為多個(gè)小查詢是很有必要的。很多高性能的應(yīng)用都會對關(guān)聯(lián)查詢進(jìn)行分解,就是可以對每一個(gè)表進(jìn)行一次單表查詢,然后將查詢結(jié)果在應(yīng)用程序中進(jìn)行關(guān)聯(lián),很多場景下這樣會更高效
表結(jié)構(gòu)優(yōu)化
對于需要經(jīng)常聯(lián)合查詢的表,可以建立中間表以提高查詢效率
水平拆分
分區(qū)表
分庫分表
垂直拆分,將單個(gè)表字段分解為多個(gè)表字段(根據(jù)模塊的耦合度,拆分為分布式系統(tǒng))
查詢執(zhí)行路徑
客戶端/服務(wù)器通信
半雙工模式---- 任意時(shí)刻數(shù)據(jù)只能單向傳輸
查詢優(yōu)化器
mysql查詢優(yōu)化器會通過某種策略自動生成最優(yōu)的執(zhí)行計(jì)劃
重新定義關(guān)聯(lián)表的順序
數(shù)據(jù)表的關(guān)聯(lián)順序并不總是按照在查詢中指定的順序執(zhí)行
將外連接轉(zhuǎn)化為內(nèi)連接
并不是所有的OUTER JOIN操作都必須以外連接的方式執(zhí)行
使用等價(jià)變換規(guī)則
mysql會使用一些等價(jià)變換規(guī)則來優(yōu)化表達(dá)式
優(yōu)化COUNT()
MyISAM維護(hù)一個(gè)變量存放表的行數(shù), MIN() -- 查詢列對應(yīng)B+樹索引最左端記錄 ,MAX() -- 查詢列對應(yīng)B+樹索引最右端記錄
預(yù)估并轉(zhuǎn)化為常數(shù)表達(dá)式
覆蓋索引掃描
當(dāng)索引中的列包含列所有查詢需要返回的列時(shí),mysql會自動使用覆蓋索引掃描而無需查詢對應(yīng)的數(shù)據(jù)行
子查詢優(yōu)化
提前終止查詢,如Limit
等值傳播
列表IN()的比較
在很多數(shù)據(jù)庫系統(tǒng)中,IN()完全等同于多個(gè)OR條件的子句,但是mysql會先將IN()列表中的數(shù)據(jù)進(jìn)行排序,然后通過二分查找來確定列表中的值是否滿足條件,O(log(n))復(fù)雜度操作,而如果轉(zhuǎn)換為OR則復(fù)雜度為O(n)
SQL執(zhí)行順序
FROM—>ON—>JOIN—>WHERE—>GROUP BY—>SUM(聚合函數(shù))—>HAVING—>SELECT—>DISTINCT—>UNION—>ORDER BY—>LIMIT
優(yōu)化特定類型查詢
優(yōu)化子查詢
MySql的子查詢實(shí)現(xiàn)非常糟糕,特別是where條件中包含IN()的子查詢性能通常會比較差,如
select * from film where film_id in (
select film_id from film_actor where film.film_id = 1
);
MySql查詢優(yōu)化器會將上面的查詢通過Exists改寫
select * from film where exists(
select * from film_actor where film.film_id = 1
and film.film_id = film_actor.film_id);
IN比較通過在內(nèi)存中遍歷,而exists走數(shù)據(jù)庫索引,所以當(dāng)子查詢中表的數(shù)據(jù)量比較大時(shí)exists效率優(yōu)于in
優(yōu)化子查詢最常見的建議就是盡可能使用關(guān)聯(lián)查詢代替
select film.* from film inner join film_actor using (film_id) where actor_id = 1;
優(yōu)化COUNT()
COUNT函數(shù)用于統(tǒng)計(jì)某個(gè)列值的數(shù)量或者行數(shù),統(tǒng)計(jì)列值時(shí)要求列值非空(不統(tǒng)計(jì)NULL)
優(yōu)化關(guān)聯(lián)查詢
確保ON或者USING子句的列上有索引。只需在關(guān)聯(lián)順序的第二個(gè)表上建立索引即可,如當(dāng)表A和表B用列c關(guān)聯(lián)的時(shí)候,如果優(yōu)化器的優(yōu)化順序?yàn)锽,A,那么就不需要在表B上建立索引
確保任何的GROUP BY或者ORDER BY中的表達(dá)式只涉及到一個(gè)表中的列,這樣mysql才有可能使用索引來優(yōu)化這個(gè)過程
優(yōu)化GROUP BY和DISTINCT
當(dāng)無法使用索引時(shí),GROUP BY會通過臨時(shí)表或者文件排序做排序
優(yōu)化limit分頁
limit操作在偏移量非常大的情況,mysql會掃描大量不需要的行然后拋棄掉導(dǎo)致效率降低
1.延遲關(guān)聯(lián):在關(guān)聯(lián)查詢中使用覆蓋索引掃描,獲取關(guān)聯(lián)字段后再根據(jù)關(guān)聯(lián)列回表查詢需要的所有列
SELECT film_id, description FROM film
INNER JOIN (
SELECT film_id
FROM film ORDER BY title LIMIT 10000, 10
) AS tmp USING (film_id);
2.取上次分頁查詢操作返回的主鍵ID作為下一次分頁查詢起始位置
SELECT film_id, description FROM film WHERE film_id > 10000 ORDER BY title LIMIT 10;
NULL值
空值是不占空間的,NULL是占空間的
聚合函數(shù),如COUNT(),MIN(),SUM()在進(jìn)行查詢時(shí)會忽略掉null值
查詢列不為NULL應(yīng)使用IS NOT NULL進(jìn)行查詢
條件查詢<>會過濾掉NULL值和空值
Explain
id:執(zhí)行編號,標(biāo)識select所屬的行。如果在語句中沒子查詢或關(guān)聯(lián)查詢,只有唯一的select,每行都將顯示1。否則,內(nèi)層的select語句一般會順序編號,對應(yīng)于其在原始語句中的位置
select_type: 顯示本行是簡單或復(fù)雜select。如果查詢有任何復(fù)雜的子查詢,則最外層標(biāo)記為PRIMARY(DERIVED、UNION、UNION RESUlT)
table: 訪問引用哪個(gè)表(引用某個(gè)查詢,如“derived3”)
type: 數(shù)據(jù)訪問讀取操作類型(ALL、index、range、ref、eq_ref、const/system、NULL)
possible_keys: 揭示哪一些索引可能有利于高效的查找
key: 顯示mysql決定采用哪個(gè)索引來優(yōu)化查詢
key_len: 顯示mysql在索引里使用的字節(jié)數(shù)
ref: 顯示了之前的表在key列記錄的索引中查找值所用的列或常量
rows: 為了找到所需的行而需要讀取的行數(shù),估算值,不精確。通過把所有rows列值相乘,可粗略估算整個(gè)查詢會檢查的行數(shù)
Extra: 額外信息,如using index、filesort等
select_type(查詢類型)
simple:簡單查詢,不包含子查詢和union
primary:查詢包含子查詢和union,最外層部分標(biāo)記為primary
derived:派生表,該臨時(shí)表是從子查詢中派生出來,位于from中的子查詢
union:union中第二個(gè)及以后的select,第一個(gè)union標(biāo)記為primary
union result:從匿名臨時(shí)表中檢索結(jié)果的select操作
dependent union:union中第二個(gè)或后面的select語句,取決于外層查詢
subquery:子查詢中第一個(gè)select
dependent subquery:子查詢中的第一個(gè)select,取決于外層查詢
type(訪問類型)
all:全表掃描
index:和全表掃描一樣,只是掃描表的順序是按照索引的順序,優(yōu)點(diǎn)是避免排序,但是開銷仍然非常大
range:范圍掃描,key列顯示使用哪個(gè)索引。當(dāng)使用如=,<>,>,>=,
ref:索引訪問,返回所有匹配的記錄,當(dāng)使用非唯一索引或者唯一索引非唯一前綴
eq_ref:最多只返回1條符合條件的記錄,使用唯一索引或者主鍵索引時(shí)
const/system:mysql能對查詢的某部分進(jìn)行優(yōu)化并將其轉(zhuǎn)化為一個(gè)常量
null:mysql能在優(yōu)化階段分解查詢語句,在執(zhí)行時(shí)不需訪問表或者索引
Extra
Using filesort: mysql會對結(jié)果使用外部索引排序,而不是按索引次序從表讀取行
Using temporary: mysql在對查詢結(jié)果排序時(shí)使用臨時(shí)表,常見于排序和分組查詢
Using index: 使用覆蓋索引掃描,直接從索引中過濾不需要的記錄并返回命中結(jié)果。這是在mysql服務(wù)器層完成的,但無需再回表查詢記錄
Using index condition:
Using where: mysql服務(wù)器將在存儲引擎檢索行后再進(jìn)行過濾
distinct: 優(yōu)化distinct操作,在找到第一匹配的元組后即停止找同樣值的動作
復(fù)制
主從復(fù)制
1.在主庫把數(shù)據(jù)更改記錄到二進(jìn)制文件中(Binary Log)
2.從庫將主庫上的日志復(fù)制到自己的中繼日志(Relay Log)上
3.從庫讀取中繼日志的事件,將其重放到從庫數(shù)據(jù)中
總結(jié)
以上是生活随笔為你收集整理的mysql分页 disti_MySql查询性能优化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 证券承销是什么意思
- 下一篇: 文件另存为时名称会改变_易经:人处在困境