1. 程式人生 > >InnoDB的關鍵特性-插入快取,兩次寫,自適應hash索引詳解

InnoDB的關鍵特性-插入快取,兩次寫,自適應hash索引詳解

InnoDB儲存引擎的關鍵特性包括插入緩衝兩次寫(double write)、自適應雜湊索引(adaptive hash index)。這些特性為InnoDB儲存引擎帶來了更好的效能和更高的可靠性。

插入緩衝

插入緩衝是InnoDB儲存引擎關鍵特性中最令人激動的。不過,這個名字可能會讓人認為插入緩衝是緩衝池中的一個部分。其實不然,InnoDB緩衝池中有Insert Buffer資訊固然不錯,但是Insert Buffer和資料頁一樣,也是物理頁的一個組成部分。

主鍵是行唯一的識別符號,在應用程式中行記錄的插入順序是按照主鍵遞增的順序進行插入的。因此,插入聚集索引一般是順序的,不需要磁碟的隨機讀取。

比如說我們按下列SQL定義的表:create table t(id int auto_increment,name varchar(30),primary key(id));

id列是自增長的,這意味著當執行插入操作時,id列會自動增長,頁中的行記錄按id執行順序存放。一般情況下,不需要隨機讀取另一頁執行記錄的存放。因此,在這樣的情況下,插入操作一般很快就能完成。但是,不可能每張表上只有一個聚集索引,在更多的情況下,一張表上有多個非聚集的輔助索引(secondary index)。比如,我們還需要按照name這個欄位進行查詢,並且name這個欄位不是唯一的。

表是按如下的SQL語句定義的:create table t (id int auto_increment,name varchar(30),primary key(id),key(name));

這樣的情況下產生了一個非聚集的並且不是唯一的索引。在進行插入操作時,資料頁的存放還是按主鍵id的執行順序存放,但是對於非聚集索引,葉子節點的插入不再是順序的了。這時就需要離散地訪問非聚集索引頁,插入效能在這裡變低了。然而這並不是這個name欄位上索引的錯誤,因為B+樹的特性決定了非聚集索引插入的離散性。

InnoDB儲存引擎開創性地設計了插入緩衝,對於非聚集索引的插入或更新操作,不是每一次直接插入索引頁中,而是先判斷插入的非聚集索引頁是否在緩衝池中。如果在,則直接插入;如果不在,則先放入一個插入緩衝區中,好似欺騙資料庫這個非聚集的索引已經插到葉子節點了,然後再以一定的頻率執行插入緩衝和非聚集索引頁子節點的合併操作

,這時通常能將多個插入合併到一個操作中(因為在一個索引頁中),這就大大提高了對非聚集索引執行插入和修改操作的效能。

插入緩衝的使用需要滿足以下兩個條件:

1.索引是輔助索引。

2.索引不是唯一的。

當滿足以上兩個條件時,InnoDB儲存引擎會使用插入緩衝,這樣就能提高效能了。不過考慮一種情況,應用程式執行大量的插入和更新操作,這些操作都涉及了不唯一的非聚集索引,如果在這個過程中資料庫發生了宕機,這時候會有大量的插入緩衝並沒有合併到實際的非聚集索引中。如果是這樣,恢復可能需要很長的時間,極端情況下甚至需要幾個小時來執行合併恢復操作。

輔助索引不能是唯一的,因為在把它插入到插入緩衝時,我們並不去查詢索引頁的情況。如果去查詢肯定又會出現離散讀的情況,插入緩衝就失去了意義。

檢視插入緩衝的資訊:

show engine innodb status\G


seg size顯示了當前插入緩衝的大小為2*16KB,free list len代表了空閒列表的長度,size代表了已經合併記錄頁的數量。

下面一行可能是我們真正關心的,因為它顯示了提高效能了。inserts代表插入的記錄數,merged recs代表合併的頁的數量,merges代表合併的次數。

merged recs:merges大約為3:1,代表插入緩衝將對於非聚集索引頁的IO請求大約降低了3倍。

問題:

目前插入緩衝存在一個問題是,在寫密集的情況下,插入緩衝會佔用過多的緩衝池記憶體,預設情況下最大可以佔用1/2的緩衝池記憶體。Percona已釋出一些patch來修正插入緩衝佔用太多緩衝池記憶體的問題,具體的可以到http://www.percona.com/percona-lab.html查詢。簡單來說,修改IBUF_POOL_SIZE_PER_MAX_SIZE就可以對插入緩衝的大小進行控制,例如,將IBUF_POOL_SIZE_PER_MAX_SIZE改為3,則最大隻能使用1/3的緩衝池記憶體。

