MySQL创建索引跳过redo_明明我建了索引,为什么sql执行的还是这么慢?
原標(biāo)題:明明我建了索引,為什么sql執(zhí)行的還是這么慢?
很多同學(xué)經(jīng)常遇到這樣一個(gè)問題,就是為了避免sql 執(zhí)行緩慢,提前將各種可能用到的字段都添加上索引,查詢的時(shí)候盡可能的使用這些字段,避免全表掃描。可是,明明我已經(jīng)添加了索引,問什么還是這么慢呢?
一條 SQL 語句執(zhí)行的很慢,那是每次執(zhí)行都很慢呢?還是大多數(shù)情況下是正常的,偶爾出現(xiàn)很慢呢?所以我覺得,我們還得分以下兩種情況來討論。
大多數(shù)情況是正常的,只是偶爾會出現(xiàn)很慢的情況。
在數(shù)據(jù)量不變的情況下,這條SQL語句一直以來都執(zhí)行的很慢。
針對這兩種情況,我們來分析下可能是哪些原因?qū)е碌摹?/p>
一、針對偶爾很慢的情況
一條 SQL 大多數(shù)情況正常,偶爾才能出現(xiàn)很慢的情況,針對這種情況,我覺得這條SQL語句的書寫本身是沒什么問題的,而是其他原因?qū)е碌?#xff0c;那會是什么原因呢?
1、數(shù)據(jù)庫在刷新臟頁
當(dāng)我們要往數(shù)據(jù)庫插入一條數(shù)據(jù)、或者要更新一條數(shù)據(jù)的時(shí)候,我們知道數(shù)據(jù)庫會在內(nèi)存中把對應(yīng)字段的數(shù)據(jù)更新了,但是更新之后,這些更新的字段并不會馬上同步持久化到磁盤中去,而是把這些更新的記錄寫入到 redo log 日記中去,等到空閑的時(shí)候,在通過 redo log 里的日記把最新的數(shù)據(jù)同步到磁盤中去。數(shù)據(jù)庫在在同步數(shù)據(jù)到磁盤的時(shí)候,就有可能導(dǎo)致我們的SQL語句執(zhí)行的很慢了。
2、拿不到鎖
這個(gè)就比較容易想到了,我們要執(zhí)行的這條語句,剛好這條語句涉及到的表,別人在用,并且加鎖了,我們拿不到鎖,只能慢慢等待別人釋放鎖了。或者,表沒有加鎖,但要使用到的某個(gè)一行被加鎖了,這個(gè)時(shí)候,我也沒辦法啊。
下來我們來訪分析下第二種情況,我覺得第二種情況的分析才是最重要的。
二、針對一直都這么慢的情況
我們先來假設(shè)我們有一個(gè)表,表里有下面兩個(gè)字段,分別是主鍵 id,和兩個(gè)普通字段 c 和 d。并建立相關(guān)索引。
mysql> CREATE TABLE `t` (
`id` int(11) NOT ,
`c` int(11) DEFAULT ,
`d` int(11) DEFAULT ,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
1、沒用到索引
沒有用上索引,我覺得這個(gè)原因是很多人都能想到的,例如你要查詢這條語句:
select * from t where 100
1)字段有索引,但卻沒有用索引
好吧,這個(gè)時(shí)候你給 c 這個(gè)字段加上了索引,然后又查詢了一條語句:
select * from t where c - 1 = 1000;
3)函數(shù)操作導(dǎo)致沒有用上索引
如果我們在查詢的時(shí)候,對字段進(jìn)行了函數(shù)操作,也是會導(dǎo)致沒有用上索引的,例如:
select * from t where pow(c,2) = 1000;
2、數(shù)據(jù)庫自己選錯(cuò)索引
我們在進(jìn)行查詢操作的時(shí)候,例如:
select * from t where 100 < c and c < 100000;
就算你在 c 字段上有索引,系統(tǒng)也并不一定會走 c 這個(gè)字段上的索引,而是有可能會直接掃描掃描全表,找出所有符合 100 < c and c < 100000 的數(shù)據(jù)。
為什么會這樣呢?系統(tǒng)是有可能走全表掃描而不走索引的。
那系統(tǒng)是怎么判斷呢?
判斷來源于系統(tǒng)的預(yù)測,也就是說,如果要走 c 字段索引的話,系統(tǒng)會預(yù)測走 c 字段索引大概需要掃描多少行。如果預(yù)測到要掃描的行數(shù)很多,它可能就不走索引而直接掃描全表了。
那么問題來了,系統(tǒng)是怎么預(yù)測判斷的呢?這里我給你講下系統(tǒng)是怎么判斷的吧,雖然這個(gè)時(shí)候我已經(jīng)寫到脖子有點(diǎn)酸了。
系統(tǒng)是通過索引的區(qū)分度來判斷的,一個(gè)索引上不同的值越多,意味著出現(xiàn)相同數(shù)值的索引越少,意味著索引的區(qū)分度越高。我們也把區(qū)分度稱之為基數(shù),即區(qū)分度越高,基數(shù)越大。所以呢,基數(shù)越大,意味著符合 100 < c and c < 10000 這個(gè)條件的行數(shù)越少。
所以呢,一個(gè)索引的基數(shù)越大,意味著走索引查詢越有優(yōu)勢。
三、總結(jié)
建了索引,并且使用了索引字段,并不代表著查詢一定走索引。sql 執(zhí)行緩慢存在多種可能,具體問題具體分析吧。添加索引,慎用函數(shù),根據(jù)規(guī)則避免走全表掃描。優(yōu)化是一個(gè)過程,需要慢慢琢磨。
ps:看更多干貨,加入技術(shù)交流微信群可以關(guān)注我的公眾號360linker返回搜狐,查看更多
責(zé)任編輯:
總結(jié)
以上是生活随笔為你收集整理的MySQL创建索引跳过redo_明明我建了索引,为什么sql执行的还是这么慢?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql存储表情测试_Mysql正确的
- 下一篇: ubuntu pip更新_Cubietr