Mysql問題收集

主從同步流程

異步模式

主節點

1、當主節點上進行 insert、update、delete 操作時,會按照時間先後順序寫入到 binlog 中;
2、當從節點連接到主節點時,主節點會創建一個叫做 binlog dump 的線程;

3、一個主節點有多少個從節點,就會創建多少個 binlog dump 線程;

4、當主節點的 binlog 發生變化的時候,也就是進行了更改操作,binlog dump 線程就會通知從節點 (Push模式),並將相應的 binlog 內容發送給從節點;

從節點

當開啓主從同步的時候,從節點會創建兩個線程用來完成數據同步的工作。

I/O線程: 此線程連接到主節點,主節點上的 binlog dump 線程會將 binlog 的內容發送給此線程。此線程接收到 binlog 內容後,再將內容寫入到本地的 relay log,並將讀取到的主庫bin log文件名和位置position記錄到master-info文件中,以便在下一次讀取用;

SQL線程: 該線程讀取 I/O 線程寫入的 relay log,並且根據 relay log 的內容對從數據庫做對應的操作。

主從配置一般都是和讀寫分離相結合,主服務器負責寫數據,從服務器負責讀數據,並保證主服務器的數據及時同步到從服務器。

全同步模式

指當主庫執行完一個事務,所有的從庫都執行了該事務才返回給客戶端。因爲需要等待所有從庫執行完該事務才能返回,所以全同步複製的性能必然會收到嚴重的影響。

半同步模式

介於異步複製和全同步複製之間,主庫在執行完客戶端提交的事務後不是立刻返回給客戶端,而是等待至少一個從庫接收到並寫到relay log中才返回給客戶端。相對於異步複製,半同步複製提高了數據的安全性,同時它也造成了一定程度的延遲,這個延遲最少是一個TCP/IP往返的時間。所以,半同步複製最好在低延時的網絡中使用

binlog記錄格式

MySQL 主從複製有三種方式:基於SQL語句的複製(statement-based replication,SBR),基於行的複製(row-based replication,RBR),混合模式複製(mixed-based replication,MBR)。對應的binlog文件的格式也有三種:STATEMENT,ROW,MIXED。

  • Statement-base Replication (SBR)就是記錄sql語句在bin log中,Mysql 5.1.4 及之前的版本都是使用的這種複製格式。優點是隻需要記錄會修改數據的sql語句到binlog中,減少了binlog日質量,節約I/O,提高性能。缺點是在某些情況下,會導致主從節點中數據不一致(比如sleep(),now()等)。
  • Row-based Relication(RBR)是mysql master將SQL語句分解爲基於Row更改的語句並記錄在bin log中,也就是隻記錄哪條數據被修改了,修改成什麼樣。優點是不會出現某些特定情況下的存儲過程、或者函數、或者trigger的調用或者觸發無法被正確複製的問題。缺點是會產生大量的日誌,尤其是修改table的時候會讓日誌暴增,同時增加bin log同步時間。也不能通過bin log解析獲取執行過的sql語句,只能看到發生的data變更。
  • Mixed-format Replication(MBR),MySQL NDB cluster 7.3 和7.4 使用的MBR。是以上兩種模式的混合,對於一般的複製使用STATEMENT模式保存到binlog,對於STATEMENT模式無法複製的操作則使用ROW模式來保存,MySQL會根據執行的SQL語句選擇日誌保存方式。

選型與配置

mysql主從模式默認是異步複製的,而MySQL Cluster是同步複製的,只要設置爲相應的模式即是在使用相應的同步策略。

從MySQL5.5開始,MySQL以插件的形式支持半同步複製。其實說明半同步複製是更好的方式,兼顧了同步和性能的問題。

集羣方案

  1. 首先反對大家做讀寫分離,關於這方面的原因解釋太多次數(增加技術複雜度、可能導致讀到落後的數據等),只說一點:99.8%的業務場景沒有必要做讀寫分離,只要做好數據庫設計優化 和配置合適正確的主機即可。