兩次寫

如果說插入緩衝帶給InnoDB儲存引擎的是效能,那麼兩次寫帶給InnoDB儲存引擎的是資料的可靠性。當資料庫宕機時,可能發生資料庫正在寫一個頁面,而這個頁只寫了一部分(比如16K的頁,只寫前4K的頁)的情況,我們稱之為部分寫失效(partial page write)。在InnoDB儲存引擎未使用double write技術前,曾出現過因為部分寫失效而導致資料丟失的情況。

有人也許會想,如果發生寫失效,可以通過重做日誌進行恢復。這是一個辦法。但是必須清楚的是,重做日誌中記錄的是對頁的物理操作,如偏移量800,寫'aaaa'記錄。如果這個頁本身已經損壞,再對其進行重做是沒有意義的。這就是說,在應用(apply)重做日誌前,我們需要一個頁的副本,當寫入失效發生時,先通過頁的副本來還原該頁再進行重做,這就是doublewrite。

InnoDB儲存引擎doublewrite的體系架構如圖2-4所示


doublewrite由兩部分組成:一部分是記憶體中的doublewrite buffer,大小為2MB;另一部分是物理磁碟上共享表空間中連續的128個頁,即兩個區(extent),大小同樣為2MB(頁的副本)。當緩衝池的髒頁重新整理時,並不直接寫磁碟,而是會通過memcpy函式將髒頁先拷貝到記憶體中的doublewrite buffer,之後通過doublewrite buffer再分兩次,每次寫入1MB到共享表空間的物理磁碟上,然後馬上呼叫fsync函式,同步磁碟,避免緩衝寫帶來的問題。在這個過程中,因為doublewrite頁是連續的,因此這個過程是順序寫的,開銷並不是很大。在完成doublewrite頁的寫入後,再將doublewrite buffer中的頁寫入各個表空間檔案中,此時的寫入則是離散的。

可以通過以下命令觀察到doublewrite執行的情況: show global status like 'innodb_dblwr%'\G


doublewrite一共寫了18 445個頁,但實際的寫入次數為434,(42:1)   基本上符合64:1。

如果發現你的系統在高峰時Innodb_dblwr_pages_written:Innodb_dblwr_writes遠小於64:1,那麼說明你的系統寫入壓力並不是很高。

如果作業系統在將頁寫入磁碟的過程中崩潰了,在恢復過程中,InnoDB儲存引擎可以從共享表空間中的doublewrite中找到改頁的一個副本,將其拷貝到表空間檔案,再應用重做日誌。下面顯示了由doublewrite進行恢復的一種情況: 

123456789101112131415161718090924 11:36:32 mysqld restarted090924 11:36:33 InnoDB:Database was not shut down normally!InnoDB:Starting crash recovery.InnoDB:Reading tablespace information from the.ibd files……InnoDB:Error:space id in fsp header 0,but in the page header 4294967295InnoDB:Error:tablespace id 4294967295 in file./test/t.ibd is not sensibleInnoDB:Error:tablespace id 0 in file./test/t2.ibd is not sensible090924 11:36:33 InnoDB:Operating system error number 40 in a file operation.InnoDB:Error number 40 means'Too many levels of symbolic links'.InnoDB:Some operating system error numbers are described atInnoDB:http://dev.mysql.com/doc/refman/5.0/en/operating-system-error-codes.htmlInnoDB:File name./now/memberInnoDB:File operation call:'stat'.InnoDB:Error:os_file_readdir_next_file()returned-1 inInnoDB:directory./nowInnoDB:Crash recovery may have failed for some.ibd files!InnoDB:Restoring possible half-written data pages from the doublewriteInnoDB:buffer……

引數skip_innodb_doublewrite可以禁止使用兩次寫功能,這時可能會發生前面提及的寫失效問題。不過,如果你有多臺從伺服器(slave server),需要提供較快的效能(如slave上做的是RAID0),也許啟用這個引數是一個辦法。不過,在需要提供資料高可靠性的主伺服器(master server)上,任何時候我們都應確保開啟兩次寫功能。

注意:有些檔案系統本身就提供了部分寫失效的防範機制,如ZFS檔案系統。在這種情況下,我們就不要啟用doublewrite了。 

自適應雜湊索引

