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