2.Keepalived+MySQL --確實有腦裂的問題,還無法做到準確判斷mysqld是否HANG的情況;

3.DRBD+Heartbeat+MySQL --同樣有腦裂的問題,還無法做到準確判斷mysqld是否HANG的情況,且DRDB是不需要的,增加反而會出問題;

3.MySQL Proxy -- 不錯的項目,可惜官方半途夭折了,不建議用,無法高可用,是一個寫分離;

4.MySQL Cluster -- 社區版本不支持NDB是錯誤的言論,商用案例確實不多,主要是跟其業務場景要求有關係、這幾年發展有點亂不過現在已經上正規了、對網絡要求高;

5.MySQL + MHA -- 可以解決腦裂的問題,需要的IP多,小集羣是可以的,但是管理大的就麻煩,其次MySQL + MMM 的話且坑很多,有MHA就沒必要採用MMM

事務

redo

它記錄的是數據庫中每個頁的修改,而不是某一行或某幾行修改成怎樣,可以用來恢復提交後的物理數據頁,且只能恢復到最後一次提交的位置。

有了redo以後,innodb引擎會把更新記錄先寫入redo log中,再修改Buffer Bool中的數據,這個時候狀態爲prepare狀態,還未真正提交成功,要等bin log寫入磁盤以後,纔會變成爲commit狀態,事務纔算是提交完成。

至於緩存中更新的數據文件何時刷入磁盤,則由後臺線程異步處理,這樣即使緩存刷入磁盤發生宕機,也可以在重啓時解析redo log重新刷盤。

redo log用到了WAL(Write-Ahead Logging)技術,這個技術的核心就在於修改記錄前,一定要先寫日誌,並保證日誌先落盤,才能算事務提交完成。

redo log日誌滿了,在擦除之前,需要確保這些要被擦除記錄對應在內存中的數據頁都已經刷到磁盤中了。擦除舊記錄騰出新空間這段期間,是不能再接收新的更新請求的,此刻MySQL的性能會下降。所以在併發量大的情況下,合理調整redo log的文件大小非常重要。

undo

如其名主要起到回滾的作用,它是保證事務原子性的關鍵。記錄的是數據修改前的狀態,在數據修改的流程中,同時會記錄一條與當前操作相反的邏輯日誌到undo log中。

我們舉個栗子:假如更新ID=1記錄的name字段,name原始數據爲小富,現改name爲程序員內點事

事務執行update X set name = 程序員內點事 where id =1語句時,先會在undo log中記錄一條相反邏輯的update X set name = 小富 where id =1記錄,這樣當某些原因導致服務異常事務失敗,就可以藉助undo log將數據回滾到事務執行前的狀態,保證事務的完整性。

bin log與redo log區別

  • 層次不同:redo log 是InnoDB存儲引擎實現的,bin log 是MySQL的服務器層實現的,但MySQL數據庫中的任何存儲引擎對於數據庫的更改都會產生bin log。
  • 作用不同:redo log 用於碰撞恢復(crash recovery),保證MySQL宕機也不會影響持久性;bin log 用於時間點恢復(point-in-time recovery),保證服務器可以基於時間點恢復數據和主從複製。
  • 內容不同:redo log 是物理日誌,內容基於磁盤的頁Page;bin log的內容是二進制,可以根據binlog_format參數自行設置。
  • 寫入方式不同:redo log 採用循環寫的方式記錄;binlog 通過追加的方式記錄,當文件大小大於給定值後,後續的日誌會記錄到新的文件上。
  • 刷盤時機不同:bin log在事務提交時寫入;redo log 在事務開始時即開始寫入。

bin log 與 redo log 功能並不衝突而是起到相輔相成的作用,需要二者同時記錄,才能保證當數據庫發生宕機重啓時,數據不會丟失。

MySql更新流程

MySQL更新數據的基礎流程,其中包括redo logbin logundo log三種日誌間的大致關係

三種日誌總結