雜湊(hash)是一種非常快的查詢方法,一般情況下查詢的時間複雜度為O(1)。常用於連線(join)操作,如SQL Server和Oracle中的雜湊連線(hash join)。但是SQL Server和Oracle等常見的資料庫並不支援雜湊索引(hash index)。MySQL的Heap儲存引擎預設的索引型別為雜湊,而InnoDB儲存引擎提出了另一種實現方法,自適應雜湊索引(adaptive hash index)。

InnoDB儲存引擎會監控表上索引的查詢,如果觀察到建立雜湊索引可以帶來速度的提升,則建立雜湊索引,所以稱之為自適應(adaptive)的。自適應雜湊索引通過緩衝池的B+樹構造而來,因此建立的速度很快。而且不需要將整個表都建雜湊索引,InnoDB儲存引擎會自動根據訪問的頻率模式來為某些頁建立雜湊索引。

根據InnoDB的官方文件顯示,啟用自適應雜湊索引後,讀取和寫入速度可以提高2倍;對於輔助索引的連線操作,效能可以提高5倍。自適應雜湊索引是非常好的優化模式,其設計思想是資料庫自優化(self-tuning),即無需DBA對資料庫進行調整。

檢視當前自適應雜湊索引的使用狀況:show engine innodb status\G



現在可以看到自適應雜湊索引的使用資訊了,包括自適應雜湊索引的大小、使用情況、每秒使用自適應雜湊索引搜尋的情況。值得注意的是,雜湊索引只能用來搜尋等值的查詢,如select * from table where index_col='xxx',而對於其他查詢型別,如範圍查詢,是不能使用的。因此,這裡出現了non-hash searches/s的情況。用hash searches:non-hash searches命令可以大概瞭解使用雜湊索引後的效率。

由於自適應雜湊索引是由InnoDB儲存引擎控制的,所以這裡的資訊只供我們參考。不過我們可以通過引數innodb_adaptive_hash_index來禁用或啟動此特性,預設為開啟。

相關推薦

InnoDB關鍵特性-插入快取,,適應hash索引

InnoDB儲存引擎的關鍵特性包括插入緩衝、兩次寫(double write)、自適應雜湊索引(adaptive hash index)。這些特性為InnoDB儲存引擎帶來了更好的效能和更高的可靠性。插入緩衝插入緩衝是InnoDB儲存引擎關鍵特性中最令人激動的。不過,這個名字

InnoDB關鍵特性適應hash索引

    一、索引的資源消耗分析 1、索引三大特點   1、小:只在一個到多個列建立索引   2、有序:可以快速定位終點   3、有棵樹:可以定位起點,樹高一般小於等於3 2、索引的資源消耗點   1、樹的高度,順序訪問索引的資料頁

