SlideShare a Scribd company logo
資料庫索引數據結構及主鍵設計 (B+Tree)
Database index data structure and primary key design (part1)
2016
Ant
yftzeng@gmail.com
2016
2/129
自我介紹
♪ Muzik Online (www.muzikair.com) 總工程師。
♪ Paganini+ (http://www.paganiniplus.com/) 技術長。
♪ BELP (fb.com/belp.general) 共同創辦人。
♪ CHROOT (www.chroot.org) 成員。
♪ 講師經驗
PHPConf, Modern Web Taiwan, MOPCON, WebConf, COSCUP, JSDC Taiwan,
DrupalCamp Taiwan, OSDC, HITCON, ...
♪ 略懂智慧財產權、資訊安全及軟體程式設計。
♪ 『略懂諸葛』。
♪ 沉浸於『人性』、『法律』與『科技』的三角關係中。
2016
3/129
問題 1: UUID ?
Q: 資料庫 Primary key 使用 UUID 比較快?
Serial/Auto-Increment
1
2
3
4
5
...
UUID
3a5e439b-eeb4-4074-8b23-51c2cdd35421
1bb19e6b-9c0c-475e-a7b3-f01a6b4cd496
af4c8b80-4bf5-4bf3-a4e3-a71bed920f10
e62acb5b-a393-4707-9aa5-90f79352eb4b
2e199d72-4e49-4ace-a504-419da63878f5
...
4/129
2016
問題 1: UUID ?
Q: 資料庫 Primary key 使用 UUID 比較快?
偽命題
2016
5/129
問題 1 ( 修正 ): MySQL UUID ?
Q: MySQL 的 Primary key 使用 UUID 比較快?
Serial/Auto-Increment
1
2
3
4
5
...
UUID
3a5e439b-eeb4-4074-8b23-51c2cdd35421
1bb19e6b-9c0c-475e-a7b3-f01a6b4cd496
af4c8b80-4bf5-4bf3-a4e3-a71bed920f10
e62acb5b-a393-4707-9aa5-90f79352eb4b
2e199d72-4e49-4ace-a504-419da63878f5
...
6/129
2016
問題 1 ( 修正 ): MySQL UUID ?
Q: MySQL 的 Primary key 使用 UUID 比較快?
偽命題
7/129
2016
問題 1 ( 修正 ): MySQL UUID ?
UUID 目前公定有五種版本:
➀ Version 1 (MAC address & date-time)
➁ Version 2 (DCE Security)
➂ Version 3 (MD5 hash & namespace)
➃ Version 4 (Random)
➄ Version 5 (SHA-1 hash & namespace)
Ref: https://en.wikipedia.org/wiki/Universally_unique_identifier
8/129
2016
問題 1 ( 修正 ): MySQL UUID ?
UUID 目前公定有五種版本:
➀ Version 1 (MAC address & date-time)
➁ Version 2 (DCE Security)
➂ Version 3 (MD5 hash & namespace)
➃ Version 4 (Random)
➄ Version 5 (SHA-1 hash & namespace)
Ref: https://en.wikipedia.org/wiki/Universally_unique_identifier
Version 2 未在 UUID 規格中定義,少見
9/129
2016
問題 1 ( 修正 ): MySQL UUID ?
UUID 目前公定有五種版本:
➀ Version 1 (MAC address & date-time)
➁ Version 2 (DCE Security)
➂ Version 3 (MD5 hash & namespace)
➃ Version 4 (Random)
➄ Version 5 (SHA-1 hash & namespace)
Ref: https://en.wikipedia.org/wiki/Universally_unique_identifier
10/129
2016
問題 1 ( 修正 ): MySQL UUID ?
UUID 類循序式 ( 通常後序產生的值 > 先前產生的值 ) :
➀ Version 1 (MAC address & date-time)
UUID 亂序式 ( 值的大小沒有前後關係 ) :
➂ Version 3 (MD5 hash & namespace)
➃ Version 4 (Random)
➄ Version 5 (SHA-1 hash & namespace)
11/129
2016
問題 1 ( 修正 ): MySQL UUID ?
UUIDv1 的範例:
2190718a-c7a3-61e2-aa34-024281ed9db5
2191f33e-c7a3-61e2-9b92-024281ed9db5
2192cc0a-c7a3-61e2-be4c-024281ed9db5
21939950-c7a3-61e2-9aad-024281ed9db5
21945ff2-c7a3-61e2-90fc-024281ed9db5
219525f4-c7a3-61e2-99df-024281ed9db5
Time
12/129
2016
問題 1 ( 修正 ): MySQL UUID ?
UUIDv4 的範例:
3a5e439b-eeb4-4074-8b23-51c2cdd35421
1bb19e6b-9c0c-475e-a7b3-f01a6b4cd496
af4c8b80-4bf5-4bf3-a4e3-a71bed920f10
e62acb5b-a393-4707-9aa5-90f79352eb4b
2e199d72-4e49-4ace-a504-419da63878f5
8cf2e49f-8ae9-43f2-a84d-78cb323114a3
Time
13/129
2016
問題 1 ( 修正 ): MySQL UUID ?
結論: UUID 可以是類循序式,也可以是亂序式。
但《循序式》與《亂序式》的重要性為何?
14/129
2016
問題 1 ( 修正 ): MySQL UUID ?
Ref: https://www.percona.com/blog/2014/12/19/store-uuid-optimized-way/
15/129
2016
問題 1 ( 修正 ): MySQL UUID ?
延伸 : GUID 與 UUID 的差異?
16/129
2016
問題 1 ( 修正 ): MySQL UUID ?
GUID 是 Microsoft 用詞,指的其實類似於 UUID ,
但實作方式不一樣。
Microsoft 對於 GUID 的實作至少有兩種:
➀ 基於 UuidCreate 的 NEWID(SQL) ;
➁ 基於 UuidCreateSequential 的 NEWSEQUENTIALID(SQL) 。
其中 NEWID 是亂序式,而 NEWSEQUENTIALID 是循序式。
2016
17/129
索引數據結構
18/129
2016
索引數據結構 : 無索引
目的:尋找【欄位一為 5 的資料】
操作: 5 , O(n)
缺點:總是需要全表掃描
資料表:
1 user1 pass1
2 user2 pass2
3 user3 pass3
4 user4 pass4
5 user5 pass5
19/129
2016
索引數據結構 : B-tree 索引
B-tree = Balanced tree (not Binary tree)
20/129
2016
索引數據結構 : B-tree 索引
目的:尋找【欄位一為 5 的資料】
操作: 4 , O(logbn)
缺點:全表掃描需要遍歷樹
資料表:
1 user1 pass1
2 user2 pass2
3 user3 pass3
4 user4 pass4
5 user5 pass5
8
3 6
1 2 4 5 7
21/129
2016
索引數據結構 : B+tree 索引
目的:尋找【欄位一為 5 的資料】
優點:全表掃描不需遍歷樹
資料表:
1 user1 pass1
2 user2 pass2
3 user3 pass3
4 user4 pass4
5 user5 pass5
13
4 7
1 2 3 4 5 6 7
22/129
2016
索引數據結構 : B+tree 索引
目的:尋找【欄位一為 5 的資料】
操作: 4 , O(logbn)
優點:全表掃描不需遍歷樹
資料表:
1 user1 pass1
2 user2 pass2
3 user3 pass3
4 user4 pass4
5 user5 pass5
13
4 7
1 2 3 4 5 6 7
13
b
2016
23/129
問題 2: B+tree
Q: 哪些資料庫索引數據結構支援 B+tree ?
MySQL
Oracle
Microsoft SQL Server
PostgreSQL
MongoDB
CouchDB
LevelDB
RocksDB
HBase
Cassandra
Riak
NessDB
BoltDB
TokuDB
Aerospike
Couchbase
24/129
2016
問題 2: B+tree
Q: 哪些資料庫索引數據結構支援 B+tree ?
MySQL
Oracle
Microsoft SQL Server
PostgreSQL
MongoDB
CouchDB
LevelDB
RocksDB
HBase
Cassandra
Riak
NessDB
BoltDB
TokuDB
Aerospike
Couchbase
2016
25/129
索引頁分裂
26/129
2016
索引頁分裂
觸發:頁剩餘空間 - 保留空間 < 新增資料
問題:頁分裂時會 Latch( 小鎖 )
page
page page
latch
page
27/129
2016
索引頁分裂 : 循序式新增資料
操作:新增 25( 假設頁只能存三筆資料 )
9 18
21 24
19 20 21 22 23 24
25
p1
p10
p12p11
9 18
21 24 25
19 20 21 22 23 24
p1
p10
p12p11
25
p13
latch
latch
hotspot
28/129
2016
索引頁分裂 : 亂序式新增資料
操作:新增 5( 假設頁只能存三筆資料 )
20
6 12
2 4 6 8 10 12
5
20
4 6 12
2 4 5 6 8 10 12
p1 p1
p2 p2
p4p3 p3 p4p5
latch
fragmentation fragmentation
29/129
2016
索引頁分裂 : 亂序式新增資料
Ref: http://blogs.catapultsystems.com/rnewkirk/archive/2013/05/14/sql-fragmentation-explained/
30/129
2016
索引頁分裂 : I/O 與 Page Size
資料庫 I/O 以 Page 為單位。
儲存引擎的 Page Size :
➊ PostgreSQL 8KB
➋ MySQL/InnoDB 16KB(default)
➌ MongoDB/MMAPv1 dynamic (powered by 2)
➍ MongoDB/WiredTiger 32KB(default)
➎ Percona/TokuDB 64KB(default)
31/129
2016
索引頁分裂 : 循序式新增 I/O
9 18
21 24 25
19 20 21 22 23 24
25
p1
p10
p12p11
25
p13
latch
latch
Block N+1 Block N+2 Block N+3 p11 p12 p13p10
I/O
hotspot?
hotspot
32/129
2016
索引頁分裂 : 循序式新增 I/O
如果 Page Size 比較大?
Block N+1 Block N+2 Block N+3 p11 p12 p13p10
I/O
Block N+1 Block N+2 p13p12p11p10
I/OI/O
33/129
2016
索引頁分裂 : 亂序式新增 I/O
Block N+3 Block N+4
I/O
p2 p3 p4p1 # # #p5
20
6 12
2 4 6 8 10 12
20
4 6 12
2 4 5 6 8 10 12
p1 p1
p2 p2
p4p3 p3 p4p5
latch
I/O
5
34/129
2016
索引頁分裂 : 亂序式新增 I/O
如果 Page Size 比較大?
Block N+4p4p3p2p1
I/OI/O
Block N+3 Block N+4
I/O
p2 p3 p4p1 # # #p5
I/O
#p5
I/O
2016
35/129
索引子頁結構
36/129
2016
索引子頁結構 : Non-clustered index
以 B+tree 為例
特色:子頁不包括資料本身 ( 指針指向資料 )
補充:對應的資料表稱 Heap table
資料表:循序式
1 user1 pass1
2 user2 pass2
3 user3 pass3
4 user4 pass4
5 user5 pass5
13
4 7
1 2 3 4 5 6 7
37/129
2016
索引子頁結構 : Non-clustered index
如果不是《循序式》而是《亂序式》。
資料表:亂序式
1 user1 pass1
4 user4 pass4
5 user5 pass5
2 user2 pass2
3 user3 pass3
13
4 7
1 2 3 4 5 6 7
38/129
2016
索引子頁結構 : Clustered index
以 B+tree 為例
特色:子頁包括資料本身 ( 不需指針指向資料 )
補充:對應的資料表稱 Index Organized Table(IOT)
資料表:循序式與亂序式都一樣
13
4 7
1 2 3 4 5 6 7
1 user1 pass1
2 user2 pass2
3 user3 pass3
4 user4 pass4
5 user5 pass5
39/129
2016
Non-clustered index(Heap table)
循序式
➀ 有索引指針指向資料的額外開銷。
➁ Hotspot 發生在樹最右下的頁,但循序寫及合併寫機率高。
➂ Range scan 讀取時開銷大。
亂序式
➀ 有索引指針指向資料的額外開銷。
➁ Range scan 讀取時開銷可能比循序式更大。
➂ 大量新增資料,幾乎是隨機寫,也難以合併寫。
索引子頁結構 : Non-clustered index
40/129
2016
索引子頁結構 : Clustered index
Clustered index(IOT)
循序式
➀ 資料佔頁空間,頁存放的資料量少,頁分裂頻繁。
➁ 搜尋至頁索引時,因包括資料本身,無額外指針開銷。
➂ Hotspot 發生在樹最右下的頁,但循序寫及合併寫機率高。
亂序式
➀ 資料佔頁空間,頁存放的資料量少,頁分裂頻繁。
➁ 搜尋至頁索引時,因包括資料本身,無額外指針開銷。
➂ 為了維持循序,發生大量的頁分裂。
41/129
2016
索引子頁結構 : Clustered index
Q: 循序式 / 亂序式 vs. I/O Scheduler vs. Filesystem vs. HDD / Flash / Fusion IO ?
循序式
亂序式
CFQ
Deadline
NOOP
HDD
Flash
Fusion IO
Ext4
XFS
ZFS
BtrFS
2016
42/129
Range scan
43/129
2016
Range scan
>, <, >=, <=
BETWEEN, IN
GROUP BY with max, min, count
44/129
2016
Range scan: Heap table w/ 循序式
SELECT * FROM x WHERE y BETWEEN 1 AND 7;
1 user1 pass1
2 user2 pass2
3 user3 pass3
4 user4 pass4
5 user5 pass5
6 user6 pass6
7 user7 pass7
13
4 7
1 2 3 4 5 6 7
Block N+3 ...
p1
p3
I/O
p2
p1 p2 p3 p4
I/O
Block N+M
45/129
2016
Range scan: Heap table w/ 亂序式
SELECT * FROM x WHERE y BETWEEN 1 AND 7;
1 user1 pass1
4 user4 pass4
5 user5 pass5
2 user2 pass2
3 user3 pass3
7 user7 pass7
6 user6 pass6
13
4 7
1 2 3 4 5 6 7
I/O
p5 p7 p3 p6
I/O I/OI/O
p1 # p2 p4...
p4
p7
p5
p1
p3
p2
p6
46/129
2016
Range scan: Heap table w/ 亂序式
I/O
p5 p7 p3 p6
I/O I/OI/O
p1 # p2 p4...
Ref: http://etutorials.org/SQL/Postgresql/Part+I+General+PostgreSQL+Use/Chapter+4.+Performance/Gathering+Performance+Information/
47/129
2016
Range scan: IOT w/ 循序式 & 亂序式
SELECT * FROM x WHERE y BETWEEN 1 AND 7;
13
4 7
1 2 3 4 5 6 7
1 user1 pass1
2 user2 pass2
3 user3 pass3
4 user4 pass4
5 user5 pass5
6 user6 pass6
7 user7 pass7
p1
p3
p2
Block N+3 ...
I/O
p1 p2 p3 p4
I/O
Block N+M
2016
48/129
問題 3
Q: 哪些資料庫支援 Heap table ?哪些支援 IOT ?
MySQL
Oracle
Microsoft SQL Server
PostgreSQL
MongoDB
CouchDB
49/129
2016
問題 3
Heap table IOT
MySQL/MyISAM O X
MySQL/InnoDB X O
Oracle O O
Microsoft SQL Server O O
PostgreSQL O X
MongoDB/MMAPv1 O X
MongoDB/WiredTiger O X
CouchDB X O
50/129
2016
問題 3
Q: 選什麼資料庫比較好?
是個偽命題,需視你的場景而定。
2016
51/129
特別篇 1: MySQL 生態系
Q: MySQL 生態系, MySQL / Percona / MariaDB /
WebScaleSQL 該怎麼選擇?
52/129
2016
特別篇 1: MySQL 生態系
MySQL
➀ 官方,有 Oracle 技術支持及專利保護。
➁ 最新的 MySQL 5.7 擁有大量新特性。
➂ 商業因素預設不會接受其他分支的特性。
Percona
➀ drop-in compatible with (official) MySQL 。
➁ 針對 MySQL 額外新增許多特性。
➂ 額外支援 XtraDB / TokuDB 等引擎。
➃ 商業特性可接受其他所有分支的特性。
53/129
2016
特別篇 1: MySQL 生態系
MariaDB
➀ drop-in replacement for (official) MySQL 。
➁ MariaDB 10 基於 MySQL 5.6 ,但不相容 5.7 。
➂ 額外支援 XtraDB / TokuDB / Cassandra / CONNECT 等引擎。
➃ 至今仍沒有穩定的自我開發儲存引擎。
XtraDB / TokuDB 都屬 Percona 公司。
WebScaleSQL
➀ 基於 5.6 ,但可收納 5.7 特性。
➁ 專針對特大型 Web 公司需求而生,小心駕馭。
54/129
2016
特別篇 1: MySQL 生態系
MySQL 5.7 解決了 index→lock contention 問題。
2016
55/129
特別篇 2: PostgreSQL
PostgreSQL 是 Object-relational database
56/129
2016
特別篇 2: PostgreSQL (Fusion IO)
Fusion IO 可大幅排除 IO Bottlenect 的可能性。
57/129
2016
特別篇 2: PostgreSQL (Fusion IO)
Fusion IO 只特別支援 Oracle / MySQL / Percona / MariaDB ?
Ref: https://www.sandisk.com/business/datacenter/resources/overviews/accelerate-mysql-open-source-databases
58/129
2016
特別篇 2: PostgreSQL (Fusion IO)
Fusion IO 可讓 MySQL 免除 double write 。
Ref: https://www.sandisk.com/business/datacenter/resources/overviews/accelerate-mysql-open-source-databases
59/129
2016
特別篇 2: PostgreSQL (Fragmentation)
PostgreSQL(HOT) 天性無法避免 fragmentation 。
Ref: http://etutorials.org/SQL/Postgresql/Part+I+General+PostgreSQL+Use/Chapter+4.+Performance/Gathering+Performance+Information/
60/129
2016
特別篇 2: PostgreSQL (Index Bloat)
PostgreSQL(non HOT updates) 天性無法避免 index bloat 。
Ref: PostgreSQL 9.0 High Performance [PACKT] (2010) (p171)
61/129
2016
特別篇 2: PostgreSQL (Index Bloat)
62/129
2016
特別篇 2: PostgreSQL (Index Bloat)
63/129
2016
特別篇 2: PostgreSQL (Merge IO)
PostgreSQL 沒有類似 MySQL 的 Change Buffer 。
Ref: http://www.slideshare.net/morgo/inno-db-presentation (p9)
64/129
2016
特別篇 2: PostgreSQL (Merge IO)
MySQL Insert Buffering( 現在改名 Change Buffer) :
1. Reducing the number of disk i/o operations by merging i/o
requests to the same block.
2. Some random i/o operations can be sequential.
Ref: http://www.percona.com/files/presentations/percona-live/london-2011/PLUK2011-linux-and-hw-optimizations-for-mysql.pdf (p17)
65/129
2016
特別篇 2: PostgreSQL (Merge IO)
66/129
2016
特別篇 2: PostgreSQL ( 儲存引擎 )
Microsoft SQL Server / Oracle 支援 Heap table 及 IOT ,
可依各資料表的特性分別採用。
MySQL 及 MongoDB 支援可抽換儲存引擎,也可依資料表的
特性分別採用。
但 PostgreSQL 只有一個儲存引擎,也只支援 Heap table 。
2016
67/129
特別篇 3: MongoDB
68/129
2016
特別篇 3: MongoDB
Ref: http://itindex.net/detail/43573
69/129
2016
特別篇 3: MongoDB
Ref: http://sql-vs-nosql.blogspot.tw/2013/11/indexes-comparison-mongodb-vs-mssqlserver.html
70/129
2016
特別篇 3: MongoDB
Ref: http://learnmongodbthehardway.com/schema/chapter4/
B+Tree / Heap Table
71/129
2016
特別篇 3: MongoDB
Ref: Indexing and Performance Tuning (2015-11-03).pdf (p39)
72/129
2016
特別篇 3: MongoDB
Index
➀ ”統一命名為 _id”
➁ ”新增若未指定 _id” 值,會使用 ObjectId
➂ ObjectId 為 12-byte BSON 型態
➊ 4-byte 為 UNIX 紀元時間
➋ 3-byte 為機器識別碼
➌ 2-byte 為 Process ID
➍ 3-byte 為隨機值
Ref: https://docs.mongodb.org/manual/reference/object-id/
“_id” : ObjectId(“563479cc8a8a4246bd27d784”)
“_id” : ObjectId(“563479d48a8a4246bd27d785”)
“_id” : ObjectId(“563479df8a8a4246bd27d786”)
循序式 UUID
73/129
2016
特別篇 3: MongoDB
MMAPv1 儲存引擎
➀ Memory-mapped files
Ref: http://learnmongodbthehardway.com/schema/chapter3/
74/129
2016
特別篇 3: MongoDB
MMAPv1 儲存引擎
➀ Memory-mapped files
➁ Padding
Ref: http://learnmongodbthehardway.com/schema/chapter3/
75/129
2016
特別篇 3: MongoDB
MMAPv1 儲存引擎
➀ Memory-mapped files
➁ Padding
➂ Fragmentation
Ref: http://learnmongodbthehardway.com/schema/chapter3/
76/129
2016
特別篇 3: MongoDB
MMAPv1 儲存引擎
➀ Memory-mapped files
➁ Padding
➂ Fragmentation
➃ Collection-level locking (WiredTiger 為 Document-level)
Ref: http://sql-vs-nosql.blogspot.tw/2013/11/indexes-comparison-mongodb-vs-mssqlserver.html
77/129
2016
特別篇 3: MongoDB
MMAPv1 儲存引擎
➀ Memory-mapped files
➁ Padding
➂ Fragmentation
➃ Collection-level locking (WiredTiger 為 Document-level)
➄ MongoDB 3.2 以前為預設引擎, 3.2 後換 WiredTiger
Ref: https://docs.mongodb.org/manual/core/wiredtiger/
78/129
2016
特別篇 3: MongoDB
MMAPv1 的 Fragmentation 問題
Ref: http://www.slideshare.net/mongodb/7-managing-a-maturing-mongo-db-ecosystem-charity-majors (p35)
左邊是大量 Fragmentation ;
右邊是修復 Fragmentation 後
79/129
2016
特別篇 3: MongoDB
MMAPv1 的 Fragmentation 問題
動作:連續新增 5 個 Document
Collection :
{Document 1}
{Document 2}
{Document 3}
{Document 4}
{Document 5}
80/129
2016
特別篇 3: MongoDB
MMAPv1 的 Fragmentation 問題
動作:更新 Document 3
情況一:新的 Document 3 大小 <= 原先大小
Collection :
{Document 1}
{Document 2}
{Document 3}
{Document 4}
{Document 5}
{Document 1}
{Document 2}
{Document 3‘}
{Document 4}
{Document 5}
81/129
2016
特別篇 3: MongoDB
MMAPv1 的 Fragmentation 問題
動作:更新 Document 3
情況二:新的 Document 3 大小 > 原先大小
Collection :
{Document 1}
{Document 2}
{Document 3}
{Document 4}
{Document 5}
{Document 1}
{Document 2}
Free
{Document 4}
{Document 5}
{Document 3‘}
82/129
2016
特別篇 3: MongoDB
MMAPv1 的 Fragmentation 問題
動作:新增 Document 6
Collection :
{Document 1}
{Document 2}
Free
{Document 4}
{Document 5}
{Document 3‘}
83/129
2016
特別篇 3: MongoDB
MMAPv1 的 Fragmentation 問題
動作:新增 Document 6
情況一: Document 6 大小 <= 原先 Document 3 (Free) 大小
Collection :
{Document 1}
{Document 2}
{Document 6}
{Document 4}
{Document 5}
{Document 3‘}
{Document 1}
{Document 2}
Free
{Document 4}
{Document 5}
{Document 3‘}
84/129
2016
特別篇 3: MongoDB
MMAPv1 的 Fragmentation 問題
動作:新增 Document 6
情況二: Document 6 大小 > 原先 Document 3 (Free) 大小
Collection :
{Document 1}
{Document 2}
Free
{Document 4}
{Document 5}
{Document 3‘}
{Document 6}
{Document 1}
{Document 2}
Free
{Document 4}
{Document 5}
{Document 3‘}
85/129
2016
特別篇 3: MongoDB
特色與改善
➀ Sharding/Replica 較容易
( 但 Sharding/Replica 只有 Primary 可寫 )
➁ Dynamic schema ( 不是 Schemaless)
➂ 儲存引擎可抽換
➊ MMAPv1
➋ WiredTiger
➌ inMemory
➍ Devnull
➎ (RocksDB)
86/129
2016
特別篇 3: MongoDB
特色與改善
➃ 寫入的 Locking level 改善
2.2 版前, Process-level lock ,一個 Mongod 實例一個鎖
2.8 版前, Database-level lock ,一個 DB 一個鎖
2.8 版之後, WiredTiger 提供 Document-level lock
3.0 版之後, MMAPv1 改為 Collection-level lock
Ref: http://sql-vs-nosql.blogspot.tw/2013/11/indexes-comparison-mongodb-vs-mssqlserver.html
87/129
2016
特別篇 3: MongoDB
特色與改善
➄ 支援 MapReduce
2.4 版前,使用 SpiderMonkey ,是 single threaded
2.4 版之後,改用 V8 engine ,改善問題
➅ Single thread model ,大多時候只用到一顆 CPU
(WiredTiger 已支援 Multiple CPUs)
2016
88/129
特別篇 4: RDMBS or NoSQL ?
Q: 使用 RDBMS 還是 NoSQL ?
89/129
2016
特別篇 4: RDMBS or NoSQL ?
Q: 使用 RDBMS 還是 NoSQL ?
是個偽命題,需視你的場景而定。
90/129
2016
特別篇 4: RDMBS or NoSQL ?
不過 RDBMS 及 NoSQL 的分界會愈來愈小。
過去的一些 RDBMS 已開始支援 NoSQL 特性,
Microsoft SQL Server / Oracle / MySQL /
PostgreSQL 都確定支援 JSON(B) 操作。
Percona / MariaDB 可抽換為 TokuDB 引擎,
MariaDB 更可抽換為 Cassandra 引擎。
NoSQL 等也開始支援強一致性。
91/129
2016
特別篇 4: RDMBS or NoSQL ?
不過 RDBMS 及 NoSQL 的分界會愈來愈小。
過去的一些 RDBMS 已開始支援 NoSQL 特性,
Microsoft SQL Server / Oracle / MySQL /
PostgreSQL 都確定支援 JSON(B) 操作。
Percona / MariaDB 可抽換為 TokuDB 引擎,
MariaDB 更可抽換為 Cassandra 引擎。
NoSQL 等也開始支援強一致性。
NewSQL
2016
92/129
特別篇 5: 黑暗執行緒案例
Q: 試著分析黑暗執行緒的文章。
【 GUID Primary Key 資料庫避雷守則】
Ref: http://blog.darkthread.net/post-2016-01-29-guid-as-pk-on-db.aspx
93/129
2016
特別篇 5: 黑暗執行緒案例
以架構設計而言,我更傾向讓應用伺服器決定 GUID / UUID 的值,
理由有幾個。
➊ 未來若需要異質資料庫彼此交換資料, GUID / UUID 的衝突會
更小。例如若 SQL Server 要與 MySQL 交換, MySQL 沒有 NEWID /
NEWSEQUENTIALID 函式,所以勢必要用另一種算法來計算 UUID ,
而算法不同就可能破壞原本 GUID / UUID 不會重複的機率。
➋ 資料庫在整體架構中,是最難以擴展的,所以我傾向讓資料庫做愈少
事情愈好。 GUID / UUID 是需要計算的,即使開銷很低,但若量大還是
很可觀,所以我還是會把計算的成本移至應用伺服器處理。
94/129
2016
特別篇 5: 黑暗執行緒案例
➌ 應用伺服器脫離 SQL Server 後,就無法使用 NEWID 及
NEWSEQUENTIALID ,所以需要找 UUID 產生器。 UUID 產生器有
幾種版本, UUIDv1 是類循序性, UUIDv4 是亂序性,可以依業務
場景選擇所需。而且 UUIDv1 的類循序性不像 NEWSEQUENTIALID
這麼容易猜測。
➍ 大規模架構中,全循序性 Insert 不一定是好事。想像一下,順序性
Insert 時,所有資料會集中在樹最右下角的 Leaf Page Insert ,當
Page 滿後,就必須 Page Split ,此時就一定有 Latch 。 Latch 會減
緩 Insert 的速度。再加上實際在硬碟寫入的 Block 也會變成是 Hotspot 。
所以有時候,適當非循序性所造成的 Fragmentation 有時反而會更快。
最後有可能會變成全順序性 Insert 不一定最快,全隨機性 Insert 也不
一定最好,反而中間找平衡才是最佳的。而這時把 UUID 的計算移到應
用伺服器,剛好可以滿足這點。
95/129
2016
特別篇 5: 黑暗執行緒案例
黑暗執行緒提供的表設計建議
96/129
2016
特別篇 5: 黑暗執行緒案例
黑暗執行緒提供的表設計建議
4c.. cb.. ee..
07.. 3b.. 4c.. 5b.. 9e.. cb.. ee..
Clustered Index ( 循序式 )
Nonclustered Index ( 亂序式 )
3 6 7
1 2 3 4 5 6 7
97/129
2016
98/129
2016
特別篇 5: 黑暗執行緒案例
假設已有五筆資料
5b.. cb..
07.. 3b.. 5b.. 9e.. cb..
3 5
1 2 3 4 5
[SeqNo] [FlowId] ...
1 07.. ...
2 9e.. ...
3 3b.. ...
4 cb.. ...
5 5b.. ...
1 3 5 2 4
Nonclustered Index ( 亂序式 )
Clustered Index ( 循序式 )
99/129
2016
特別篇 5: 黑暗執行緒案例
尋找【 WHERE FlowId = “5b..” 】
IO 次數: 0
5b.. cb..
07.. 3b.. 5b.. 9e.. cb..
3 5
1 2 3 4 5
[SeqNo] [FlowId] ...
1 07.. ...
2 9e.. ...
3 3b.. ...
4 cb.. ...
5 5b.. ...
1 3 5 2 4
Nonclustered Index ( 亂序式 )
Clustered Index ( 循序式 )
100/129
2016
特別篇 5: 黑暗執行緒案例
尋找【 WHERE FlowId = “5b..” 】
IO 次數: 1
5b.. cb..
07.. 3b.. 5b.. 9e.. cb..
3 5
1 2 3 4 5
[SeqNo] [FlowId] ...
1 07.. ...
2 9e.. ...
3 3b.. ...
4 cb.. ...
5 5b.. ...
1 3 5 2 4
Nonclustered Index ( 亂序式 )
Clustered Index ( 循序式 )
101/129
2016
特別篇 5: 黑暗執行緒案例
尋找【 WHERE FlowId = “5b..” 】
IO 次數: 2
5b.. cb..
07.. 3b.. 5b.. 9e.. cb..
3 5
1 2 3 4 5
[SeqNo] [FlowId] ...
1 07.. ...
2 9e.. ...
3 3b.. ...
4 cb.. ...
5 5b.. ...
1 3 5 2 4
Nonclustered Index ( 亂序式 )
Clustered Index ( 循序式 )
102/129
2016
特別篇 5: 黑暗執行緒案例
尋找【 WHERE FlowId = “5b..” 】
IO 次數: 3
5b.. cb..
07.. 3b.. 5b.. 9e.. cb..
3 5
1 2 3 4 5
[SeqNo] [FlowId] ...
1 07.. ...
2 9e.. ...
3 3b.. ...
4 cb.. ...
5 5b.. ...
1 3 5 2 4
Nonclustered Index ( 亂序式 )
Clustered Index ( 循序式 )
103/129
2016
特別篇 5: 黑暗執行緒案例
尋找【 WHERE FlowId = “5b..” 】
IO 次數: 4 ( 完成 )
5b.. cb..
07.. 3b.. 5b.. 9e.. cb..
3 5
1 2 3 4 5
[SeqNo] [FlowId] ...
1 07.. ...
2 9e.. ...
3 3b.. ...
4 cb.. ...
5 5b.. ...
1 3 5 2 4
Nonclustered Index ( 亂序式 )
Clustered Index ( 循序式 )
104/129
2016
特別篇 5: 黑暗執行緒案例
新增【 SeqNo: 6, FlowID: 4c.. 】
IO 次數: 0
5b.. cb..
07.. 3b.. 5b.. 9e.. cb..
3 5
1 2 3 4 5
[SeqNo] [FlowId] ...
1 07.. ...
2 9e.. ...
3 3b.. ...
4 cb.. ...
5 5b.. ...
6 4c.. ...
1 3 5 2 4
Nonclustered Index ( 亂序式 )
Clustered Index ( 循序式 )
105/129
2016
特別篇 5: 黑暗執行緒案例
新增【 SeqNo: 6, FlowID: 4c.. 】
IO 次數: 1
5b.. cb..
07.. 3b.. 5b.. 9e.. cb..
3 5
1 2 3 4 5
[SeqNo] [FlowId] ...
1 07.. ...
2 9e.. ...
3 3b.. ...
4 cb.. ...
5 5b.. ...
6 4c.. ...
1 3 5 2 4
Nonclustered Index ( 亂序式 )
Clustered Index ( 循序式 )
106/129
2016
特別篇 5: 黑暗執行緒案例
新增【 SeqNo: 6, FlowID: 4c.. 】
IO 次數: 2
5b.. cb..
07.. 3b.. 5b.. 9e.. cb..
3 5
1 2 3 4 5
[SeqNo] [FlowId] ...
1 07.. ...
2 9e.. ...
3 3b.. ...
4 cb.. ...
5 5b.. ...
6 4c.. ...
1 3 5 2 4
Nonclustered Index ( 亂序式 )
Clustered Index ( 循序式 )
107/129
2016
特別篇 5: 黑暗執行緒案例
新增【 SeqNo: 6, FlowID: 4c.. 】
IO 次數: 3+3
Page Split 次數: 1
3 5
1 2 3 4 5
[SeqNo] [FlowId] ...
1 07.. ...
2 9e.. ...
3 3b.. ...
4 cb.. ...
5 5b.. ...
6 4c.. ...
Nonclustered Index ( 亂序式 )
Clustered Index ( 循序式 )
07.. 3b.. 4c.. 5b..
1 3 6 5 42
3b.. 5b.. cb..
9e.. cb..
108/129
2016
特別篇 5: 黑暗執行緒案例
新增【 SeqNo: 6, FlowID: 4c.. 】
IO 次數: 3+3+1
Page Split 次數: 1
3 5
1 2 3 4 5
[SeqNo] [FlowId] ...
1 07.. ...
2 9e.. ...
3 3b.. ...
4 cb.. ...
5 5b.. ...
6 4c.. ...
Nonclustered Index ( 亂序式 )
Clustered Index ( 循序式 )
07.. 3b.. 4c.. 5b..
1 3 6 5 42
3b.. 5b.. cb..
9e.. cb..
109/129
2016
特別篇 5: 黑暗執行緒案例
新增【 SeqNo: 6, FlowID: 4c.. 】
IO 次數: 3+3+2
Page Split 次數: 1
3 5
1 2 3 4 5
[SeqNo] [FlowId] ...
1 07.. ...
2 9e.. ...
3 3b.. ...
4 cb.. ...
5 5b.. ...
6 4c.. ...
Nonclustered Index ( 亂序式 )
Clustered Index ( 循序式 )
07.. 3b.. 4c.. 5b..
1 3 6 5 42
3b.. 5b.. cb..
9e.. cb..
110/129
2016
特別篇 5: 黑暗執行緒案例
新增【 SeqNo: 6, FlowID: 4c.. 】
IO 次數: 3+3+3
Page Split 次數: 1
3 5
1 2 3 4 5 6
[SeqNo] [FlowId] ...
1 07.. ...
2 9e.. ...
3 3b.. ...
4 cb.. ...
5 5b.. ...
6 4c.. ...
Nonclustered Index ( 亂序式 )
Clustered Index ( 循序式 )
07.. 3b.. 4c.. 5b..
1 3 6 5 42
3b.. 5b.. cb..
9e.. cb..
111/129
2016
特別篇 5: 黑暗執行緒案例
新增【 SeqNo: 6, FlowID: 4c.. 】
IO 次數: 3+3+4=10 ( 完成 )
Page Split 次數: 1
07.. 3b.. 4c.. 5b..
3 6
1 2 3 4 5 6
[SeqNo] [FlowId] ...
1 07.. ...
2 9e.. ...
3 3b.. ...
4 cb.. ...
5 5b.. ...
6 4c.. ...
1 3 6 5 42
Nonclustered Index ( 亂序式 )
Clustered Index ( 循序式 )
3b.. 5b.. cb..
9e.. cb..
112/129
2016
特別篇 5: 黑暗執行緒案例
如果用一般亂序式 UUID
[FlowId] ... ...
07.. ... ...
9e.. ... ...
3b.. ... ...
cb.. ... ...
5b.. ... ...
5b.. cb..
07.. 3b.. 5b.. 9e.. cb..
Clustered Index ( 亂序式 )
113/129
2016
特別篇 5: 黑暗執行緒案例
尋找【 WHERE FlowId = “5b..” 】
IO 次數: 0
[FlowId] ... ...
07.. ... ...
9e.. ... ...
3b.. ... ...
cb.. ... ...
5b.. ... ...
5b.. cb..
07.. 3b.. 5b.. 9e.. cb..
Clustered Index ( 亂序式 )
114/129
2016
特別篇 5: 黑暗執行緒案例
尋找【 WHERE FlowId = “5b..” 】
IO 次數: 1
[FlowId] ... ...
07.. ... ...
9e.. ... ...
3b.. ... ...
cb.. ... ...
5b.. ... ...
5b.. cb..
07.. 3b.. 5b.. 9e.. cb..
Clustered Index ( 亂序式 )
115/129
2016
特別篇 5: 黑暗執行緒案例
尋找【 WHERE FlowId = “5b..” 】
IO 次數: 2 ( 完成 )
[FlowId] ... ...
07.. ... ...
9e.. ... ...
3b.. ... ...
cb.. ... ...
5b.. ... ...
5b.. cb..
07.. 3b.. 5b.. 9e.. cb..
Clustered Index ( 亂序式 )
116/129
2016
特別篇 5: 黑暗執行緒案例
新增【 FlowID: 4c.. 】
IO 次數: 0
[FlowId] ... ...
07.. ... ...
9e.. ... ...
3b.. ... ...
cb.. ... ...
5b.. ... ...
4c.. ... ...
5b.. cb..
07.. 3b.. 5b.. 9e.. cb..
Clustered Index ( 亂序式 )
117/129
2016
特別篇 5: 黑暗執行緒案例
新增【 FlowID: 4c.. 】
IO 次數: 1
[FlowId] ... ...
07.. ... ...
9e.. ... ...
3b.. ... ...
cb.. ... ...
5b.. ... ...
4c.. ... ...
5b.. cb..
07.. 3b.. 5b.. 9e.. cb..
Clustered Index ( 亂序式 )
118/129
2016
特別篇 5: 黑暗執行緒案例
新增【 FlowID: 4c.. 】
IO 次數: 2
[FlowId] ... ...
07.. ... ...
9e.. ... ...
3b.. ... ...
cb.. ... ...
5b.. ... ...
4c.. ... ...
5b.. cb..
07.. 3b.. 5b.. 9e.. cb..
Clustered Index ( 亂序式 )
119/129
2016
特別篇 5: 黑暗執行緒案例
新增【 FlowID: 4c.. 】
IO 次數: 3+3 ( 完成 )
Page Split 次數: 1
[FlowId] ... ...
07.. ... ...
9e.. ... ...
3b.. ... ...
cb.. ... ...
5b.. ... ...
4c.. ... ...
3b.. 5b.. cb..
07.. 3b.. 4c.. 5b..
Clustered Index ( 亂序式 )
9e.. cb..
120/129
2016
特別篇 5: 黑暗執行緒案例
如果用一般循序式 UUID
[FlowId] ... ...
1 ... ...
2 ... ...
3 ... ...
4 ... ...
5 ... ...
3 5
1 2 3 4 5
Clustered Index ( 循序式 )
121/129
2016
特別篇 5: 黑暗執行緒案例
尋找【 WHERE FlowId = 5 】
IO 次數: 0
[FlowId] ... ...
1 ... ...
2 ... ...
3 ... ...
4 ... ...
5 ... ...
3 5
1 2 3 4 5
Clustered Index ( 循序式 )
122/129
2016
特別篇 5: 黑暗執行緒案例
尋找【 WHERE FlowId = 5 】
IO 次數: 1
[FlowId] ... ...
1 ... ...
2 ... ...
3 ... ...
4 ... ...
5 ... ...
3 5
1 2 3 4 5
Clustered Index ( 循序式 )
123/129
2016
特別篇 5: 黑暗執行緒案例
尋找【 WHERE FlowId = 5 】
IO 次數: 2 ( 完成 )
[FlowId] ... ...
1 ... ...
2 ... ...
3 ... ...
4 ... ...
5 ... ...
3 5
1 2 3 4 5
Clustered Index ( 循序式 )
124/129
2016
特別篇 5: 黑暗執行緒案例
新增【 FlowID: 6 】
IO 次數: 0
[FlowId] ... ...
1 ... ...
2 ... ...
3 ... ...
4 ... ...
5 ... ...
6 ... ...
3 5
1 2 3 4 5
Clustered Index ( 循序式 )
125/129
2016
特別篇 5: 黑暗執行緒案例
新增【 FlowID: 6 】
IO 次數: 1
[FlowId] ... ...
1 ... ...
2 ... ...
3 ... ...
4 ... ...
5 ... ...
6 ... ...
3 5
1 2 3 4 5
Clustered Index ( 循序式 )
126/129
2016
特別篇 5: 黑暗執行緒案例
新增【 FlowID: 6 】
IO 次數: 2
[FlowId] ... ...
1 ... ...
2 ... ...
3 ... ...
4 ... ...
5 ... ...
6 ... ...
3 5
1 2 3 4 5
Clustered Index ( 循序式 )
127/129
2016
特別篇 5: 黑暗執行緒案例
新增【 FlowID: 6 】
IO 次數: 3+1 ( 完成 )
[FlowId] ... ...
1 ... ...
2 ... ...
3 ... ...
4 ... ...
5 ... ...
6 ... ...
3 6
1 2 3 4 5 6
Clustered Index ( 循序式 )
128/129
2016
特別篇 5: 黑暗執行緒案例
小結:本場景為例
黑暗執行緒 亂序式 UUID 循序式 UUID
Point-of-query IO 4 2 2
Insert IO 10 6 4
Insert
(Page Split)
1 1 0
Space size ++ + +
Latch(%) ++ + +
129/129
2016
特別篇 6: MultiColumn B-Tree Index
[Col#1] [Col#2]
1 A
3 B
3 C
4 D
3 C
CREATE INDEX ON table (Col#1, Col#2);
1 A 3 B 3 C 4 D

More Related Content

PDF
談 Uber 從 PostgreSQL 轉用 MySQL 的技術爭議
PDF
淺入淺出 MySQL & PostgreSQL
PDF
Innodb Deep Talk #2 でお話したスライド
PPTX
分散システムについて語らせてくれ
PDF
PostgreSQLをKubernetes上で活用するためのOperator紹介!(Cloud Native Database Meetup #3 発表資料)
PDF
PostgreSQLのgitレポジトリから見える2022年の開発状況(第38回PostgreSQLアンカンファレンス@オンライン 発表資料)
PDF
VIOPS10: SSDの基本技術と最新動向
PDF
eStargzイメージとlazy pullingによる高速なコンテナ起動
談 Uber 從 PostgreSQL 轉用 MySQL 的技術爭議
淺入淺出 MySQL & PostgreSQL
Innodb Deep Talk #2 でお話したスライド
分散システムについて語らせてくれ
PostgreSQLをKubernetes上で活用するためのOperator紹介!(Cloud Native Database Meetup #3 発表資料)
PostgreSQLのgitレポジトリから見える2022年の開発状況(第38回PostgreSQLアンカンファレンス@オンライン 発表資料)
VIOPS10: SSDの基本技術と最新動向
eStargzイメージとlazy pullingによる高速なコンテナ起動

What's hot (20)

PDF
PGOを用いたPostgreSQL on Kubernetes入門(PostgreSQL Conference Japan 2022 発表資料)
PDF
PostgreSQLのリカバリ超入門(もしくはWAL、CHECKPOINT、オンラインバックアップの仕組み)
PDF
片手間MySQLチューニング戦略
PDF
GoogleのSHA-1のはなし
PDF
ruby-ffiについてざっくり解説
PPTX
ネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptx
PDF
MySQL・PostgreSQLだけで作る高速あいまい全文検索システム
PDF
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
PPTX
アンケートを即可視化!~MS Forms ⇒ MS Flow ⇒ Power BI~
PDF
行ロックと「LOG: process 12345 still waiting for ShareLock on transaction 710 afte...
PDF
不揮発性メモリ(PMEM)を利用したストレージエンジンの話 #mysql_jp #myna会 #yahoo #mysql #pmem #不揮発性メモリ
PDF
PostgreSQLコミュニティに飛び込もう
PDF
(資料更新)事前に準備できる方は本資料で環境準備していただけるとより理解が深まります。ご協力宜しく御願い致します。
PDF
PostgreSQL10を導入!大規模データ分析事例からみるDWHとしてのPostgreSQL活用のポイント
PDF
Page cache in Linux kernel
PDF
アーキテクチャから理解するPostgreSQLのレプリケーション
PDF
YugabyteDBを使ってみよう(NewSQL/分散SQLデータベースよろず勉強会 #1 発表資料)
PDF
[OpenInfra Days Korea 2018] Day 2 - CEPH 운영자를 위한 Object Storage Performance T...
PDF
暗認本読書会10
PDF
BHyVeってなんや
PGOを用いたPostgreSQL on Kubernetes入門(PostgreSQL Conference Japan 2022 発表資料)
PostgreSQLのリカバリ超入門(もしくはWAL、CHECKPOINT、オンラインバックアップの仕組み)
片手間MySQLチューニング戦略
GoogleのSHA-1のはなし
ruby-ffiについてざっくり解説
ネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptx
MySQL・PostgreSQLだけで作る高速あいまい全文検索システム
Pythonの理解を試みる 〜バイトコードインタプリタを作成する〜
アンケートを即可視化!~MS Forms ⇒ MS Flow ⇒ Power BI~
行ロックと「LOG: process 12345 still waiting for ShareLock on transaction 710 afte...
不揮発性メモリ(PMEM)を利用したストレージエンジンの話 #mysql_jp #myna会 #yahoo #mysql #pmem #不揮発性メモリ
PostgreSQLコミュニティに飛び込もう
(資料更新)事前に準備できる方は本資料で環境準備していただけるとより理解が深まります。ご協力宜しく御願い致します。
PostgreSQL10を導入!大規模データ分析事例からみるDWHとしてのPostgreSQL活用のポイント
Page cache in Linux kernel
アーキテクチャから理解するPostgreSQLのレプリケーション
YugabyteDBを使ってみよう(NewSQL/分散SQLデータベースよろず勉強会 #1 発表資料)
[OpenInfra Days Korea 2018] Day 2 - CEPH 운영자를 위한 Object Storage Performance T...
暗認本読書会10
BHyVeってなんや
Ad

Similar to 資料庫索引數據結構及主鍵設計(b+tree)(part 1) (20)

PPT
搜狐Pv insight(py)技术交流
 
PPT
搜狐Pv insight(py)技术交流
PPTX
LinkIt 7697 開發平台簡介 (Traditional Chinese)
PDF
Data Pipeline Matters
PPT
Using google appengine_1027
PDF
前端开发演进之路 | The development of the front end - By TaoBeier
PPT
Using google appengine (2)
PPTX
Coscup 2018
PPT
Bluemix Node-Red Part II
PPTX
Google雲端 第一章準備篇
PDF
HPX_HP25_專案管理:如何言之有物
PDF
廣宣學堂Python金融爬蟲原理班 20170416
PDF
程式人雜誌 -- 2014 年8月號
PDF
淺談物聯網巨量資料挑戰 - Jazz 王耀聰 (2016/3/17 於鴻海內湖) 免費講座
PDF
程式人雜誌 -- 2013年4月號
PPT
Using google appengine_final
PPT
asker's Gartner ITxpo
PPT
Bluemix Node-Red Part I
PDF
Deep learning hardware architecture and software deploy with docker
PPTX
開放源碼的ASP.NET Core & ADO.NET (for VS2015)
搜狐Pv insight(py)技术交流
 
搜狐Pv insight(py)技术交流
LinkIt 7697 開發平台簡介 (Traditional Chinese)
Data Pipeline Matters
Using google appengine_1027
前端开发演进之路 | The development of the front end - By TaoBeier
Using google appengine (2)
Coscup 2018
Bluemix Node-Red Part II
Google雲端 第一章準備篇
HPX_HP25_專案管理:如何言之有物
廣宣學堂Python金融爬蟲原理班 20170416
程式人雜誌 -- 2014 年8月號
淺談物聯網巨量資料挑戰 - Jazz 王耀聰 (2016/3/17 於鴻海內湖) 免費講座
程式人雜誌 -- 2013年4月號
Using google appengine_final
asker's Gartner ITxpo
Bluemix Node-Red Part I
Deep learning hardware architecture and software deploy with docker
開放源碼的ASP.NET Core & ADO.NET (for VS2015)
Ad

More from Yi-Feng Tzeng (20)

PDF
重新想像:如何做技術選型決策 / Rethinking : Technical Decision
PDF
擁抱開源:企業應如何善用開源技術,才能得其利而防其弊-加強版
PDF
Testing in Production, Deploy on Fridays
PDF
COSCUP 2020 Day 2 - Opening Keynote
PDF
COSCUP 2020 Day 1 - Opening Keynote
PDF
Severless PHP Case : Agile Dashboard via GitLab Board API
PDF
給資安工程師開源授權觀念
PDF
Progressive Deployment & NoDeploy
PDF
Dev(Sec)Ops - Architecture for Security and Compliance
PDF
擁抱開源:企業應如何善用開源技術,才能得其利而防其弊
PDF
淺談量子機器學習 - 當機器學習遇見量子計算
PDF
A Modern Web Architecture for (GDPR) Compliance
PDF
量子技術 (2018 03-31)
PDF
Swoole Love PHP
PDF
邏輯優化的灰色面:針對網頁應用的時序攻擊 (2018臺灣資安大會: 軟體安全論壇)
PDF
Modern Web Architecture Design Journey
PDF
善用 MySQL 及 PostgreSQL - RDBMS 的逆襲 - part1
PDF
恰如其分的 MySQL 設計技巧 [Modern Web 2016]
PDF
軟體接案自由職業者 (Freelancer) 意想不到的風險
PDF
Enterprise Architecture Case in PHP (MUZIK Online)
重新想像:如何做技術選型決策 / Rethinking : Technical Decision
擁抱開源:企業應如何善用開源技術,才能得其利而防其弊-加強版
Testing in Production, Deploy on Fridays
COSCUP 2020 Day 2 - Opening Keynote
COSCUP 2020 Day 1 - Opening Keynote
Severless PHP Case : Agile Dashboard via GitLab Board API
給資安工程師開源授權觀念
Progressive Deployment & NoDeploy
Dev(Sec)Ops - Architecture for Security and Compliance
擁抱開源:企業應如何善用開源技術,才能得其利而防其弊
淺談量子機器學習 - 當機器學習遇見量子計算
A Modern Web Architecture for (GDPR) Compliance
量子技術 (2018 03-31)
Swoole Love PHP
邏輯優化的灰色面:針對網頁應用的時序攻擊 (2018臺灣資安大會: 軟體安全論壇)
Modern Web Architecture Design Journey
善用 MySQL 及 PostgreSQL - RDBMS 的逆襲 - part1
恰如其分的 MySQL 設計技巧 [Modern Web 2016]
軟體接案自由職業者 (Freelancer) 意想不到的風險
Enterprise Architecture Case in PHP (MUZIK Online)

資料庫索引數據結構及主鍵設計(b+tree)(part 1)

  • 1. 資料庫索引數據結構及主鍵設計 (B+Tree) Database index data structure and primary key design (part1) 2016 Ant [email protected]
  • 2. 2016 2/129 自我介紹 ♪ Muzik Online (www.muzikair.com) 總工程師。 ♪ Paganini+ (http://www.paganiniplus.com/) 技術長。 ♪ BELP (fb.com/belp.general) 共同創辦人。 ♪ CHROOT (www.chroot.org) 成員。 ♪ 講師經驗 PHPConf, Modern Web Taiwan, MOPCON, WebConf, COSCUP, JSDC Taiwan, DrupalCamp Taiwan, OSDC, HITCON, ... ♪ 略懂智慧財產權、資訊安全及軟體程式設計。 ♪ 『略懂諸葛』。 ♪ 沉浸於『人性』、『法律』與『科技』的三角關係中。
  • 3. 2016 3/129 問題 1: UUID ? Q: 資料庫 Primary key 使用 UUID 比較快? Serial/Auto-Increment 1 2 3 4 5 ... UUID 3a5e439b-eeb4-4074-8b23-51c2cdd35421 1bb19e6b-9c0c-475e-a7b3-f01a6b4cd496 af4c8b80-4bf5-4bf3-a4e3-a71bed920f10 e62acb5b-a393-4707-9aa5-90f79352eb4b 2e199d72-4e49-4ace-a504-419da63878f5 ...
  • 4. 4/129 2016 問題 1: UUID ? Q: 資料庫 Primary key 使用 UUID 比較快? 偽命題
  • 5. 2016 5/129 問題 1 ( 修正 ): MySQL UUID ? Q: MySQL 的 Primary key 使用 UUID 比較快? Serial/Auto-Increment 1 2 3 4 5 ... UUID 3a5e439b-eeb4-4074-8b23-51c2cdd35421 1bb19e6b-9c0c-475e-a7b3-f01a6b4cd496 af4c8b80-4bf5-4bf3-a4e3-a71bed920f10 e62acb5b-a393-4707-9aa5-90f79352eb4b 2e199d72-4e49-4ace-a504-419da63878f5 ...
  • 6. 6/129 2016 問題 1 ( 修正 ): MySQL UUID ? Q: MySQL 的 Primary key 使用 UUID 比較快? 偽命題
  • 7. 7/129 2016 問題 1 ( 修正 ): MySQL UUID ? UUID 目前公定有五種版本: ➀ Version 1 (MAC address & date-time) ➁ Version 2 (DCE Security) ➂ Version 3 (MD5 hash & namespace) ➃ Version 4 (Random) ➄ Version 5 (SHA-1 hash & namespace) Ref: https://en.wikipedia.org/wiki/Universally_unique_identifier
  • 8. 8/129 2016 問題 1 ( 修正 ): MySQL UUID ? UUID 目前公定有五種版本: ➀ Version 1 (MAC address & date-time) ➁ Version 2 (DCE Security) ➂ Version 3 (MD5 hash & namespace) ➃ Version 4 (Random) ➄ Version 5 (SHA-1 hash & namespace) Ref: https://en.wikipedia.org/wiki/Universally_unique_identifier Version 2 未在 UUID 規格中定義,少見
  • 9. 9/129 2016 問題 1 ( 修正 ): MySQL UUID ? UUID 目前公定有五種版本: ➀ Version 1 (MAC address & date-time) ➁ Version 2 (DCE Security) ➂ Version 3 (MD5 hash & namespace) ➃ Version 4 (Random) ➄ Version 5 (SHA-1 hash & namespace) Ref: https://en.wikipedia.org/wiki/Universally_unique_identifier
  • 10. 10/129 2016 問題 1 ( 修正 ): MySQL UUID ? UUID 類循序式 ( 通常後序產生的值 > 先前產生的值 ) : ➀ Version 1 (MAC address & date-time) UUID 亂序式 ( 值的大小沒有前後關係 ) : ➂ Version 3 (MD5 hash & namespace) ➃ Version 4 (Random) ➄ Version 5 (SHA-1 hash & namespace)
  • 11. 11/129 2016 問題 1 ( 修正 ): MySQL UUID ? UUIDv1 的範例: 2190718a-c7a3-61e2-aa34-024281ed9db5 2191f33e-c7a3-61e2-9b92-024281ed9db5 2192cc0a-c7a3-61e2-be4c-024281ed9db5 21939950-c7a3-61e2-9aad-024281ed9db5 21945ff2-c7a3-61e2-90fc-024281ed9db5 219525f4-c7a3-61e2-99df-024281ed9db5 Time
  • 12. 12/129 2016 問題 1 ( 修正 ): MySQL UUID ? UUIDv4 的範例: 3a5e439b-eeb4-4074-8b23-51c2cdd35421 1bb19e6b-9c0c-475e-a7b3-f01a6b4cd496 af4c8b80-4bf5-4bf3-a4e3-a71bed920f10 e62acb5b-a393-4707-9aa5-90f79352eb4b 2e199d72-4e49-4ace-a504-419da63878f5 8cf2e49f-8ae9-43f2-a84d-78cb323114a3 Time
  • 13. 13/129 2016 問題 1 ( 修正 ): MySQL UUID ? 結論: UUID 可以是類循序式,也可以是亂序式。 但《循序式》與《亂序式》的重要性為何?
  • 14. 14/129 2016 問題 1 ( 修正 ): MySQL UUID ? Ref: https://www.percona.com/blog/2014/12/19/store-uuid-optimized-way/
  • 15. 15/129 2016 問題 1 ( 修正 ): MySQL UUID ? 延伸 : GUID 與 UUID 的差異?
  • 16. 16/129 2016 問題 1 ( 修正 ): MySQL UUID ? GUID 是 Microsoft 用詞,指的其實類似於 UUID , 但實作方式不一樣。 Microsoft 對於 GUID 的實作至少有兩種: ➀ 基於 UuidCreate 的 NEWID(SQL) ; ➁ 基於 UuidCreateSequential 的 NEWSEQUENTIALID(SQL) 。 其中 NEWID 是亂序式,而 NEWSEQUENTIALID 是循序式。
  • 18. 18/129 2016 索引數據結構 : 無索引 目的:尋找【欄位一為 5 的資料】 操作: 5 , O(n) 缺點:總是需要全表掃描 資料表: 1 user1 pass1 2 user2 pass2 3 user3 pass3 4 user4 pass4 5 user5 pass5
  • 19. 19/129 2016 索引數據結構 : B-tree 索引 B-tree = Balanced tree (not Binary tree)
  • 20. 20/129 2016 索引數據結構 : B-tree 索引 目的:尋找【欄位一為 5 的資料】 操作: 4 , O(logbn) 缺點:全表掃描需要遍歷樹 資料表: 1 user1 pass1 2 user2 pass2 3 user3 pass3 4 user4 pass4 5 user5 pass5 8 3 6 1 2 4 5 7
  • 21. 21/129 2016 索引數據結構 : B+tree 索引 目的:尋找【欄位一為 5 的資料】 優點:全表掃描不需遍歷樹 資料表: 1 user1 pass1 2 user2 pass2 3 user3 pass3 4 user4 pass4 5 user5 pass5 13 4 7 1 2 3 4 5 6 7
  • 22. 22/129 2016 索引數據結構 : B+tree 索引 目的:尋找【欄位一為 5 的資料】 操作: 4 , O(logbn) 優點:全表掃描不需遍歷樹 資料表: 1 user1 pass1 2 user2 pass2 3 user3 pass3 4 user4 pass4 5 user5 pass5 13 4 7 1 2 3 4 5 6 7 13 b
  • 23. 2016 23/129 問題 2: B+tree Q: 哪些資料庫索引數據結構支援 B+tree ? MySQL Oracle Microsoft SQL Server PostgreSQL MongoDB CouchDB LevelDB RocksDB HBase Cassandra Riak NessDB BoltDB TokuDB Aerospike Couchbase
  • 24. 24/129 2016 問題 2: B+tree Q: 哪些資料庫索引數據結構支援 B+tree ? MySQL Oracle Microsoft SQL Server PostgreSQL MongoDB CouchDB LevelDB RocksDB HBase Cassandra Riak NessDB BoltDB TokuDB Aerospike Couchbase
  • 26. 26/129 2016 索引頁分裂 觸發:頁剩餘空間 - 保留空間 < 新增資料 問題:頁分裂時會 Latch( 小鎖 ) page page page latch page
  • 27. 27/129 2016 索引頁分裂 : 循序式新增資料 操作:新增 25( 假設頁只能存三筆資料 ) 9 18 21 24 19 20 21 22 23 24 25 p1 p10 p12p11 9 18 21 24 25 19 20 21 22 23 24 p1 p10 p12p11 25 p13 latch latch hotspot
  • 28. 28/129 2016 索引頁分裂 : 亂序式新增資料 操作:新增 5( 假設頁只能存三筆資料 ) 20 6 12 2 4 6 8 10 12 5 20 4 6 12 2 4 5 6 8 10 12 p1 p1 p2 p2 p4p3 p3 p4p5 latch fragmentation fragmentation
  • 29. 29/129 2016 索引頁分裂 : 亂序式新增資料 Ref: http://blogs.catapultsystems.com/rnewkirk/archive/2013/05/14/sql-fragmentation-explained/
  • 30. 30/129 2016 索引頁分裂 : I/O 與 Page Size 資料庫 I/O 以 Page 為單位。 儲存引擎的 Page Size : ➊ PostgreSQL 8KB ➋ MySQL/InnoDB 16KB(default) ➌ MongoDB/MMAPv1 dynamic (powered by 2) ➍ MongoDB/WiredTiger 32KB(default) ➎ Percona/TokuDB 64KB(default)
  • 31. 31/129 2016 索引頁分裂 : 循序式新增 I/O 9 18 21 24 25 19 20 21 22 23 24 25 p1 p10 p12p11 25 p13 latch latch Block N+1 Block N+2 Block N+3 p11 p12 p13p10 I/O hotspot? hotspot
  • 32. 32/129 2016 索引頁分裂 : 循序式新增 I/O 如果 Page Size 比較大? Block N+1 Block N+2 Block N+3 p11 p12 p13p10 I/O Block N+1 Block N+2 p13p12p11p10 I/OI/O
  • 33. 33/129 2016 索引頁分裂 : 亂序式新增 I/O Block N+3 Block N+4 I/O p2 p3 p4p1 # # #p5 20 6 12 2 4 6 8 10 12 20 4 6 12 2 4 5 6 8 10 12 p1 p1 p2 p2 p4p3 p3 p4p5 latch I/O 5
  • 34. 34/129 2016 索引頁分裂 : 亂序式新增 I/O 如果 Page Size 比較大? Block N+4p4p3p2p1 I/OI/O Block N+3 Block N+4 I/O p2 p3 p4p1 # # #p5 I/O #p5 I/O
  • 36. 36/129 2016 索引子頁結構 : Non-clustered index 以 B+tree 為例 特色:子頁不包括資料本身 ( 指針指向資料 ) 補充:對應的資料表稱 Heap table 資料表:循序式 1 user1 pass1 2 user2 pass2 3 user3 pass3 4 user4 pass4 5 user5 pass5 13 4 7 1 2 3 4 5 6 7
  • 37. 37/129 2016 索引子頁結構 : Non-clustered index 如果不是《循序式》而是《亂序式》。 資料表:亂序式 1 user1 pass1 4 user4 pass4 5 user5 pass5 2 user2 pass2 3 user3 pass3 13 4 7 1 2 3 4 5 6 7
  • 38. 38/129 2016 索引子頁結構 : Clustered index 以 B+tree 為例 特色:子頁包括資料本身 ( 不需指針指向資料 ) 補充:對應的資料表稱 Index Organized Table(IOT) 資料表:循序式與亂序式都一樣 13 4 7 1 2 3 4 5 6 7 1 user1 pass1 2 user2 pass2 3 user3 pass3 4 user4 pass4 5 user5 pass5
  • 39. 39/129 2016 Non-clustered index(Heap table) 循序式 ➀ 有索引指針指向資料的額外開銷。 ➁ Hotspot 發生在樹最右下的頁,但循序寫及合併寫機率高。 ➂ Range scan 讀取時開銷大。 亂序式 ➀ 有索引指針指向資料的額外開銷。 ➁ Range scan 讀取時開銷可能比循序式更大。 ➂ 大量新增資料,幾乎是隨機寫,也難以合併寫。 索引子頁結構 : Non-clustered index
  • 40. 40/129 2016 索引子頁結構 : Clustered index Clustered index(IOT) 循序式 ➀ 資料佔頁空間,頁存放的資料量少,頁分裂頻繁。 ➁ 搜尋至頁索引時,因包括資料本身,無額外指針開銷。 ➂ Hotspot 發生在樹最右下的頁,但循序寫及合併寫機率高。 亂序式 ➀ 資料佔頁空間,頁存放的資料量少,頁分裂頻繁。 ➁ 搜尋至頁索引時,因包括資料本身,無額外指針開銷。 ➂ 為了維持循序,發生大量的頁分裂。
  • 41. 41/129 2016 索引子頁結構 : Clustered index Q: 循序式 / 亂序式 vs. I/O Scheduler vs. Filesystem vs. HDD / Flash / Fusion IO ? 循序式 亂序式 CFQ Deadline NOOP HDD Flash Fusion IO Ext4 XFS ZFS BtrFS
  • 43. 43/129 2016 Range scan >, <, >=, <= BETWEEN, IN GROUP BY with max, min, count
  • 44. 44/129 2016 Range scan: Heap table w/ 循序式 SELECT * FROM x WHERE y BETWEEN 1 AND 7; 1 user1 pass1 2 user2 pass2 3 user3 pass3 4 user4 pass4 5 user5 pass5 6 user6 pass6 7 user7 pass7 13 4 7 1 2 3 4 5 6 7 Block N+3 ... p1 p3 I/O p2 p1 p2 p3 p4 I/O Block N+M
  • 45. 45/129 2016 Range scan: Heap table w/ 亂序式 SELECT * FROM x WHERE y BETWEEN 1 AND 7; 1 user1 pass1 4 user4 pass4 5 user5 pass5 2 user2 pass2 3 user3 pass3 7 user7 pass7 6 user6 pass6 13 4 7 1 2 3 4 5 6 7 I/O p5 p7 p3 p6 I/O I/OI/O p1 # p2 p4... p4 p7 p5 p1 p3 p2 p6
  • 46. 46/129 2016 Range scan: Heap table w/ 亂序式 I/O p5 p7 p3 p6 I/O I/OI/O p1 # p2 p4... Ref: http://etutorials.org/SQL/Postgresql/Part+I+General+PostgreSQL+Use/Chapter+4.+Performance/Gathering+Performance+Information/
  • 47. 47/129 2016 Range scan: IOT w/ 循序式 & 亂序式 SELECT * FROM x WHERE y BETWEEN 1 AND 7; 13 4 7 1 2 3 4 5 6 7 1 user1 pass1 2 user2 pass2 3 user3 pass3 4 user4 pass4 5 user5 pass5 6 user6 pass6 7 user7 pass7 p1 p3 p2 Block N+3 ... I/O p1 p2 p3 p4 I/O Block N+M
  • 48. 2016 48/129 問題 3 Q: 哪些資料庫支援 Heap table ?哪些支援 IOT ? MySQL Oracle Microsoft SQL Server PostgreSQL MongoDB CouchDB
  • 49. 49/129 2016 問題 3 Heap table IOT MySQL/MyISAM O X MySQL/InnoDB X O Oracle O O Microsoft SQL Server O O PostgreSQL O X MongoDB/MMAPv1 O X MongoDB/WiredTiger O X CouchDB X O
  • 51. 2016 51/129 特別篇 1: MySQL 生態系 Q: MySQL 生態系, MySQL / Percona / MariaDB / WebScaleSQL 該怎麼選擇?
  • 52. 52/129 2016 特別篇 1: MySQL 生態系 MySQL ➀ 官方,有 Oracle 技術支持及專利保護。 ➁ 最新的 MySQL 5.7 擁有大量新特性。 ➂ 商業因素預設不會接受其他分支的特性。 Percona ➀ drop-in compatible with (official) MySQL 。 ➁ 針對 MySQL 額外新增許多特性。 ➂ 額外支援 XtraDB / TokuDB 等引擎。 ➃ 商業特性可接受其他所有分支的特性。
  • 53. 53/129 2016 特別篇 1: MySQL 生態系 MariaDB ➀ drop-in replacement for (official) MySQL 。 ➁ MariaDB 10 基於 MySQL 5.6 ,但不相容 5.7 。 ➂ 額外支援 XtraDB / TokuDB / Cassandra / CONNECT 等引擎。 ➃ 至今仍沒有穩定的自我開發儲存引擎。 XtraDB / TokuDB 都屬 Percona 公司。 WebScaleSQL ➀ 基於 5.6 ,但可收納 5.7 特性。 ➁ 專針對特大型 Web 公司需求而生,小心駕馭。
  • 54. 54/129 2016 特別篇 1: MySQL 生態系 MySQL 5.7 解決了 index→lock contention 問題。
  • 55. 2016 55/129 特別篇 2: PostgreSQL PostgreSQL 是 Object-relational database
  • 56. 56/129 2016 特別篇 2: PostgreSQL (Fusion IO) Fusion IO 可大幅排除 IO Bottlenect 的可能性。
  • 57. 57/129 2016 特別篇 2: PostgreSQL (Fusion IO) Fusion IO 只特別支援 Oracle / MySQL / Percona / MariaDB ? Ref: https://www.sandisk.com/business/datacenter/resources/overviews/accelerate-mysql-open-source-databases
  • 58. 58/129 2016 特別篇 2: PostgreSQL (Fusion IO) Fusion IO 可讓 MySQL 免除 double write 。 Ref: https://www.sandisk.com/business/datacenter/resources/overviews/accelerate-mysql-open-source-databases
  • 59. 59/129 2016 特別篇 2: PostgreSQL (Fragmentation) PostgreSQL(HOT) 天性無法避免 fragmentation 。 Ref: http://etutorials.org/SQL/Postgresql/Part+I+General+PostgreSQL+Use/Chapter+4.+Performance/Gathering+Performance+Information/
  • 60. 60/129 2016 特別篇 2: PostgreSQL (Index Bloat) PostgreSQL(non HOT updates) 天性無法避免 index bloat 。 Ref: PostgreSQL 9.0 High Performance [PACKT] (2010) (p171)
  • 63. 63/129 2016 特別篇 2: PostgreSQL (Merge IO) PostgreSQL 沒有類似 MySQL 的 Change Buffer 。 Ref: http://www.slideshare.net/morgo/inno-db-presentation (p9)
  • 64. 64/129 2016 特別篇 2: PostgreSQL (Merge IO) MySQL Insert Buffering( 現在改名 Change Buffer) : 1. Reducing the number of disk i/o operations by merging i/o requests to the same block. 2. Some random i/o operations can be sequential. Ref: http://www.percona.com/files/presentations/percona-live/london-2011/PLUK2011-linux-and-hw-optimizations-for-mysql.pdf (p17)
  • 66. 66/129 2016 特別篇 2: PostgreSQL ( 儲存引擎 ) Microsoft SQL Server / Oracle 支援 Heap table 及 IOT , 可依各資料表的特性分別採用。 MySQL 及 MongoDB 支援可抽換儲存引擎,也可依資料表的 特性分別採用。 但 PostgreSQL 只有一個儲存引擎,也只支援 Heap table 。
  • 68. 68/129 2016 特別篇 3: MongoDB Ref: http://itindex.net/detail/43573
  • 69. 69/129 2016 特別篇 3: MongoDB Ref: http://sql-vs-nosql.blogspot.tw/2013/11/indexes-comparison-mongodb-vs-mssqlserver.html
  • 70. 70/129 2016 特別篇 3: MongoDB Ref: http://learnmongodbthehardway.com/schema/chapter4/ B+Tree / Heap Table
  • 71. 71/129 2016 特別篇 3: MongoDB Ref: Indexing and Performance Tuning (2015-11-03).pdf (p39)
  • 72. 72/129 2016 特別篇 3: MongoDB Index ➀ ”統一命名為 _id” ➁ ”新增若未指定 _id” 值,會使用 ObjectId ➂ ObjectId 為 12-byte BSON 型態 ➊ 4-byte 為 UNIX 紀元時間 ➋ 3-byte 為機器識別碼 ➌ 2-byte 為 Process ID ➍ 3-byte 為隨機值 Ref: https://docs.mongodb.org/manual/reference/object-id/ “_id” : ObjectId(“563479cc8a8a4246bd27d784”) “_id” : ObjectId(“563479d48a8a4246bd27d785”) “_id” : ObjectId(“563479df8a8a4246bd27d786”) 循序式 UUID
  • 73. 73/129 2016 特別篇 3: MongoDB MMAPv1 儲存引擎 ➀ Memory-mapped files Ref: http://learnmongodbthehardway.com/schema/chapter3/
  • 74. 74/129 2016 特別篇 3: MongoDB MMAPv1 儲存引擎 ➀ Memory-mapped files ➁ Padding Ref: http://learnmongodbthehardway.com/schema/chapter3/
  • 75. 75/129 2016 特別篇 3: MongoDB MMAPv1 儲存引擎 ➀ Memory-mapped files ➁ Padding ➂ Fragmentation Ref: http://learnmongodbthehardway.com/schema/chapter3/
  • 76. 76/129 2016 特別篇 3: MongoDB MMAPv1 儲存引擎 ➀ Memory-mapped files ➁ Padding ➂ Fragmentation ➃ Collection-level locking (WiredTiger 為 Document-level) Ref: http://sql-vs-nosql.blogspot.tw/2013/11/indexes-comparison-mongodb-vs-mssqlserver.html
  • 77. 77/129 2016 特別篇 3: MongoDB MMAPv1 儲存引擎 ➀ Memory-mapped files ➁ Padding ➂ Fragmentation ➃ Collection-level locking (WiredTiger 為 Document-level) ➄ MongoDB 3.2 以前為預設引擎, 3.2 後換 WiredTiger Ref: https://docs.mongodb.org/manual/core/wiredtiger/
  • 78. 78/129 2016 特別篇 3: MongoDB MMAPv1 的 Fragmentation 問題 Ref: http://www.slideshare.net/mongodb/7-managing-a-maturing-mongo-db-ecosystem-charity-majors (p35) 左邊是大量 Fragmentation ; 右邊是修復 Fragmentation 後
  • 79. 79/129 2016 特別篇 3: MongoDB MMAPv1 的 Fragmentation 問題 動作:連續新增 5 個 Document Collection : {Document 1} {Document 2} {Document 3} {Document 4} {Document 5}
  • 80. 80/129 2016 特別篇 3: MongoDB MMAPv1 的 Fragmentation 問題 動作:更新 Document 3 情況一:新的 Document 3 大小 <= 原先大小 Collection : {Document 1} {Document 2} {Document 3} {Document 4} {Document 5} {Document 1} {Document 2} {Document 3‘} {Document 4} {Document 5}
  • 81. 81/129 2016 特別篇 3: MongoDB MMAPv1 的 Fragmentation 問題 動作:更新 Document 3 情況二:新的 Document 3 大小 > 原先大小 Collection : {Document 1} {Document 2} {Document 3} {Document 4} {Document 5} {Document 1} {Document 2} Free {Document 4} {Document 5} {Document 3‘}
  • 82. 82/129 2016 特別篇 3: MongoDB MMAPv1 的 Fragmentation 問題 動作:新增 Document 6 Collection : {Document 1} {Document 2} Free {Document 4} {Document 5} {Document 3‘}
  • 83. 83/129 2016 特別篇 3: MongoDB MMAPv1 的 Fragmentation 問題 動作:新增 Document 6 情況一: Document 6 大小 <= 原先 Document 3 (Free) 大小 Collection : {Document 1} {Document 2} {Document 6} {Document 4} {Document 5} {Document 3‘} {Document 1} {Document 2} Free {Document 4} {Document 5} {Document 3‘}
  • 84. 84/129 2016 特別篇 3: MongoDB MMAPv1 的 Fragmentation 問題 動作:新增 Document 6 情況二: Document 6 大小 > 原先 Document 3 (Free) 大小 Collection : {Document 1} {Document 2} Free {Document 4} {Document 5} {Document 3‘} {Document 6} {Document 1} {Document 2} Free {Document 4} {Document 5} {Document 3‘}
  • 85. 85/129 2016 特別篇 3: MongoDB 特色與改善 ➀ Sharding/Replica 較容易 ( 但 Sharding/Replica 只有 Primary 可寫 ) ➁ Dynamic schema ( 不是 Schemaless) ➂ 儲存引擎可抽換 ➊ MMAPv1 ➋ WiredTiger ➌ inMemory ➍ Devnull ➎ (RocksDB)
  • 86. 86/129 2016 特別篇 3: MongoDB 特色與改善 ➃ 寫入的 Locking level 改善 2.2 版前, Process-level lock ,一個 Mongod 實例一個鎖 2.8 版前, Database-level lock ,一個 DB 一個鎖 2.8 版之後, WiredTiger 提供 Document-level lock 3.0 版之後, MMAPv1 改為 Collection-level lock Ref: http://sql-vs-nosql.blogspot.tw/2013/11/indexes-comparison-mongodb-vs-mssqlserver.html
  • 87. 87/129 2016 特別篇 3: MongoDB 特色與改善 ➄ 支援 MapReduce 2.4 版前,使用 SpiderMonkey ,是 single threaded 2.4 版之後,改用 V8 engine ,改善問題 ➅ Single thread model ,大多時候只用到一顆 CPU (WiredTiger 已支援 Multiple CPUs)
  • 88. 2016 88/129 特別篇 4: RDMBS or NoSQL ? Q: 使用 RDBMS 還是 NoSQL ?
  • 89. 89/129 2016 特別篇 4: RDMBS or NoSQL ? Q: 使用 RDBMS 還是 NoSQL ? 是個偽命題,需視你的場景而定。
  • 90. 90/129 2016 特別篇 4: RDMBS or NoSQL ? 不過 RDBMS 及 NoSQL 的分界會愈來愈小。 過去的一些 RDBMS 已開始支援 NoSQL 特性, Microsoft SQL Server / Oracle / MySQL / PostgreSQL 都確定支援 JSON(B) 操作。 Percona / MariaDB 可抽換為 TokuDB 引擎, MariaDB 更可抽換為 Cassandra 引擎。 NoSQL 等也開始支援強一致性。
  • 91. 91/129 2016 特別篇 4: RDMBS or NoSQL ? 不過 RDBMS 及 NoSQL 的分界會愈來愈小。 過去的一些 RDBMS 已開始支援 NoSQL 特性, Microsoft SQL Server / Oracle / MySQL / PostgreSQL 都確定支援 JSON(B) 操作。 Percona / MariaDB 可抽換為 TokuDB 引擎, MariaDB 更可抽換為 Cassandra 引擎。 NoSQL 等也開始支援強一致性。 NewSQL
  • 92. 2016 92/129 特別篇 5: 黑暗執行緒案例 Q: 試著分析黑暗執行緒的文章。 【 GUID Primary Key 資料庫避雷守則】 Ref: http://blog.darkthread.net/post-2016-01-29-guid-as-pk-on-db.aspx
  • 93. 93/129 2016 特別篇 5: 黑暗執行緒案例 以架構設計而言,我更傾向讓應用伺服器決定 GUID / UUID 的值, 理由有幾個。 ➊ 未來若需要異質資料庫彼此交換資料, GUID / UUID 的衝突會 更小。例如若 SQL Server 要與 MySQL 交換, MySQL 沒有 NEWID / NEWSEQUENTIALID 函式,所以勢必要用另一種算法來計算 UUID , 而算法不同就可能破壞原本 GUID / UUID 不會重複的機率。 ➋ 資料庫在整體架構中,是最難以擴展的,所以我傾向讓資料庫做愈少 事情愈好。 GUID / UUID 是需要計算的,即使開銷很低,但若量大還是 很可觀,所以我還是會把計算的成本移至應用伺服器處理。
  • 94. 94/129 2016 特別篇 5: 黑暗執行緒案例 ➌ 應用伺服器脫離 SQL Server 後,就無法使用 NEWID 及 NEWSEQUENTIALID ,所以需要找 UUID 產生器。 UUID 產生器有 幾種版本, UUIDv1 是類循序性, UUIDv4 是亂序性,可以依業務 場景選擇所需。而且 UUIDv1 的類循序性不像 NEWSEQUENTIALID 這麼容易猜測。 ➍ 大規模架構中,全循序性 Insert 不一定是好事。想像一下,順序性 Insert 時,所有資料會集中在樹最右下角的 Leaf Page Insert ,當 Page 滿後,就必須 Page Split ,此時就一定有 Latch 。 Latch 會減 緩 Insert 的速度。再加上實際在硬碟寫入的 Block 也會變成是 Hotspot 。 所以有時候,適當非循序性所造成的 Fragmentation 有時反而會更快。 最後有可能會變成全順序性 Insert 不一定最快,全隨機性 Insert 也不 一定最好,反而中間找平衡才是最佳的。而這時把 UUID 的計算移到應 用伺服器,剛好可以滿足這點。
  • 96. 96/129 2016 特別篇 5: 黑暗執行緒案例 黑暗執行緒提供的表設計建議 4c.. cb.. ee.. 07.. 3b.. 4c.. 5b.. 9e.. cb.. ee.. Clustered Index ( 循序式 ) Nonclustered Index ( 亂序式 ) 3 6 7 1 2 3 4 5 6 7
  • 98. 98/129 2016 特別篇 5: 黑暗執行緒案例 假設已有五筆資料 5b.. cb.. 07.. 3b.. 5b.. 9e.. cb.. 3 5 1 2 3 4 5 [SeqNo] [FlowId] ... 1 07.. ... 2 9e.. ... 3 3b.. ... 4 cb.. ... 5 5b.. ... 1 3 5 2 4 Nonclustered Index ( 亂序式 ) Clustered Index ( 循序式 )
  • 99. 99/129 2016 特別篇 5: 黑暗執行緒案例 尋找【 WHERE FlowId = “5b..” 】 IO 次數: 0 5b.. cb.. 07.. 3b.. 5b.. 9e.. cb.. 3 5 1 2 3 4 5 [SeqNo] [FlowId] ... 1 07.. ... 2 9e.. ... 3 3b.. ... 4 cb.. ... 5 5b.. ... 1 3 5 2 4 Nonclustered Index ( 亂序式 ) Clustered Index ( 循序式 )
  • 100. 100/129 2016 特別篇 5: 黑暗執行緒案例 尋找【 WHERE FlowId = “5b..” 】 IO 次數: 1 5b.. cb.. 07.. 3b.. 5b.. 9e.. cb.. 3 5 1 2 3 4 5 [SeqNo] [FlowId] ... 1 07.. ... 2 9e.. ... 3 3b.. ... 4 cb.. ... 5 5b.. ... 1 3 5 2 4 Nonclustered Index ( 亂序式 ) Clustered Index ( 循序式 )
  • 101. 101/129 2016 特別篇 5: 黑暗執行緒案例 尋找【 WHERE FlowId = “5b..” 】 IO 次數: 2 5b.. cb.. 07.. 3b.. 5b.. 9e.. cb.. 3 5 1 2 3 4 5 [SeqNo] [FlowId] ... 1 07.. ... 2 9e.. ... 3 3b.. ... 4 cb.. ... 5 5b.. ... 1 3 5 2 4 Nonclustered Index ( 亂序式 ) Clustered Index ( 循序式 )
  • 102. 102/129 2016 特別篇 5: 黑暗執行緒案例 尋找【 WHERE FlowId = “5b..” 】 IO 次數: 3 5b.. cb.. 07.. 3b.. 5b.. 9e.. cb.. 3 5 1 2 3 4 5 [SeqNo] [FlowId] ... 1 07.. ... 2 9e.. ... 3 3b.. ... 4 cb.. ... 5 5b.. ... 1 3 5 2 4 Nonclustered Index ( 亂序式 ) Clustered Index ( 循序式 )
  • 103. 103/129 2016 特別篇 5: 黑暗執行緒案例 尋找【 WHERE FlowId = “5b..” 】 IO 次數: 4 ( 完成 ) 5b.. cb.. 07.. 3b.. 5b.. 9e.. cb.. 3 5 1 2 3 4 5 [SeqNo] [FlowId] ... 1 07.. ... 2 9e.. ... 3 3b.. ... 4 cb.. ... 5 5b.. ... 1 3 5 2 4 Nonclustered Index ( 亂序式 ) Clustered Index ( 循序式 )
  • 104. 104/129 2016 特別篇 5: 黑暗執行緒案例 新增【 SeqNo: 6, FlowID: 4c.. 】 IO 次數: 0 5b.. cb.. 07.. 3b.. 5b.. 9e.. cb.. 3 5 1 2 3 4 5 [SeqNo] [FlowId] ... 1 07.. ... 2 9e.. ... 3 3b.. ... 4 cb.. ... 5 5b.. ... 6 4c.. ... 1 3 5 2 4 Nonclustered Index ( 亂序式 ) Clustered Index ( 循序式 )
  • 105. 105/129 2016 特別篇 5: 黑暗執行緒案例 新增【 SeqNo: 6, FlowID: 4c.. 】 IO 次數: 1 5b.. cb.. 07.. 3b.. 5b.. 9e.. cb.. 3 5 1 2 3 4 5 [SeqNo] [FlowId] ... 1 07.. ... 2 9e.. ... 3 3b.. ... 4 cb.. ... 5 5b.. ... 6 4c.. ... 1 3 5 2 4 Nonclustered Index ( 亂序式 ) Clustered Index ( 循序式 )
  • 106. 106/129 2016 特別篇 5: 黑暗執行緒案例 新增【 SeqNo: 6, FlowID: 4c.. 】 IO 次數: 2 5b.. cb.. 07.. 3b.. 5b.. 9e.. cb.. 3 5 1 2 3 4 5 [SeqNo] [FlowId] ... 1 07.. ... 2 9e.. ... 3 3b.. ... 4 cb.. ... 5 5b.. ... 6 4c.. ... 1 3 5 2 4 Nonclustered Index ( 亂序式 ) Clustered Index ( 循序式 )
  • 107. 107/129 2016 特別篇 5: 黑暗執行緒案例 新增【 SeqNo: 6, FlowID: 4c.. 】 IO 次數: 3+3 Page Split 次數: 1 3 5 1 2 3 4 5 [SeqNo] [FlowId] ... 1 07.. ... 2 9e.. ... 3 3b.. ... 4 cb.. ... 5 5b.. ... 6 4c.. ... Nonclustered Index ( 亂序式 ) Clustered Index ( 循序式 ) 07.. 3b.. 4c.. 5b.. 1 3 6 5 42 3b.. 5b.. cb.. 9e.. cb..
  • 108. 108/129 2016 特別篇 5: 黑暗執行緒案例 新增【 SeqNo: 6, FlowID: 4c.. 】 IO 次數: 3+3+1 Page Split 次數: 1 3 5 1 2 3 4 5 [SeqNo] [FlowId] ... 1 07.. ... 2 9e.. ... 3 3b.. ... 4 cb.. ... 5 5b.. ... 6 4c.. ... Nonclustered Index ( 亂序式 ) Clustered Index ( 循序式 ) 07.. 3b.. 4c.. 5b.. 1 3 6 5 42 3b.. 5b.. cb.. 9e.. cb..
  • 109. 109/129 2016 特別篇 5: 黑暗執行緒案例 新增【 SeqNo: 6, FlowID: 4c.. 】 IO 次數: 3+3+2 Page Split 次數: 1 3 5 1 2 3 4 5 [SeqNo] [FlowId] ... 1 07.. ... 2 9e.. ... 3 3b.. ... 4 cb.. ... 5 5b.. ... 6 4c.. ... Nonclustered Index ( 亂序式 ) Clustered Index ( 循序式 ) 07.. 3b.. 4c.. 5b.. 1 3 6 5 42 3b.. 5b.. cb.. 9e.. cb..
  • 110. 110/129 2016 特別篇 5: 黑暗執行緒案例 新增【 SeqNo: 6, FlowID: 4c.. 】 IO 次數: 3+3+3 Page Split 次數: 1 3 5 1 2 3 4 5 6 [SeqNo] [FlowId] ... 1 07.. ... 2 9e.. ... 3 3b.. ... 4 cb.. ... 5 5b.. ... 6 4c.. ... Nonclustered Index ( 亂序式 ) Clustered Index ( 循序式 ) 07.. 3b.. 4c.. 5b.. 1 3 6 5 42 3b.. 5b.. cb.. 9e.. cb..
  • 111. 111/129 2016 特別篇 5: 黑暗執行緒案例 新增【 SeqNo: 6, FlowID: 4c.. 】 IO 次數: 3+3+4=10 ( 完成 ) Page Split 次數: 1 07.. 3b.. 4c.. 5b.. 3 6 1 2 3 4 5 6 [SeqNo] [FlowId] ... 1 07.. ... 2 9e.. ... 3 3b.. ... 4 cb.. ... 5 5b.. ... 6 4c.. ... 1 3 6 5 42 Nonclustered Index ( 亂序式 ) Clustered Index ( 循序式 ) 3b.. 5b.. cb.. 9e.. cb..
  • 112. 112/129 2016 特別篇 5: 黑暗執行緒案例 如果用一般亂序式 UUID [FlowId] ... ... 07.. ... ... 9e.. ... ... 3b.. ... ... cb.. ... ... 5b.. ... ... 5b.. cb.. 07.. 3b.. 5b.. 9e.. cb.. Clustered Index ( 亂序式 )
  • 113. 113/129 2016 特別篇 5: 黑暗執行緒案例 尋找【 WHERE FlowId = “5b..” 】 IO 次數: 0 [FlowId] ... ... 07.. ... ... 9e.. ... ... 3b.. ... ... cb.. ... ... 5b.. ... ... 5b.. cb.. 07.. 3b.. 5b.. 9e.. cb.. Clustered Index ( 亂序式 )
  • 114. 114/129 2016 特別篇 5: 黑暗執行緒案例 尋找【 WHERE FlowId = “5b..” 】 IO 次數: 1 [FlowId] ... ... 07.. ... ... 9e.. ... ... 3b.. ... ... cb.. ... ... 5b.. ... ... 5b.. cb.. 07.. 3b.. 5b.. 9e.. cb.. Clustered Index ( 亂序式 )
  • 115. 115/129 2016 特別篇 5: 黑暗執行緒案例 尋找【 WHERE FlowId = “5b..” 】 IO 次數: 2 ( 完成 ) [FlowId] ... ... 07.. ... ... 9e.. ... ... 3b.. ... ... cb.. ... ... 5b.. ... ... 5b.. cb.. 07.. 3b.. 5b.. 9e.. cb.. Clustered Index ( 亂序式 )
  • 116. 116/129 2016 特別篇 5: 黑暗執行緒案例 新增【 FlowID: 4c.. 】 IO 次數: 0 [FlowId] ... ... 07.. ... ... 9e.. ... ... 3b.. ... ... cb.. ... ... 5b.. ... ... 4c.. ... ... 5b.. cb.. 07.. 3b.. 5b.. 9e.. cb.. Clustered Index ( 亂序式 )
  • 117. 117/129 2016 特別篇 5: 黑暗執行緒案例 新增【 FlowID: 4c.. 】 IO 次數: 1 [FlowId] ... ... 07.. ... ... 9e.. ... ... 3b.. ... ... cb.. ... ... 5b.. ... ... 4c.. ... ... 5b.. cb.. 07.. 3b.. 5b.. 9e.. cb.. Clustered Index ( 亂序式 )
  • 118. 118/129 2016 特別篇 5: 黑暗執行緒案例 新增【 FlowID: 4c.. 】 IO 次數: 2 [FlowId] ... ... 07.. ... ... 9e.. ... ... 3b.. ... ... cb.. ... ... 5b.. ... ... 4c.. ... ... 5b.. cb.. 07.. 3b.. 5b.. 9e.. cb.. Clustered Index ( 亂序式 )
  • 119. 119/129 2016 特別篇 5: 黑暗執行緒案例 新增【 FlowID: 4c.. 】 IO 次數: 3+3 ( 完成 ) Page Split 次數: 1 [FlowId] ... ... 07.. ... ... 9e.. ... ... 3b.. ... ... cb.. ... ... 5b.. ... ... 4c.. ... ... 3b.. 5b.. cb.. 07.. 3b.. 4c.. 5b.. Clustered Index ( 亂序式 ) 9e.. cb..
  • 120. 120/129 2016 特別篇 5: 黑暗執行緒案例 如果用一般循序式 UUID [FlowId] ... ... 1 ... ... 2 ... ... 3 ... ... 4 ... ... 5 ... ... 3 5 1 2 3 4 5 Clustered Index ( 循序式 )
  • 121. 121/129 2016 特別篇 5: 黑暗執行緒案例 尋找【 WHERE FlowId = 5 】 IO 次數: 0 [FlowId] ... ... 1 ... ... 2 ... ... 3 ... ... 4 ... ... 5 ... ... 3 5 1 2 3 4 5 Clustered Index ( 循序式 )
  • 122. 122/129 2016 特別篇 5: 黑暗執行緒案例 尋找【 WHERE FlowId = 5 】 IO 次數: 1 [FlowId] ... ... 1 ... ... 2 ... ... 3 ... ... 4 ... ... 5 ... ... 3 5 1 2 3 4 5 Clustered Index ( 循序式 )
  • 123. 123/129 2016 特別篇 5: 黑暗執行緒案例 尋找【 WHERE FlowId = 5 】 IO 次數: 2 ( 完成 ) [FlowId] ... ... 1 ... ... 2 ... ... 3 ... ... 4 ... ... 5 ... ... 3 5 1 2 3 4 5 Clustered Index ( 循序式 )
  • 124. 124/129 2016 特別篇 5: 黑暗執行緒案例 新增【 FlowID: 6 】 IO 次數: 0 [FlowId] ... ... 1 ... ... 2 ... ... 3 ... ... 4 ... ... 5 ... ... 6 ... ... 3 5 1 2 3 4 5 Clustered Index ( 循序式 )
  • 125. 125/129 2016 特別篇 5: 黑暗執行緒案例 新增【 FlowID: 6 】 IO 次數: 1 [FlowId] ... ... 1 ... ... 2 ... ... 3 ... ... 4 ... ... 5 ... ... 6 ... ... 3 5 1 2 3 4 5 Clustered Index ( 循序式 )
  • 126. 126/129 2016 特別篇 5: 黑暗執行緒案例 新增【 FlowID: 6 】 IO 次數: 2 [FlowId] ... ... 1 ... ... 2 ... ... 3 ... ... 4 ... ... 5 ... ... 6 ... ... 3 5 1 2 3 4 5 Clustered Index ( 循序式 )
  • 127. 127/129 2016 特別篇 5: 黑暗執行緒案例 新增【 FlowID: 6 】 IO 次數: 3+1 ( 完成 ) [FlowId] ... ... 1 ... ... 2 ... ... 3 ... ... 4 ... ... 5 ... ... 6 ... ... 3 6 1 2 3 4 5 6 Clustered Index ( 循序式 )
  • 128. 128/129 2016 特別篇 5: 黑暗執行緒案例 小結:本場景為例 黑暗執行緒 亂序式 UUID 循序式 UUID Point-of-query IO 4 2 2 Insert IO 10 6 4 Insert (Page Split) 1 1 0 Space size ++ + + Latch(%) ++ + +
  • 129. 129/129 2016 特別篇 6: MultiColumn B-Tree Index [Col#1] [Col#2] 1 A 3 B 3 C 4 D 3 C CREATE INDEX ON table (Col#1, Col#2); 1 A 3 B 3 C 4 D