RDBMS是咱們常見的一些存儲數據的倉庫,不管是作前端仍是後端,都會接觸到。前端
咱們常見的數據處理,都是經過sql來和數據庫作交互的,所以形成了許多人對數據庫認知比較模糊,底層的架構也不是很清晰,從本週開始,咱們介紹些數據庫的基礎知識,來了解數據庫引擎是如何工做的,以及如何設計更好的索引的方法論,歡迎一塊兒探討。mysql
咱們以mysql的架構爲例,進行說明。sql
最上層用於鏈接、線程處理;第二層中包含了大多數 的核心服務,包括了對 SQL 的解析、分析、優化和緩存等功能,存儲過程、觸發器和視圖都是在這裏實現的;而第三層就是 真正負責數據的存儲和提取的存儲引擎,例如:InnoDB、MyISAM等,文中對存儲引擎的介紹都是對 InnoDB 實現的分析。數據庫
在整個數據庫體系結構中,咱們可使用不一樣的存儲引擎來存儲數據,而絕大多數存儲引擎都以二進制的形式存儲數據。後端
在 InnoDB 存儲引擎中,全部的數據都被邏輯地存放在表空間中,表空間(tablespace)是存儲引擎中最高的存儲邏輯單位,在表空間的下面又包括段(segment)、區(extent)、頁(page):緩存
同一個數據庫實例的全部表空間都有相同的頁大小;默認狀況下,表空間中的頁大小都爲 16KB,固然也能夠經過改變 innodb_page_size 選項對默認大小進行修改,須要注意的是不一樣的頁大小最終也會致使區大小的不一樣:服務器
從圖中能夠看出,在 InnoDB 存儲引擎中,一個區的大小最小爲 1MB,頁的數量最少爲 64 個。架構
在咱們經常使用的sql理解中,數據是以行的形式讀取出來的,其實否則,經過上述的結構,咱們能夠了解到,單次從磁盤讀取單位是頁,而不是行,也就是說,你即使只讀取一行記錄,從磁盤中也是會讀取一頁的,固然了單頁讀取代價也是蠻高的,通常都會進行預讀,這些後續再說。優化
關係型數據庫管理系統最重要的一個目標就是,確保表或者索引中的數據是隨時能夠用的。那麼爲了儘量的實現這個目標,會使用內存中的緩衝池來最小化磁盤活動。spa
每個緩衝池都足夠大,大到能夠存放許多頁,多是成千上萬的頁。
緩衝池管理器將盡力確保常用的數據被保存於池中,以免一些沒必要要的磁盤讀。若是一個索引或者表頁在緩衝池中被找到,那麼將會處理很快。
若是在緩衝池中,沒有找到數據,會從磁盤服務器的緩衝區裏面去讀取。
磁盤服務器的緩衝區,如同數據庫的緩衝池讀取同樣,磁盤服務器試圖將頻繁使用的數據保留在內存中,以下降高昂的磁盤讀取成本。這個讀取成本大概會在1ms左右。
若是磁盤服務器的緩衝池中依然沒有找到數據,此時就必需要從磁盤讀取了,此時讀取又分區隨機讀取和順序讀取。
咱們必須記住一個頁包含了多條記錄,咱們可能須要該頁上的全部行,也多是其中一部分,或者是一行,但所花費的成本都是相同的,讀取一個頁,須要一次隨機I/O,大約須要10ms的時間。
時間組成:
咱們能夠看到,一次隨機IO須要耗時的時間仍是好久的,10ms對計算機來講是一個很長的時間節點了。
若是咱們須要將多個頁讀取到緩衝池中,並按順序處理它們,此時讀取的速度回變的很快,具體的原理,在B樹索引中也有過介紹,此時讀取每一個頁面(4kb)所花費的時間大概爲0.1ms左右,這個時間消耗對隨機IO有很大的優點。
如下幾種狀況,會對數據進行順序讀取。
全表掃描
全索引掃描
索引片掃描
經過聚蔟索引掃描錶行
順序讀取有兩個重要的優點:
- 同時讀取多個頁意味着平均讀取每一個頁的時間將會減小。在當前磁盤服務器條件下,對於4kb大小的頁而言,這一值可能會低於0.1ms(40MB/s)
- 因爲數據庫引擎知道須要讀取哪些頁,全部能夠在頁被真正請求以前就提早將其讀取進來,咱們稱爲預讀。
數據庫中的 B+ 樹索引能夠分爲彙集索引(clustered index)和輔助索引(secondary index),它們之間的最大區別就是,彙集索引中存放着一條行記錄的所有信息,而輔助索引中只包含索引列和一個用於查找對應行記錄或者主鍵記錄的指針。
關於索引的B+樹結構,網上有不少文章進行分析了,咱們就不在一一介紹。
引用:
https://draveness.me/mysql-innodb
-----------------------------------------------------------------------------
想看更多有趣原創的技術文章,掃描關注公衆號。
關注我的成長和遊戲研發,推進國內遊戲社區的成長與進步。