undo log讓mysql有回滾事物的能力,redo log讓mysql有崩潰恢復的能力,以及我們現在說的bin log讓MySQL有搭建集羣、數據備份、恢復數據的能力

問題

手動用begin開啓事務,然後執行update語句,再然後執行commit語句,那上面的update更新流程哪些是update語句執行之後做的,哪些是commit語句執行之後做的?

實際上,redo log在內存中有一個redo log buffer,binlog 也有一個binlog cache.所以在手動開啓的事務中,你執行sql語句,其實是寫到redo log buffer和binlog cache中去的(肯定不可能是直接寫磁盤日誌,一個是性能差一個是回滾的時候不可能去回滾磁盤日誌吧),然後當你執行commit的時候,首先要將redo log的提交狀態遊prepare改爲commit狀態,然後就要把binlog cache刷新到binlog日誌(可能也只是flush到操作系統的page cache,這個就看你的mysql配置),redo log buffer刷新到redo log 日誌(刷新時機也是可以配置的)。 如果你回滾的話,就只用把binlog cache和redo log buffer中的數據清除就行了。

在update過程中,mysql突然宕機,會發生什麼情況?

1.如果redolog寫入了,處於prepare狀態,binlog還沒寫入,那麼宕機重啓後,redolog中的這個事務就直接回滾了。

2.如果redolog寫入了,binlog也寫入了,但redolog還沒有更新爲commit狀態,那麼宕機重啓以後,mysql會去檢查對應事務在binlog中是否完整。如果是,就提交事務;如果不是,就回滾事務。 (redolog處於prepare狀態,binlog完整啓動時就提交事務,爲啥要這麼設計? 主要是因爲binlog寫入了,那麼就會被從庫或者用這個binlog恢復出來的庫使用,爲了數據一致性就採用了這個策略) redo log和binlog是通過xid這個字段關聯起來的。

MVCC 多版本併發控制

通過多版本併發控制MVCC解決不可重複讀問題,加上間隙鎖(也就是併發控制)解決幻讀問題。因此InnodbRR隔離級別其實實現了串行化級別的效果,而且保留了比較好的併發性能。

MVCC解決讀寫互不阻塞和不重複讀的問題

MVCC只在READ COMMITTEDREPEATABLE READ 兩個隔離級別下工作。其他兩個隔離級別夠和MVCC不兼容。

因爲 READ UNCOMMITTED 總是讀取最新的數據行, 而不是符合當前事務版本的數據行。而 SERIALIZABLE 則會對所有讀取的行都加鎖。

Undo日誌版本鏈

undolog隱藏兩個字段trx_id(事務id)roll_pointer(指向上一次修改記錄指針)

ReadView一致性視圖

RR和RC生成一致性視圖的時機不一樣 (這也是兩種隔離級別實現的主要區別)

  • 讀提交(read committed RC) 是在每一次select的時候生成ReadView的

  • 可重複讀(repeatable read RR)是在第一次select的時候生成ReadView的

區別:RC在事務過程中,如果有其他事務提交了,可以讀取到,但是RR不可以

比如:事務A60,事務B61,61修改並提交,RC是可以讀取到新的提交的,RR不可以。

查詢生成的ReadView中包含trx_ids數組,就是當前未提交事務id的集合

版本鏈比對規則:

min_id,max_id分別表示trx_ids中最小的事務id,最大的事務id

  1. 如果 row 的 trx_id 落在綠色部分( trx_id<min_id ),表示這個版本是已提交的事務生成的,這個數據是可見的;
  2. 如果 row 的 trx_id 落在紅色部分( trx_id>max_id ),表示這個版本是由將來啓動的事務生成的,是不可見的(若 row 的 trx_id 就是當前自己的事務是可見的);
  3. 如果 row 的 trx_id 落在黃色部分(min_id <=trx_id<= max_id),那就包括兩種情況
    1. 若 row 的 trx_id 在視圖數組中,表示這個版本是由還沒提交的事務生成的,不可見(若 row 的 trx_id 就是當前自己的事務是可見的);
    2. 若 row 的 trx_id 不在視圖數組中,表示這個版本是已經提交了的事務生成的,可見。

