å¾æ¹äºææ§ã£ã¦è¾ãããã©ããããããã§ãã
æè¿ Rust 㧠SQLite ããã«ã¹ã¯ã©ããã§åå®è£ ãã¦ãã¾ãã
åå®è£ ããããã« SQLite ã®å ¬å¼ããã¥ã¡ã³ããã½ã¼ã¹ã³ã¼ããèªã¿è¾¼ãã§ããããã§ããããã®éç¨ã§æ°ä»ãããããããã¤ã³ããå ±æããããã¨æãã¾ãã
ä»åã¯ãã®ç¬¬äºå¼¾ããã¡ã¤ã«ãã©ã¼ãããç·¨ã§ãã第ä¸å¼¾ã¯ãã¡ãï¼SQLite のおもしろ仕様 (1) : データ型 - kawasin73のブログ
åæç¥è : ãã¼ã¸
ã¾ãããã®è¨äºãé¢ç½ãã¨æã£ã¦ãããããã®åæç¥èã§ãã
大æµã®ãã¼ã¿ãã¼ã¹ã¯ãã¼ã¿ãä¿åãããã¡ã¤ã«ããã¼ã¸ã¨ããåä½ã§ç®¡çãã¾ããSQLite ã§ã¯ããã©ã«ãã§ã¯ 1 ãã¼ã¸ 4096 ãã¤ãã§ããããã¯ããã¡ã¤ã«ãä¿åããããã¤ã¹ï¼HDD ã SSD ãªã©ï¼ã¨ãã¦ãããã¯ããã¤ã¹ãæ³å®ãã¦ããããã§ãããããã¯ããã¤ã¹ã¨ã¯ãã¼ã¿ã®èªã¿æ¸ãããããã¯åä½ã§è¡ãã1 ãã¤ãåä½ã®ã¢ã¯ã»ã¹ãã§ããªãããã¤ã¹ã§ãããããã¯ã®ãµã¤ãºã¯ 512 ãã¤ãã ã£ãããã£ã¨å¤§ããã£ãããã¾ããã2 ã®åªä¹ã®ãµã¤ãºã§ãï¼ä¾å¤ããããã¯ç¥ãã¾ããï¼ã1 ãã¼ã¸ã«ã¯ 1 ã¤ä»¥ä¸ã®ãããã¯ãããã¿ãªåã¾ãã¾ãã
å¤ãã®ãã¼ã¿ãã¼ã¹ã·ã¹ãã ã§ã¯ I/O ã¬ã¤ãã³ã·ã¼ãæ¯é çã«ãªãããããã£ã¹ã¯ã¸ã®ã¢ã¯ã»ã¹ãæé©åããããã«ãã¼ã¸ã®å¢çãè¶ ãããã¼ã¿ã®ä¿åã¯ãã¾ãããå ¨ã¦ã®ãã¼ã¿ã¢ã¯ã»ã¹ã®åä½ã¯ãã¼ã¸å ã«åã¾ãããã«è¨è¨ããã¦ãã¾ãã
å¯å¤é·ã®ãã¼ã¿ã®ä¿åã®ä»æ¹
第ä¸å¼¾ ã§ç´¹ä»ããããã« SQLite ã§ã¯ããããã®ã«ã©ã ã«ã©ã®åã®ãã¼ã¿ãæ¥ããã¯å®éã« INSERT ãããã¾ã§ãããã¾ããããåãã«ã©ã ã§ãå¥ã®è¡ã§ã¯ç°ãªããã¼ã¿åã«ãªããã¨ãããã¾ããã¤ã¾ãããã¼ã¸å ã«ä¿åãããã»ã«ã¯å ¨ã¦å¯å¤é·ã§ãããã®ããã1 ãã¼ã¸ã«ä½åã®ã»ã«ãä¿åã§ãããã¯åçã«æ±ºã¾ãã¾ãã
SQLite ã®ãã©ã¼ãããã§ã¯ã»ã«ããã¼ã¸ã®å¾ããå é ã«åãã£ã¦ä¿åãã¦ãããããããã®ã»ã«ã®å é ã®ãªãã»ãããã»ã«ãã¤ã³ã¿ã¨ãã¦ãã¼ã¸ã®å é ããå¾ãã«åãã£ã¦ä¿åãã¦ããã¾ãã
ã»ã«ãã¤ã³ã¿ã¯ 2 ãã¤ããªã®ã§ãX çªç®ã®ã»ã«ãã¤ã³ã¿ã®ä½ç½®ã¯ä¸æã§ããããããã°ã¨ã³ãã£ã¢ã³ã§ã¨ã³ã³ã¼ããããå¤ãèªã¿åãã°ã»ã«ã®ãªãã»ãããä¸æã§åå¾ãããã¨ãã§ãã¾ãã
ããã»ã«ãµã¤ãº + 2 ãã¤ãã®ä½è£ããã®ãã¼ã¸ã«ãªãå ´åã¯ãã®ãã¼ã¸ã¯æºæ¯ã«ãªã£ãã¨ãã¦å¦çããã¾ãã
ãã®ã·ãªã¢ã©ã¤ãºæ¹æ³ã¯ãå¯å¤é·ã®ãã¼ã¿ããã¡ã¤ã«ã«ä¿åãããã¨ãã¨ãã«å¿ç¨ã§ãããã§ãã
Overflow ã¸ã®å¯¾å¿
SQLite ã¯ã4096 ãã¤ããè¶ ããæååãªã© 1 ãã¼ã¸ã«åã¾ããªããããªå¤§ããªãã¼ã¿ã®ä¿åã«ããã¡ãã対å¿ãã¦ãã¾ããããé¾å¤ãè¶ ãããµã¤ãºã®ãã¼ã¿ã¯ Cell Payload Overflow Pages ã«åå²ãããå é ã®ãã¼ã¿ã®ã¿ãã»ã«ã¨ãã¦ãã¼ãã«ã®ãã¼ã¸ã«ä¿åããã¾ããå¾ç¶ã®ã¯ã¿åºããã¼ã¿ã¯ Cell Payload Overflow Pages ã¨ãã¦é£çµãªã¹ãã®è¦é ã§è¤æ°ãã¼ã¸ã«åå²ãã¦ä¿åããã¾ãã
ãã¦ããã®é¾å¤ã¨ã»ã«ã¨ãã¦ä¿åããããã¤ãæ°ã¯ä»¥ä¸ã®ããã«è¨ç®ããã¾ãã
- X is
U-35
for table btree leaf pages or((U-12)*64/255)-23
for index pages.- M is always
((U-12)*32/255)-23
.- Let K be
M+((P-M)%(U-4))
.- If P<=X then all P bytes of payload are stored directly on the btree page without overflow.
- If P>X and K<=X then the first K bytes of P are stored on the btree page and the remaining P-K bytes are stored on overflow pages.
- If P>X and K>X then the first M bytes of P are stored on the btree page and the remaining P-M bytes are stored on overflow pages.
ãªããã±ã£ã¨è¦ãè¤éã§ããè¤éãªã®ã¯ä½è ãèªèãã¦ããããã§ãããã¥ã¡ã³ãã®ããä¸ã§ã¯å¾æã¨è² ãæãã¿ãè¿°ã¹ããã¦ãã¾ããã
In hindsight, the designer of the SQLite b-tree logic realized that these thresholds could have been made much simpler. However, the computations cannot be changed without resulting in an incompatible file format. And the current computations work well, even if they are a little complex.
(æ¥æ¬èªè¨³): æ¯ãè¿ã£ã¦ã¿ãã¨ãSQLiteã®Bããªã¼ãã¸ãã¯ã®è¨è¨è ã¯ããããã®é¾å¤ããã£ã¨ã·ã³ãã«ã«è¨å®ã§ããã¨æ°ã¥ãã¾ãããããããè¨ç®æ¹æ³ãå¤æ´ããã¨ããã¡ã¤ã«ãã©ã¼ãããã®äºææ§ã失ããããããå¤æ´ã¯ã§ãã¾ãããããã¦ãç¾å¨ã®è¨ç®æ¹æ³ã¯ãå°ã è¤éã§ãã£ã¦ãããã¾ãæ©è½ãã¦ãã¾ãã
å¾æ¹äºææ§ã£ã¦è¾ããã
B æ¨ vs B+ æ¨
B æ¨ã¨ã¯ 1 ã¤ã®ãã¼ãã« 3 ã¤ä»¥ä¸ã®å¤ãä¿åããæ¨æ§é ã§ãããã¼ãããã¼ã¸ã®åä½ã«æãããã¨ãã§ããã®ã§ãã¼ã¿ããããã¯ããã¤ã¹ã«ä¿åãããã¼ã¿ãã¼ã¹ã¨ç¸æ§ãããããã¼ã¿ãã¼ã¹ã§ã¯ãã¼ã¿æ§é ã¨ã㦠B æ¨ããã®æ´¾çããã使ããã¾ãã
B+ æ¨ã¯ B æ¨ã®æ´¾çã®ä¸ç¨®ã§ããB æ¨ã¯ããããã®å¤ãéè¤ããã« 1 ã¤ã®ãã¼ãã ãã«ä¿åããã¦ããä¸æ¹ã§ãB+ æ¨ã¯å ¨ã¦ã®å¤ã¨ãã¼ã®çµãèãã¼ãã®ã¿ã«ä¿åãã¦æ¤ç´¢ã®ããã®ãã¼ãä¸éãã¼ãã«éè¤ãã¦ä¿åããã¦ããã¨ããç¹å¾´ãããã¾ããB+ æ¨ã¯ä¸éãã¼ãã«å¤ãä¿åããªããããããå¤ãã®ãã¼ã¨åãã¼ãã¸ã®ãã¤ã³ã¿ãä¸ã¤ã®ãã¼ãã«ä¿åã§ããæ¨ã®é層ãæ¸ãããã¨ãã§ãã¾ããã¾ããèãã¼ãå士ãç¹ããã¤ã³ã¿ãæã¤ãã¨ã§ç¯å²æ¤ç´¢æã«ã¢ã¯ã»ã¹ãããã¼ã¸æ°ãæ¸ãããã¨ãã§ããã¨ããå©ç¹ããããããã®ã§ãããSQLite ã§ã¯èãã¼ãå士ãç¹ãã¨ãããã¨ã¯ãã¦ãã¾ããã§ããã詳ããã¯èªåã§èª¿ã¹ã¦ã¿ã¦ãã ããã
SQLite ã§ã¯ãã¼ãã«ã« B+ æ¨ããã¤ã³ããã¯ã¹ã« B æ¨ãã¨ä½¿ãåãã¦ãã¾ããåã®æ¨æ¸¬ã§ããã¤ã³ããã¯ã¹ã¯å·¨å¤§ãªãµã¤ãºã®ãã¼ãèãã¼ãã¨ä¸éãã¼ãã«éè¤ãã¦ä¿åããã¨ãã®ç¡é§ã大ãããããã B æ¨ã使ã£ã¦ããã®ã ã¨æãã¾ããä¸æ¹ããã¼ãã«ã®ãã¼ã¯ 64 ãããã®ç¬¦å·ä»æ´æ°ã Varint ã¨ã³ã³ã¼ããããã®ãªã®ã§ 1 ~ 9 ãã¤ãã¨ãµã¤ãºã®ä¸éãååå°ãããä¸éãã¼ãã«éè¤ãã¦ä¿åããã¨ãã®ç¡é§ã¯å°ããæ¸ã¿ã¾ãã
æ¨ã®æ§é ãå¾®å¦ã«éãã®ã§ãSQLite ã®å®è£
ã§ã¯ãã¼ãã«ã¨ã¤ã³ããã¯ã¹ã§ sqlite3BtreeTableMoveto() 㨠sqlite3BtreeIndexMoveto() ã®ããã«å¥ã
ã®é¢æ°ãå®ç¾©ããã¦ãã¾ããä¸æ¹ã§ãã以å¤ã®æä½ (sqlite3BtreeInsert()
, sqlite3BtreeNext()
ãªã©) ã¯å
±éã®é¢æ°ãæä¾ããã¦ãã¾ããå®è£
ãã¦ã¿ãã¨ãããã¾ãããæå¤ã¨å
±éã®æä½ãå¤ãã§ãã
éå»ã®ãã°ã®ä»£å
Freelist ã¯ãã¼ã¿ã®åé¤ãªã©ã§ä½¿ããªããªã£ããã¼ã¸ãåå©ç¨ã®ããã«ãªã¹ãããããã®æ§é ã§ãã
A bug in SQLite versions prior to 3.6.0 (2008-07-16) caused the database to be reported as corrupt if any of the last 6 entries in the freelist trunk page array contained non-zero values. Newer versions of SQLite do not have this problem. However, newer versions of SQLite still avoid using the last six entries in the freelist trunk page array in order that database files created by newer versions of SQLite can be read by older versions of SQLite.
(æ¥æ¬èªè¨³): SQLiteã®3.6.0 (2008-07-16)ããåã®ãã¼ã¸ã§ã³ã§ã¯ãããªã¼ãªã¹ãã®ãã©ã³ã¯ãã¼ã¸é åã®æå¾ã®6ã¨ã³ããªã®ããããã«éã¼ãå¤ãå«ã¾ãã¦ããå ´åããã¼ã¿ãã¼ã¹ãç ´æãã¦ããã¨å ±åããããã°ãããã¾ãããæ°ãããã¼ã¸ã§ã³ã®SQLiteã«ã¯ãã®åé¡ã¯ããã¾ãããããããæ°ãããã¼ã¸ã§ã³ã®SQLiteã¯ãæ°ãããã¼ã¸ã§ã³ã®SQLiteã§ä½æããããã¼ã¿ãã¼ã¹ãã¡ã¤ã«ãå¤ããã¼ã¸ã§ã³ã®SQLiteã§ãèªã¿åããããã«ãããªã¼ãªã¹ãã®ãã©ã³ã¯ãã¼ã¸é åã®æå¾ã®6ã¨ã³ããªã使ç¨ããªãããã«ãã¦ãã¾ãã
3.6.0 ããåã®ãã°ã®ããã« Freelist trunk page ã®æå¾ã®æ¹ã® 24 ãã¤ãã¯æªæ¥æ°¸å«ä½¿ãããªãé åã«ãªã£ã¦ãã¾ãã¾ããã
å¾æ¹äºææ§ã£ã¦è¾ããã
ããã¥ã¡ã³ãããã¦ããªãä»æ§
prsqlite ã¯æ¬å®¶ã® SQLite ã¨äºææ§ãæã¤ãã¨ãç®æ¨ã¨ãã¦ããã®ã§ãããã¥ã¡ã³ãã¯ãã¡ããã§ããæ¬å®¶ã®ã½ã¼ã¹ã³ã¼ããèªã¿ãªããå®è£ ãã¦ãã¾ãã
ããã§ãã©ããã 4 ãã¤ãããå°ããã»ã«ã¯ 4 ãã¤ãã¨ãã¦é åã確ä¿ããã¦ããããããã¨ããããã¾ãããããã¯ããã¥ã¡ã³ãã«ã¯æ¸ããã¦ãããè¡æã§ããã
static int balance_nonroot( // ... while( b.szCell[b.nCell]<4 ){ /* Do not allow any cells smaller than 4 bytes. If a smaller cell ** does exist, pad it with 0x00 bytes. */ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ // ... assert( iSize>=4 ); /* Minimum cell size is 4 */ static int fillInCell( // ... if( n<4 ) n = 4;
åã®æ¨æ¸¬ã§ããã解æ¾ãããã»ã«ã®ãµã¤ãºã 4 ãã¤ãæªæºã ã¨ãã¼ã¸å ã® freeblock list ã«è¿½å ã§ãã "fragmented free bytes" ã¨ãã¦ç¡è¦ããã¦ãã¾ãããããªãã¹ã解æ¾ãããã»ã«ãåå©ç¨ãããããã®æé©åãªã®ã ã¨æãã¾ãããããã3 ãã¤ãæªæºã®ã»ã«ããããã¡ã¤ã«ã SQLite ãå¦çããã¨ã»ã«ã®è§£æ¾æã«å¥ã®ã»ã«é åãç ´å£ãã¦ãã¾ããããããã¯ããã¥ã¡ã³ãããã¹ãä»æ§ãªæ°ããã¾ãã
ä¸æ¹ã§ããã¼ãã«ã¯æä½ 1 ã«ã©ã 以ä¸ãã¤ã³ããã¯ã¹ã¯æä½ 1 ã«ã©ã + rowid ã® 1 integer 以ä¸ã®è¦ç´ ã Record Format ã«ãã£ã¦ãã¤ãã¼ãã«ã·ãªã¢ã©ã¤ãºããããããå ¨ã¦ã®ã»ã«ã¯ 4 ãã¤ã以ä¸ã«ãªãã®ã§ãããbtree cursor èªä½ã¯ Record Format ã¨ã¯ç¬ç«ã§ãããã¨ãSQLite èªèº«ã 3 ãã¤ãã®ã»ã«ã®ãã¹ã ããã¦ãã以ä¸ä»æ§ã£ã½ãã§ãã
æå¾ã«
ãã¡ã¤ã«ãã©ã¼ãããã¯ä¸åº¦ãã¡ã¤ã«ãã¦ã¼ã¶ã¼ã®æå ã§ä½ããã¦ãã¾ãã¨å¾æ¹äºææ§ã常ã«æèããªããæ¡å¼µãã¦ãããªãã¨ãããªãã®ã§ãã¡ã¢ãªã¬ã¤ã¢ã¦ãã¨æ¯ã¹ã¦ããç´ããå¹ããç¹ã«å¤§å¤ã§ãã
ããããå¾æ¹äºææ§ãé¿ããããã«ã¯ãMessagePack ã¨ã Protocol Buffers ã¨ãã®ã·ãªã¢ã©ã¤ãºãã©ã¼ãããã使ãã¨ã SQLite ãªã©ã®çµã¿è¾¼ã¿ãã¼ã¿ãã¼ã¹ã使ãã¨å®å¿ã§ããããããé¨åæ´æ°ããããå ´åã¨ãããããããã¨ã«å¯¾ãã¦çµã¿è¾¼ã¿ãã¼ã¿ãã¼ã¹ã¯è¤éãããå ´åãªã©ã¯ãèªåã§ãã¡ã¤ã«ãã©ã¼ããããèããå¿ è¦ãããï¼ãã£ãï¼ã大å¤ã§ããã¤ã¤ã楽ããã§ããããããã