IOS viewDidLoad方法被執行(viewDidLoad和loadView方法

為了搞清楚viewDidLoad、loadView等方法的用途和呼叫順序,寫了一個小demo,不料viewDidLoad方法被執行了兩次,模擬器也一直是黑屏。查看了這兩個方法的官方解釋後找到了錯誤原因和解決方法。 首先來看UIViewController.h檔

InnoDB關鍵特性之change buffer

dap 數據節點 排好序 適合 pre 成本 可能 like 命中 一、關於IOT:索引組織表   表在存儲的時候按照主鍵排序進行存儲,同時在主鍵上建立一棵樹,這樣就形成了一個索引組織表,一個表的存儲方式以索引的方式來組織存儲的。   所以,MySQL表一定要加上主鍵,通過

InnoDB關鍵特性之double write

一、髒頁刷盤風險 關於IO的最小單位:   1、資料庫IO的最小單位是16K(MySQL預設,oracle是8K)   2、檔案系統IO的最小單位是4K(也有1K的)   3、磁碟IO的最小單位是512K 因此,存在IO寫入導致page損壞的風險:   二、doublew

優化版本對生成對抗網路生成手數字集(附程式碼)

# 先匯入必要的庫 import os import cv2 import tensorflow as tf import numpy as np # 把結果儲存到本地的一個庫 import pickle import matplotlib.pyplot as plt from tensor

瀏覽器快取 from memory cache與from disk cache

在chrome瀏覽器中的控制檯Network中size欄通常會有三種狀態 1.from memory cache 2.from disk cache 3.資源本身的大小(如:1.5k) 那麼問題來了 1.三種區別在哪裡;2.瀏覽器採取不同措施的原則是什麼;3.其他瀏覽器的策略 下

C++通過jsoncpp類庫讀JSON檔案-json用法

介紹: JSON 是常用的資料的一種格式,各個語言或多或少都會用的JSON格式。 JSON是一個輕量級的資料定義格式,比起XML易學易用,而擴充套件功能不比XML差多少,用之進行資料交換是一個很好的選擇。JSON的全稱為:JavaScript Object Notation ,顧名思義,JSON是用於標記

MySQL讀分離和多例項

mysql讀寫分離的優缺點 資料庫讀寫分離的好處: – 減輕單臺伺服器的壓力,增加併發量,提高了硬體利用率 資料庫讀寫分離的缺點: – 單點故障 – 當訪問量大時,排程器的效能會成為瓶錦 讀寫分離環境: 51為主 52為從 57為排程器 1 部署Mysql主從同步結構,一主一從

Java併發--互斥同步--Java種鎖機制synchronized和ReentrantLock

Java 提供了兩種鎖機制來控制多個執行緒對共享資源的互斥訪問,第一個是 JVM 實現的 synchronized,而另一個是 JDK 實現的 ReentrantLock。 synchronized 1. 同步一個程式碼塊 public void func() {

CDN快取伺服器負載均衡叢集《CDN技術

1. 集群系統 1.1 集群系統分類 伺服器叢集的分類,可以分為三種分別是計算叢集、負載均衡叢集、高可用叢集,下面分析對計算叢集、負載均衡叢集和高可用叢集做以詳細講解。 根據用途的不同,我們把伺服器叢集分為如下幾類。 (1)計算叢集 伺服器計算叢集通常被用於承載

順序表的插入操作原理及實現(C語言)

順序表中存放資料的特點和陣列這種資料型別完全吻合,所以順序表的實現使用的是陣列。換句話說,順序表中插入元素問題也就等同於討論如何向陣列中插入資料。 因此,順序表中插入資料元素,無非三種情況: 在表頭插入; 在表的中間某個位置插入; 直接尾隨順序表,作為表的最後一個元素; 無論在順序表的什麼位置插

Java8新特性,介面中的靜態方法和預設方法

在此之前可以先看一下這個大佬寫的文章,裡面關於Java 8介面中的靜態方法和預設方法的新特性解釋的蠻好的 在這裡補充幾點其他需要注意的,也可能是你一直疑惑的(我之前就困惑了好久)~ 介面中的靜態方法

佇列實現棧,個佇列實現一個棧方法(含實現程式碼)

本節介紹一下如何用兩個佇列實現棧。 棧的主要操作就是入棧和出棧,其特點就是後進先出。我們先將兩個佇列分別定義為 queue1 與 queue2。 方案 1 入棧和出棧,都在 queue1 中完成,而 queue2 作為中轉空間。 入棧:直接入 queue1 即可。 出棧:把 queue1 中除最後一

判斷單鏈表是否存在環,判斷個連結串列是否相交問題

有一個單鏈表,其中可能有一個環,也就是某個節點的next指向的是連結串列中在它之前的節點,這樣在連結串列的尾部形成一環。問題:1、如何判斷一個連結串列是不是這類連結串列?2、如果連結串列為存在環,如何找到環的入口點?解答:一、判斷連結串列是否存在環,辦法為:設定兩個指標(fast, slow),初始值都指向頭

判斷個矩形是否相交的原理

bool Rect::intersectsRect(const Rect& rect) const {     return !(     getMaxX() < rect.getMinX() ||              rect.getMaxX() &l

STM32利用SPI讀SD卡的程式

SD卡的讀寫驅動程式是運用FATFS的基礎,學了FATFS就可以在SD卡上建立資料夾及檔案了。我們先從main檔案瞭解一下程式的執行流程int main(void) { u16 i; USART1_Config(); for(i=0;i<1536;i++) send_data[

(read&write)視訊(video) 及 程式碼

讀取(read&write)視訊(video) 詳解 及 程式碼本文地址: http://blog.csdn.net/caroline_wendy/article/details/1708439

解析用PHP讀音訊檔案資訊的(支援WMA和MP3)

<?php // AudioExif.class.php // 用PHP進行音訊檔案頭部資訊的讀取與寫入 // 目前只支援 WMA 和 MP3 兩種格式, 只支援常用的幾個頭部資訊 // // 寫入資訊支援: Title(名稱), Artist(藝術家), Copyright(版權), Descri

tcp三握手四揮手(及原因)

TCP(Transmission Control Protocol,傳輸控制協議)是 面向連線的協議,也就是說在收發資料之前,必須先和對方建立連線, 一個TCP連線必須要經過三次“對話”才能建立起來,其中的過程非常複雜,只簡單的 描述下這三次對話的簡單過程:主機A向主機B發