我勸!這位年輕人不講MVCC,耗子尾汁!

京東面試官問我:“聊聊MySql事務,MVCC?”

Mysql事務隔離與鎖

  • 未提交讀:事務A中修改完數據M後,立刻對這個數據M加上共享鎖(S鎖)[當事務A繼續修改數據M的時候,先釋放掉S鎖,再修改數據,再加上S鎖],根據S鎖的特性,事務B可以讀到事務A修改後的數據(無論事務A是否提交,因爲是共享鎖,隨時隨地都能查到數據A修改後的結果),事務B不能去修改數據M,直到事務A提交,釋放掉S鎖。
  • 已提交讀:事務A在修改數據M後立刻加X鎖,事務B不能修改數據M,同時不能查詢到最新的數據M(避免髒讀),查詢到的數據M是上一個版本(Innodb MVCC快照)的
  • 可重複讀:是在已提交讀的基礎上,對讀到的數據M瞬間加上共享鎖,直到事務結束才釋放(保證了其他事務沒辦法修改該數據)
  • 串行化:是從MVCC併發控制退化到基於鎖的併發控制,對事務中所有讀取操作加S鎖,寫操作加X鎖,這樣可以避免髒讀,不可重複讀,幻讀,更新丟失,開銷也最大,會造成讀寫衝突,併發程度也最低。

Mysql 當前讀 快照讀

MySQL-當前讀、快照讀、MVCC

當前讀

  • select...lock in share mode (共享讀鎖)
  • select...for update
  • update , delete , insert

當前讀的實現方式:next-key鎖(行記錄鎖+Gap間隙鎖)
間隙鎖:只有在Read RepeatableSerializable隔離級別纔有,就是鎖定那些範圍空間內的數據,假設鎖定id>3的數據,id有3,4,5,那麼4,5和後面的數字都會被鎖定,像6,7...,爲什麼要這樣?因爲如果我們不鎖定沒有的數據,當加入了新的數據id=6,就會出現幻讀,間隙鎖避免了幻讀。

快照讀

單純的select操作,不包括上述 select ... lock in share mode, select ... for update。    
Read Committed隔離級別:每次select都生成一個快照讀
Read Repeatable隔離級別:開啓事務後第一個select語句纔是快照讀的地方,而不是一開啓事務就快照讀

快照讀的實現方式:undolog和多版本併發控制MVCC

Mysql explain 優化

  • system: 表中只有一條數據. 這個類型是特殊的 const 類型.

  • const: 針對主鍵或唯一索引的等值查詢掃描, 最多隻返回一行數據. const 查詢速度非常快, 因爲它僅僅讀取一次即可.
    例如下面的這個查詢, 它使用了主鍵索引, 因此 type 就是 const 類型的.

    explain select * from user_info where id = 2
    
  • eq_ref: 此類型通常出現在多表的 join 查詢, 表示對於前表的每一個結果, 都只能匹配到後表的一行結果. 並且查詢的比較操作通常是 =, 查詢效率較高.

    EXPLAIN SELECT * FROM user_info, order_info WHERE user_info.id = order_info.user_id
    
  • ref: 此類型通常出現在多表的 join 查詢, 針對於非唯一或非主鍵索引, 或者是使用了 最左前綴 規則索引的查詢.

    EXPLAIN SELECT * FROM user_info, order_info WHERE user_info.id = order_info.user_id AND order_info.user_id = 5
    
  • range: 表示使用索引範圍查詢, 通過索引字段範圍獲取表中部分數據記錄. 這個類型通常出現在 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, IN() 操作中.
    typerange 時, 那麼 EXPLAIN 輸出的 ref 字段爲 NULL, 並且 key_len 字段是此次查詢中使用到的索引的最長的那個.
  • index: 表示全索引掃描(full index scan), 和 ALL 類型類似, 只不過 ALL 類型是全表掃描, 而 index 類型則僅僅掃描所有的索引, 而不掃描數據.
    index 類型通常出現在: 所要查詢的數據直接在索引樹中就可以獲取到, 而不需要掃描數據. 當是這種情況時, Extra 字段 會顯示 Using index.
  • ALL: 表示全表掃描, 這個類型的查詢是性能最差的查詢之一. 通常來說, 我們的查詢不應該出現 ALL 類型的查詢, 因爲這樣的查詢在數據量大的情況下, 對數據庫的性能是巨大的災難. 如一個查詢是 ALL 類型查詢, 那麼一般來說可以對相應的字段添加索引來避免.
    下面是一個全表掃描的例子, 可以看到, 在全表掃描時, possible_keys 和 key 字段都是 NULL, 表示沒有使用到索引, 並且 rows 十分巨大, 因此整個查詢效率是十分低下的.

type 類型的性能比較

通常來說, 不同的 type 類型的性能關係如下:
ALL < index < range ~ index_merge < ref < eq_ref < const < system
ALL 類型因爲是全表掃描, 因此在相同的查詢條件下, 它是速度最慢的.
index 類型的查詢雖然不是全表掃描, 但是它掃描了所有的索引, 因此比 ALL 類型的稍快.
後面的幾種類型都是利用了索引來查詢數據, 因此可以過濾部分或大部分數據, 因此查詢效率就比較高了.

MySQL 性能優化神器 Explain 使用分析

聯合索引在B+樹上的結構

首先,表T1有字段a,b,c,d,e,其中a是主鍵,除e爲varchar其餘爲int類型,並創建了一個聯合索引idx_t1_bcd(b,c,d),然後b、c、d三列作爲聯合索引,在B+樹上的結構正如上圖所示。聯合索引的所有索引列都出現在索引數上,並依次比較三列的大小。

聯合索引在B+樹上的存儲結構及數據查找方式

Mysql中的innodb與myisam區別?

  1. InnoDB 支持事務,MyISAM 不支持事務。這是 MySQL 將默認存儲引擎從 MyISAM 變成 InnoDB 的重要原因之一;

  2. InnoDB 支持外鍵,而 MyISAM 不支持。對一個包含外鍵的 InnoDB 錶轉爲 MYISAM 會失敗;

  3. InnoDB 是聚集索引,MyISAM 是非聚集索引。聚簇索引的文件存放在主鍵索引的葉子節點上,因此 InnoDB 必須要有主鍵,通過主鍵索引效率很高。但是輔助索引需要兩次查詢,先查詢到主鍵,然後再通過主鍵查詢到數據。因此,主鍵不應該過大,因爲主鍵太大,其他索引也都會很大。而 MyISAM 是非聚集索引,數據文件是分離的,索引保存的是數據文件的指針。主鍵索引和輔助索引是獨立的。

  4. InnoDB 不保存表的具體行數,執行 select count(*) from table 時需要全表掃描。而MyISAM 用一個變量保存了整個表的行數,執行上述語句時只需要讀出該變量即可,速度很快;

  5. InnoDB 最小的鎖粒度是行鎖,MyISAM 最小的鎖粒度是表鎖。一個更新語句會鎖住整張表,導致其他查詢和更新都會被阻塞,因此併發訪問受限。這也是 MySQL 將默認存儲引擎從 MyISAM 變成 InnoDB 的重要原因之一;

索引的幾大原則

1.最左前綴匹配原則,非常重要的原則,mysql會一直向右匹配直到遇到範圍查詢(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到,a,b,d的順序可以任意調整。

2.=和in可以亂序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序,mysql的查詢優化器會幫你優化成索引可以識別的形式。

3.儘量選擇區分度高的列作爲索引,區分度的公式是count(distinct col)/count(*),表示字段不重複的比例,比例越大我們掃描的記錄數越少,唯一鍵的區分度是1,而一些狀態、性別字段可能在大數據面前區分度就是0,那可能有人會問,這個比例有什麼經驗值嗎?使用場景不同,這個值也很難確定,一般需要join的字段我們都要求是0.1以上,即平均1條掃描10條記錄。

4.索引列不能參與計算,保持列“乾淨”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很簡單,b+樹中存的都是數據表中的字段值,但進行檢索時,需要把所有元素都應用函數才能比較,顯然成本太大。所以語句應該寫成create_time = unix_timestamp(’2014-05-29’)。

5.儘量的擴展索引,不要新建索引。比如表中已經有a的索引,現在要加(a,b)的索引,那麼只需要修改原來的索引即可。

慢查詢優化基本步驟

  1. 先運行看看是否真的很慢,注意設置SQL_NO_CACHE

  2. where條件單表查,鎖定最小返回記錄表。這句話的意思是把查詢語句的where都應用到表中返回的記錄數最小的表開始查起,單表每個字段分別查詢,看哪個字段的區分度最高

  3. explain查看執行計劃,是否與1預期一致(從鎖定記錄較少的表開始查詢)

  4. order by limit 形式的sql語句讓排序的表優先查

  5. 瞭解業務方使用場景

  6. 加索引時參照建索引的幾大原則

  7. 觀察結果,不符合預期繼續從0分析

mysql索引失效的場景

  • 使用!= 或者 <> 導致索引失效
  • 字類型不一致導致的索引失效(字段類型與查詢條件類型不一致)
  • 函數導致的索引失效
  • 運算符導致的索引失效
    SELECT * FROM user WHERE age - 1 = 20;
    
  • OR引起的索引失效

    OR導致索引是在特定情況下的,並不是所有的OR都是使索引失效,如果OR連接的是同一個字段,那麼索引不會失效,反之索引失效。

  • 模糊搜索導致的索引失效

MySQL中IS NULL、IS NOT NULL、!=不能用索引?胡扯!

導致MySQL索引失效的幾種常見寫法

MySQL - 負向查詢完全不能走索引麼?

「MySQL系列」索引設計原則、索引失效場景、limit 、order by、group by 等常見場景優化

mysql對千萬級數據的優化

mysql數據表規模90000000(九千萬)左右,怎麼優化查詢?

MySQL 對於千萬級的大表要怎麼優化?

mysql對執行語句分析

mysql索引命中分析

MySQL索引原理及慢查詢優化

爲什麼不建議將字段設置爲可以爲null

  • Null 列需要更多的存儲空間:需要一個額外字節作爲判斷是否爲 NULL 的標誌位
  • NOT IN、!= 等負向條件查詢在有 NULL 值的情況下返回永遠爲空結果,查詢容易出錯

MySQL 一千個不用 Null 的理由

or 、in | not in 、is null | is not null、!=、<>,使用,是否走索引

  1. 全表掃描是否比索引更快,以至於優化器選擇全表掃描
  2. mysql-server 的版本。。。
  3. 可以通過優化語法或者配置優化器,走索引

not in或者!=會導致索引失效並不是絕對的 對於數據較爲均勻的場景是會失效的 但是如果業務數據嚴重不均的字段加了索引的話是不一定失效的 mysql自己會做判斷 並不是絕對判定不使用索引 比如表A性別列有男10000條女20條,當sex!=’男‘是可以使用索引的 同樣的如果你sex='男'反而不會使用索引 mysql自己會選擇最優的檢索方式

那既然IS NULLIS NOT NULL!=這些條件都可能使用到索引,那到底什麼時候索引,什麼時候採用全表掃描呢?

答案很簡單:成本。當然,關於如何定量的計算使用某個索引執行查詢的成本比較複雜,我們在小冊中花了很大的篇幅來嘮叨了。不過因爲篇幅有限,我們在這裏只准備定性的分析一下。對於使用二級索引進行查詢來說,成本組成主要有兩個方面:

  • 讀取二級索引記錄的成本
  • 將二級索引記錄執行回表操作,也就是到聚簇索引中找到完整的用戶記錄的操作所付出的成本。

很顯然,要掃描的二級索引記錄條數越多,那麼需要執行的回表操作的次數也就越多,達到了某個比例時,使用二級索引執行查詢的成本也就超過了全表掃描的成本(舉一個極端的例子,比方說要掃描的全部的二級索引記錄,那就要對每條記錄執行一遍回表操作,自然不如直接掃描聚簇索引來的快)。

所以MySQL優化器在真正執行查詢之前,對於每個可能使用到的索引來說,都會預先計算一下需要掃描的二級索引記錄的數量,比方說對於下邊這個查詢:

SELECT * FROM s1 WHERE key1 IS NULL;

優化器會分析出此查詢只需要查找key1值爲NULL的記錄,然後訪問一下二級索引idx_key1,看一下值爲NULL的記錄有多少(如果符合條件的二級索引記錄數量較少,那麼統計結果是精確的,如果太多的話,會採用一定的手段計算一個模糊的值,當然算法也比較麻煩,我們就不展開說了,小冊裏有說),這種在查詢真正執行前優化器就率先訪問索引來計算需要掃描的索引記錄數量的方式稱之爲index dive。當然,對於某些查詢,比方說WHERE子句中有IN條件,並且IN條件中包含許多參數的話,比方說這樣:

SELECT * FROM s1 WHERE key1 IN ('a', 'b', 'c', ... , 'zzzzzzz');

這樣的話需要統計的key1值所在的區間就太多了,這樣就不能採用index dive的方式去真正的訪問二級索引idx_key1,而是需要採用之前在背地裏產生的一些統計數據去估算匹配的二級索引記錄有多少條(很顯然根據統計數據去估算記錄條數比index dive的方式精確性差了很多)。

反正不論採用index dive還是依據統計數據估算,最終要得到一個需要掃描的二級索引記錄條數,如果這個條數佔整個記錄條數的比例特別大,那麼就趨向於使用全表掃描執行查詢,否則趨向於使用這個索引執行查詢。

理解了這個也就好理解爲什麼在WHERE子句中出現IS NULLIS NOT NULL!=這些條件仍然可以使用索引,本質上都是優化器去計算一下對應的二級索引數量佔所有記錄數量的比值而已。

MySQL中IS NULL、IS NOT NULL、!=不能用索引?胡扯!

MySQL索引原理及慢查詢優化

無效索引

  • 如果條件中有or,即使其中有條件帶索引也不會使用(這也是爲什麼儘量少用or的原因)注意:要想使用or,又想讓索引生效,只能將or條件中的每個列都加上索引
  • 對於多列索引,不是使用的第一部分(第一個),則不會使用索引,就是未匹配到最左匹配原則
  • like查詢是以%開頭
  • 如果列類型是字符串,那一定要在條件中將數據使用引號引用起來,否則不使用索引
  • where查詢條件中,對列使用了函數的(day(column)=....
  • 如果mysql估計使用全表掃描要比使用索引快,則不使用索引

Mysql索引失效的幾種情況

Mysql有效索引和無效索引的介紹

MySQL高級 之 索引失效與優化詳解

索引性能優化

  • 最左匹配原則
  • 覆蓋索引
  • 索引下推

MySQL 5.6中 引入的索引下推優化(index condition push down), 可以在索引遍歷過程中,對索引中包含的字段先做判斷,直接過濾掉不滿足條件的記錄,減少回表次數,比如 like '張%'

參考:

面試官你好,我已經掌握了MySQL主從配置和讀寫分離,你看我還有機會嗎?

MySQL 半同步複製模式說明及配置示例 - 運維小結

MySQL主從同步詳解與配置

MySQL集羣之五大常見的MySQL高可用方案(轉)

高性能、高可用、可擴展的MySQL集羣如何組建?

MySQL不會丟失數據的祕密,就藏在它的 7種日誌裏

MySQL必知必會:簡介undo log、truncate、以及undo log如何幫你回滾事務

理解 MySQL 一致性非鎖定讀原理

MySQL · 引擎特性 · 庖丁解InnoDB之REDO LOG

mysql_一條更新語句的執行流程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章