婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > MySQL Innodb 存儲結構 和 存儲Null值 用法詳解

MySQL Innodb 存儲結構 和 存儲Null值 用法詳解

熱門標簽:地圖標注客戶付款 咸陽防封電銷卡 宜賓全自動外呼系統廠家 新鄉智能外呼系統好處 臨沂做地圖標注 石家莊400電話辦理公司 許昌外呼增值業務線路 廣東400企業電話申請流程 申請400電話電話價格

背景:

表空間:INNODB 所有數據都存在表空間當中(共享表空間),要是開啟innodb_file_per_table,則每張表的數據會存到單獨的一個表空間內(獨享表空間)。
獨享表空間包括:數據,索引,插入緩存,數據字典。共享表空間包括:Undo信息(不會回收物理空間上>),雙寫緩存信息,事務信息等。
段(segment):組成表空間,有區組成。
區(extent):有64個連續的頁組成。每個頁16K,總共1M。對于大的數據段,每次最后可申請4個區。
頁(page):是INNODB 磁盤管理的單位,有行組成。
行(row):包括事務ID,回滾指針,列信息等。

目的1:
了解表空間各個頁的信息和溢出行數據存儲的信息。通過該書作者蔣承堯編寫的工具:http://code.google.com/p/david-mysql-tools/source/browse/trunk/py_innodb_page_type/
3個腳本:

py_innodb_page_info.py

View Code 

#! /usr/bin/env python 
#encoding=utf-8
import mylib
from sys import argv
from mylib import myargv

if __name__ == '__main__':
 myargv = myargv(argv)
 if myargv.parse_cmdline() == 0:
  pass
 else:
  mylib.get_innodb_page_type(myargv)

mylib.py

View Code 

encoding=utf-8
import os
import include
from include import *

TABLESPACE_NAME='D:\\mysql_data\\test\\t.ibd'
VARIABLE_FIELD_COUNT = 1
NULL_FIELD_COUNT = 0

class myargv(object):
 def __init__(self, argv):
  self.argv = argv
  self.parms = {}
  self.tablespace = ''

 def parse_cmdline(self):
  argv = self.argv
  if len(argv) == 1:
   print 'Usage: python py_innodb_page_info.py [OPTIONS] tablespace_file'
   print 'For more options, use python py_innodb_page_info.py -h'
   return 0
  while argv:
   if argv[0][0] == '-':
    if argv[0][1] == 'h':
     self.parms[argv[0]] = ''
     argv = argv[1:]
     break
    if argv[0][1] == 'v':
     self.parms[argv[0]] = ''
     argv = argv[1:]
    else:
     self.parms[argv[0]] = argv[1]
     argv = argv[2:]
   else:
    self.tablespace = argv[0]
    argv = argv[1:]
  if self.parms.has_key('-h'):
   print 'Get InnoDB Page Info'
   print 'Usage: python py_innodb_page_info.py [OPTIONS] tablespace_file\n'
   print 'The following options may be given as the first argument:'
   print '-h  help '
   print '-o output put the result to file'
   print '-t number thread to anayle the tablespace file'
   print '-v  verbose mode'
   return 0
  return 1

def mach_read_from_n(page,start_offset,length):
 ret = page[start_offset:start_offset+length]
 return ret.encode('hex')

def get_innodb_page_type(myargv):
 f=file(myargv.tablespace,'rb')
 fsize = os.path.getsize(f.name)/INNODB_PAGE_SIZE
 ret = {}
 for i in range(fsize):
  page = f.read(INNODB_PAGE_SIZE)
  page_offset = mach_read_from_n(page,FIL_PAGE_OFFSET,4)
  page_type = mach_read_from_n(page,FIL_PAGE_TYPE,2)
  if myargv.parms.has_key('-v'):
   if page_type == '45bf':
    page_level = mach_read_from_n(page,FIL_PAGE_DATA+PAGE_LEVEL,2)
    print "page offset %s, page type %s>, page level %s>"%(page_offset,innodb_page_type[page_type],page_level)
   else:
    print "page offset %s, page type %s>"%(page_offset,innodb_page_type[page_type])
  if not ret.has_key(page_type):
   ret[page_type] = 1
  else:
   ret[page_type] = ret[page_type] + 1
 print "Total number of page: %d:"%fsize
 for type in ret:
  print "%s: %s"%(innodb_page_type[type],ret[type])

include.py

View Code 

#encoding=utf-8
INNODB_PAGE_SIZE = 16*1024*1024

# Start of the data on the page
FIL_PAGE_DATA = 38


FIL_PAGE_OFFSET = 4 # page offset inside space
FIL_PAGE_TYPE = 24 # File page type

# Types of an undo log segment */
TRX_UNDO_INSERT = 1
TRX_UNDO_UPDATE = 2

# On a page of any file segment, data may be put starting from this offset
FSEG_PAGE_DATA = FIL_PAGE_DATA

# The offset of the undo log page header on pages of the undo log
TRX_UNDO_PAGE_HDR = FSEG_PAGE_DATA

PAGE_LEVEL = 26 #level of the node in an index tree; the leaf level is the level 0 */

innodb_page_type={
 '0000':u'Freshly Allocated Page',
 '0002':u'Undo Log Page',
 '0003':u'File Segment inode',
 '0004':u'Insert Buffer Free List',
 '0005':u'Insert Buffer Bitmap',
 '0006':u'System Page',
 '0007':u'Transaction system Page',
 '0008':u'File Space Header',
 '0009':u'擴展描述頁',
 '000a':u'Uncompressed BLOB Page',
 '000b':u'1st compressed BLOB Page',
 '000c':u'Subsequent compressed BLOB Page',
 '45bf':u'B-tree Node'
 }

innodb_page_direction={
 '0000': 'Unknown(0x0000)',
 '0001': 'Page Left',
 '0002': 'Page Right',
 '0003': 'Page Same Rec',
 '0004': 'Page Same Page',
 '0005': 'Page No Direction',
 'ffff': 'Unkown2(0xffff)'
}


INNODB_PAGE_SIZE=1024*16 # InnoDB Page 16K

測試1:

root@localhost : test 02:26:13>create table tt(id int auto_increment,name varchar(10),age int,address varchar(20),primary key (id))engine=innodb;
Query OK, 0 rows affected (0.17 sec)
root@zhoujy:/var/lib/mysql/test# ls -lh tt.ibd 
-rw-rw---- 1 mysql mysql 96K 2012-10-17 14:26 tt.ibd

查看ibd:

root@zhoujy:/home/zhoujy/jiaoben/read_ibd# python py_innodb_page_info.py /var/lib/mysql/test/tt.ibd -v
page offset 00000000, page type File Space Header>
page offset 00000001, page type Insert Buffer Bitmap>
page offset 00000002, page type File Segment inode>
page offset 00000003, page type B-tree Node>, page level 0000> ---葉子節點
page offset 00000000, page type Freshly Allocated Page>
page offset 00000000, page type Freshly Allocated Page>
Total number of page: 6: 
Freshly Allocated Page: 2
Insert Buffer Bitmap: 1
File Space Header: 1
B-tree Node: 1
File Segment inode: 1

解釋:
Total number of page: 總頁數
Freshly Allocated Page:可用頁
Insert Buffer Bitmap:插入緩存位圖頁
Insert Buffer Free List:插入緩存空閑列表頁
B-tree Node:數據頁
Uncompressed BLOB Page:二進制大對象頁,存放溢出行的頁,即溢出頁
上面得到的信息是表初始化大小為96K,他是有 Total number of page * 16 得來的。1個數據頁,2個可用頁面。

root@localhost : test 02:42:58>insert into tt values(name,age,address) values('aaa',23,'HZZZ');

疑惑:為什么沒有申請區?區是64個連續的頁,大小1M。那么表大小也應該是至少1M。但是現在只有96K(默認)。原因是因為每個段開始的時候,先有32個頁大小的碎片頁存放數據,使用
完之后才是64頁的連續申請,最多每次可以申請4個區,保證數據的順序。這里看出表大小增加是按照至少64頁的大小的空間來增加的,即1M增加。
驗證:
填充數據,寫滿這32個碎片頁,32*16 = 512K。看看是否能申請大于1M的空間。

View Code 

root@zhoujy:/home/zhoujy/jiaoben/read_ibd# ls -lh /var/lib/mysql/test/tt.ibd 
-rw-rw---- 1 mysql mysql 576K 2012-10-17 15:30 /var/lib/mysql/test/tt.ibd
root@zhoujy:/home/zhoujy/jiaoben/read_ibd# python py_innodb_page_info.py /var/lib/mysql/test/tt.ibd -v
page offset 00000000, page type File Space Header>
page offset 00000001, page type Insert Buffer Bitmap>
page offset 00000002, page type File Segment inode>
page offset 00000003, page type B-tree Node>, page level 0001>
page offset 00000004, page type B-tree Node>, page level 0000>
page offset 00000005, page type B-tree Node>, page level 0000>
page offset 00000006, page type B-tree Node>, page level 0000>
page offset 00000007, page type B-tree Node>, page level 0000>
page offset 00000008, page type B-tree Node>, page level 0000>
page offset 00000009, page type B-tree Node>, page level 0000>
page offset 0000000a, page type B-tree Node>, page level 0000>
page offset 0000000b, page type B-tree Node>, page level 0000>
page offset 0000000c, page type B-tree Node>, page level 0000>
page offset 0000000d, page type B-tree Node>, page level 0000>
page offset 0000000e, page type B-tree Node>, page level 0000>
page offset 0000000f, page type B-tree Node>, page level 0000>
page offset 00000010, page type B-tree Node>, page level 0000>
page offset 00000011, page type B-tree Node>, page level 0000>
page offset 00000012, page type B-tree Node>, page level 0000>
page offset 00000013, page type B-tree Node>, page level 0000>
page offset 00000014, page type B-tree Node>, page level 0000>
page offset 00000015, page type B-tree Node>, page level 0000>
page offset 00000016, page type B-tree Node>, page level 0000>
page offset 00000017, page type B-tree Node>, page level 0000>
page offset 00000018, page type B-tree Node>, page level 0000>
page offset 00000019, page type B-tree Node>, page level 0000>
page offset 0000001a, page type B-tree Node>, page level 0000>
page offset 0000001b, page type B-tree Node>, page level 0000>
page offset 0000001c, page type B-tree Node>, page level 0000>
page offset 0000001d, page type B-tree Node>, page level 0000>
page offset 0000001e, page type B-tree Node>, page level 0000>
page offset 0000001f, page type B-tree Node>, page level 0000>
page offset 00000020, page type B-tree Node>, page level 0000>
page offset 00000021, page type B-tree Node>, page level 0000>
page offset 00000022, page type B-tree Node>, page level 0000>
page offset 00000023, page type B-tree Node>, page level 0000>
Total number of page: 36:
Insert Buffer Bitmap: 1
File Space Header: 1
B-tree Node: 33
File Segment inode: 1

"額外"頁:4個
page offset 00000000, page type File Space Header> :文件頭空間頁
page offset 00000001, page type Insert Buffer Bitmap>:插入緩存位圖頁
page offset 00000002, page type File Segment inode>:文件段節點
page offset 00000003, page type B-tree Node>, page level 0001>:根頁
碎片頁:32個
page type B-tree Node>, page level 0000>
總共36個頁,ibd大小 576K的由來:32*16=512K(碎片頁)+ 4*16=64(額外頁),這里開始要是再插入的話,應該申請最少1M的頁:

root@zhoujy:/home/zhoujy/jiaoben/read_ibd# ls -lh /var/lib/mysql/test/tt.ibd 
-rw-rw---- 1 mysql mysql 2.0M 2012-10-17 16:10 /var/lib/mysql/test/tt.ibd
root@zhoujy:/home/zhoujy/jiaoben/read_ibd# python py_innodb_page_info.py /var/lib/mysql/test/tt.ibd
Total number of page: 128:
Freshly Allocated Page: 91
Insert Buffer Bitmap: 1
File Space Header: 1
B-tree Node: 34
File Segment inode: 1

頁從36跳到了128,因為已經用完了32個碎片頁,新的頁會采用區的方式進行空間申請。信息中看到有很多可用頁,正好說明這點。

▲溢出行數據存放:INNODB存儲引擎是索引組織的,即每頁中至少有兩行記錄,因此如果頁中只能存放一行記錄,INNODB會自動將行數據放到溢出頁中。當發生溢出行的時候,實際數據保存在BLOB頁中,數據頁只保存數據的前768字節(老的文件格式),新的文件格式(Barracuda)采用完全行溢出的方式,數據頁只保存20個字節的指針,BLOB也保存所有數據。如何查看表中有溢出行數據呢?

root@localhost : test 04:52:34>create table t1 (id int,name varchar(10),memo varchar(8000))engine =innodb default charset utf8;
Query OK, 0 rows affected (0.16 sec)

root@localhost : test 04:53:10>insert into t1 values(1,'zjy',repeat('我',8000));
Query OK, 1 row affected (0.00 sec)

查看ibd:

root@zhoujy:/home/zhoujy/jiaoben/read_ibd# python py_innodb_page_info.py /var/lib/mysql/test/t1.ibd -v
page offset 00000000, page type File Space Header>
page offset 00000001, page type Insert Buffer Bitmap>
page offset 00000002, page type File Segment inode>
page offset 00000003, page type B-tree Node>, page level 0000>
page offset 00000004, page type Uncompressed BLOB Page>
page offset 00000005, page type Uncompressed BLOB Page>
Total number of page: 6:
Insert Buffer Bitmap: 1
Uncompressed BLOB Page: 2
File Space Header: 1
B-tree Node: 1
File Segment inode: 1

從信息中看到,剛才插入的一行記錄,已經溢出了,保存到了2個BLOB頁中(Uncompressed BLOB Page>)。因為1頁只有16K,又要存2行數據,所以每行記錄最好小于8K,而上面的遠遠大于8K,所以被溢出了。當然這個也不是包括特大字段,要是一張表里面有5個字段都是varchar(512)【多個varchar的總和大于8K就可以】,也會溢出:

root@localhost : test 05:08:39>create table t2 (id int,name varchar(1000),address varchar(512),company varchar(200),xx varchar(512),memo varchar(512),dem varchar(1000))engine =innodb default charset utf8;
Query OK, 0 rows affected (0.17 sec)
root@localhost : test 05:08:43>insert into t2 values(1,repeat('周',1000),repeat('我',500),repeat('丁',500),repeat('啊',500),repeat('噢',500),repeat('阿a',500));

1000+500+500+500+500+500=3500*3>8000字節;行會被溢出:

root@zhoujy:/home/zhoujy/jiaoben/read_ibd# python py_innodb_page_info.py /var/lib/mysql/test/t2.ibd -v
page offset 00000000, page type File Space Header>
page offset 00000001, page type Insert Buffer Bitmap>
page offset 00000002, page type File Segment inode>
page offset 00000003, page type B-tree Node>, page level 0000>
page offset 00000004, page type Uncompressed BLOB Page>
page offset 00000000, page type Freshly Allocated Page>
Total number of page: 6:
Insert Buffer Bitmap: 1
Freshly Allocated Page: 1
File Segment inode: 1
B-tree Node: 1
File Space Header: 1
Uncompressed BLOB Page: 1

Uncompressed BLOB Page> 頁存放真正的數據,那數據頁到底存放什么?用hexdump查看:

root@zhoujy:/home/zhoujy/jiaoben/read_ibd# hexdump -C -v /var/lib/mysql/test/t1.ibd > t1.txt

查看ibd:

View Code 

3082 0000c090 00 32 01 10 80 00 00 01 7a 6a 79 e6 88 91 e6 88 |.2......zjy.....|
3083 0000c0a0 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 |................|
3084 0000c0b0 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 |................|
3085 0000c0c0 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 |................|
3086 0000c0d0 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 |................|
3087 0000c0e0 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 |................|
3088 0000c0f0 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 |................|
3089 0000c100 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 |................|
3090 0000c110 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 |................|
3091 0000c120 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 |................|
3092 0000c130 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 |................|
3093 0000c140 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 |................|
3094 0000c150 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 |................|
3095 0000c160 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 |................|
3096 0000c170 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 |................|
3097 0000c180 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 |................|
3098 0000c190 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 |................|
3099 0000c1a0 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 |................|
3100 0000c1b0 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 |................|
3101 0000c1c0 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 |................|
3102 0000c1d0 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 |................|
3103 0000c1e0 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 |................|
3104 0000c1f0 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 |................|
3105 0000c200 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 |................|
3106 0000c210 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 |................|
3107 0000c220 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 |................|
3108 0000c230 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 |................|
3109 0000c240 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 |................|
3110 0000c250 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 |................|
3111 0000c260 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 |................|
3112 0000c270 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 |................|
3113 0000c280 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 |................|
3114 0000c290 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 |................|
3115 0000c2a0 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 |................|
3116 0000c2b0 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 |................|
3117 0000c2c0 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 |................|
3118 0000c2d0 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 |................|
3119 0000c2e0 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 |................|
3120 0000c2f0 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 |................|
3121 0000c300 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 |................|
3122 0000c310 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 |................|
3123 0000c320 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 |................|
3124 0000c330 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 |................|
3125 0000c340 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 |................|
3126 0000c350 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 |................|
3127 0000c360 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 |................|
3128 0000c370 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 |................|
3129 0000c380 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 88 91 e6 |................|
3130 0000c390 88 91 e6 88 91 e6 88 91 e6 88 91 00 00 02 1c 00 |................|

文本中剛好是48行,每行16字節。48*16=768字節,剛好驗證了之前說的:數據頁只保存數據的前768字節(老的文件格式)。

總結1:
通過上面的信息,可以能清楚的知道ibd表空間各個頁的分布和利用信息以及表空間大小增加的步長;特別注意的是溢出行,一個頁中至少包含2行數據,如果頁中存放的行數越多,性能就越好。

************************************
************************************

目的2:
了解表空間如何存儲數據,以及對NULL值的存儲。

測試2:
在測試前先了解INNODB的存儲格式(row_format)。老格式(Antelope):Compact默認>,Redumdant;新格式(Barracuda):Compressed,Dynamic。
這里測試指針對默認的存儲格式。
Compact行記錄方式如下:

 |變長字段長度列表(1~2字節)|NULL標志位(1字節)|記錄頭信息(5字節)|RowID(6字節)|事務ID(6字節)|回滾指針(7字節)|

上面信息除了 "NULL標志位"[表中所有字段都定義為NOT NULL],"RowID"[表中有主鍵] ,"變長字段長度列表" [沒有變長字段] 可能不存在外,其他信息都會出現。所以一行數據除了列數據所占用的字段外,還需要額外18字節。

一:字段全NULL

mysql> create table mytest(t1 varchar(10),t2 varchar(10),t3 varchar(10) ,t4 varchar(10))engine=innodb charset = latin1 row_format=compact;
Query OK, 0 rows affected (0.08 sec)

mysql> insert into mytest values('a','bb','bb','ccc');
Query OK, 1 row affected (0.02 sec)

mysql> insert into mytest values('a','ee','ee','fff');
Query OK, 1 row affected (0.01 sec)

mysql> insert into mytest values('a',NULL,NULL,'fff');
Query OK, 1 row affected (0.00 sec)

測試數據準備完之后,執行shell命令:

root@zhoujy:/usr/local/mysql/test# hexdump -C -v mytest.ibd > /home/zhoujy/mytest.txt

打開mytest.txt文件找到supremum這一行:

0000c070 73 75 70 72 65 6d 75 6d 03 02 02 01 00 00 00 10 |supremum........| ----------->一行,16字節
0000c080 00 25 00 00 00 03 b9 00 00 00 00 02 49 01 82 00 |.%..........I...|
0000c090 00 01 4a 01 10 61 62 62 62 62 63 63 63 03 02 02 |..J..abbbbccc...|
0000c0a0 01 00 00 00 18 00 23 00 00 00 03 b9 01 00 00 00 |......#.........|
0000c0b0 02 49 02 83 00 00 01 4b 01 10 61 65 65 65 65 66 |.I.....K..aeeeef|
0000c0c0 66 66 03 01 06 00 00 20 ff a6 00 00 00 03 b9 02 |ff..... ........|
0000c0d0 00 00 00 02 49 03 84 00 00 01 4c 01 10 61 66 66 |....I.....L..aff|
0000c0e0 66 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |f...............|

解釋:
第一行數據:
03 02 02 01/*變長字段*/ ---- 表中4個字段類型為varchar,并且沒有NULL數據,而且每個字段君小于255。
00 /*NULL標志位,第一行沒有null的數據*/
00 00 10 00 25 /*記錄頭信息,固定5個字節*/
00 00 00 03 b9 00/*RowID,固定6個字節,表沒有主鍵*/
00 00 00 02 49 01 /*事務ID,固定6個字節*/
82 00 00 01 4a 01 10 /*回滾指針,固定7個字節*/
61 62 62 62 62 63 63 63/*列的數據*/
第二行數據和第一行數據一樣(顏色匹配)。
第三行數據(有NULL值)和第一行的解釋的顏色對應起來比較差別:

03 02 02 01 VS 03 01 ----------當值為NULL時,變長字段列表不會占用存儲空間。
61 62 62 62 62 63 63 63 VS 61 66 66 66 --------- NULL值沒有存儲,不占空間

結論:當值為NULL時,變長字段列表不會占用存儲空間。NULL值沒有存儲,不占空間,但是需要一個標志位(一行一個)。

二:字段全NOT NULL

mysql> create table mytest(t1 varchar(10) NOT NULL,t2 varchar(10) NOT NULL,t3 varchar(10) NOT NULL,t4 varchar(10) NOT NULL)engine=innodb charset = latin1 row_format=compact;
Query OK, 0 rows affected (0.03 sec)

mysql> insert into mytest values('a','bb','bb','ccc');
Query OK, 1 row affected (0.01 sec)

mysql> insert into mytest values('a','ee','ee','fff');
Query OK, 1 row affected (0.01 sec)

mysql> insert into mytest values('a',NULL,NULL,'fff');
ERROR 1048 (23000): Column 't2' cannot be null

步驟和上面一樣,得到的ibd的結果是:

0000c070 73 75 70 72 65 6d 75 6d 03 02 02 01 00 00 10 00 |supremum........|
0000c080 24 00 00 00 03 b9 03 00 00 00 02 49 07 87 00 00 |$..........I....|
0000c090 01 4f 01 10 61 62 62 62 62 63 63 63 03 02 02 01 |.O..abbbbccc....|
0000c0a0 00 00 18 ff cb 00 00 00 03 b9 04 00 00 00 02 49 |...............I|
0000c0b0 08 88 00 00 01 50 01 10 61 65 65 65 65 66 66 66 |.....P..aeeeefff|

和上面比較,發現少了NULL的標志位信息。
結論: NULL值會有額外的空間來存儲,即每行1字節的大小。對于相同數據的表,字段中有NULL值的表比NOT NULL的大。

三:1個NULL,和1個''的數據:

mysql> create table mytest(t1 varchar(10) NOT NULL,t2 varchar(10) NOT NULL DEFAULT '',t3 varchar(10) NOT NULL ,t4 varchar(10))engine=innodb charset = latin1 row_format=compact;
Query OK, 0 rows affected (0.02 sec)
mysql> insert into mytest(t1,t2) values('A','BB');
Query OK, 1 row affected, 1 warning (0.01 sec)

步驟和上面一樣,得到的ibd的結果是:

0000c070 73 75 70 72 65 6d 75 6d 00 02 01 01 00 00 10 ff |supremum........|
0000c080 ef 00 00 00 43 b9 03 00 00 00 02 4a 15 90 00 00 |....C......J....|
0000c090 01 c2 01 10 41 42 42 00 00 00 00 00 00 00 00 00 |....ABB.........|

和上面2個區別主要在于變長列表和列數據這里。

結論:列數據信息里表明了 NULL數據和''數據都不占用任何空間,對于變長字段列表的信息,和一對比得出:‘'數據雖然不需要占用任何存儲空間,但是在變長字段列表里面還是需要占用一個字節畢竟還是一個‘'值>,NULL值不需要占用”,只是NULL會有額外的一個標志位,所以能有個優化的說法:“數據庫表中能設置NOT NULL的就盡量設置為NOT NULL,除非確實需要NULL值得。” 在此得到了證明。

上面的測試都是針對VARCHAR的變長類型,那對于CHAR呢?

CHAR 測試:

root@localhost : test 10:33:35>create table mytest(t1 char(10),t2 char(10),t3 char(10) ,t4 char(10))engine=innodb charset = latin1 row_format=compact;Query OK, 0 rows affected (0.16 sec)

root@localhost : test 10:33:59>insert into mytest values('a','bb','bb','ccc');
Query OK, 1 row affected (0.00 sec)

root@localhost : test 10:34:09>insert into mytest values('a','ee','ee','fff');
Query OK, 1 row affected (0.00 sec)

root@localhost : test 10:34:19>insert into mytest values('a',NULL,NULL,'fff');
Query OK, 1 row affected (0.00 sec)

打開ibd生成的文件:

0000c060 02 00 1b 69 6e 66 69 6d 75 6d 00 04 00 0b 00 00 |...infimum......|
0000c070 73 75 70 72 65 6d 75 6d 00 00 00 10 00 41 00 00 |supremum.....A..|
0000c080 00 0a f5 00 00 00 00 81 2d 07 80 00 00 00 32 01 |........-.....2.|
0000c090 10 61 20 20 20 20 20 20 20 20 20 62 62 20 20 20 |.a   bb |
0000c0a0 20 20 20 20 20 62 62 20 20 20 20 20 20 20 20 63 |  bb  c|
0000c0b0 63 63 20 20 20 20 20 20 20 00 00 00 18 00 41 00 |cc  .....A.|
0000c0c0 00 00 0a f5 01 00 00 00 81 2d 08 80 00 00 00 32 |.........-.....2|
0000c0d0 01 10 61 20 20 20 20 20 20 20 20 20 65 65 20 20 |..a   ee |
0000c0e0 20 20 20 20 20 20 65 65 20 20 20 20 20 20 20 20 |  ee  |
0000c0f0 66 66 66 20 20 20 20 20 20 20 06 00 00 20 ff 70 |fff  ... .p|
0000c100 00 00 00 0a f5 02 00 00 00 81 2d 09 80 00 00 00 |..........-.....|
0000c110 32 01 10 61 20 20 20 20 20 20 20 20 20 66 66 66 |2..a   fff|
0000c120 20 20 20 20 20 20 20 00 00 00 00 00 00 00 00 00 |  .........|

和一的varchar比較發現:少了變長字段列表,但是對于char來講,需要固定長度來存儲的,存不到固定長度,也會被填充滿。如:20;并且NULL值也不需要占用存儲空間。

混合(varchar,char):

root@localhost : test 11:21:48>create table mytest(t1 int,t2 char(10),t3 varchar(10) ,t4 char(10))engine=innodb charset = latin1 row_format=compact;
Query OK, 0 rows affected (0.17 sec)

root@localhost : test 11:21:50>insert into mytest values(1,'a','b','c');
Query OK, 1 row affected (0.00 sec)

root@localhost : test 11:22:06>insert into mytest values(11,'aa','bb','cc');
Query OK, 1 row affected (0.00 sec)

從上面的表結構中看出:
1,變長字段列表長度:1
2,NULL標志位:1
3,記錄頭信息:5
4,RowID:6
5,事務ID:6
6,回滾指針:7

idb的信息:

0000c070 73 75 70 72 65 6d 75 6d 01 00 00 00 10 00 33 00 |supremum......3.| 
0000c080 00 00 0a f5 07 00 00 00 81 2d 1a 80 00 00 00 32 |.........-.....2|
0000c090 01 10 80 00 00 01 61 20 20 20 20 20 20 20 20 20 |......a   |
0000c0a0 62 63 20 20 20 20 20 20 20 20 20 02 00 00 00 18 |bc   .....|
0000c0b0 ff be 00 00 00 0a f5 08 00 00 00 81 2d 1b 80 00 |............-...|
0000c0c0 00 00 32 01 10 80 00 00 0b 61 61 20 20 20 20 20 |..2......aa  |
0000c0d0 20 20 20 62 62 63 63 20 20 20 20 20 20 20 20 00 | bbcc  .|

從上信息得出和之前預料的一樣:因為表中只有一個varchar字段,所以,變長列表長度就只有:01
特別注意的是:各個列數據存儲的信息:t1字段為int 類型,占用4個字節的大小。第一行:80 00 00 01 就是表示 1 數字;第二行:80 00 00 0b 表示了11的數字。[select hex(11) == B ],其他的和上面的例子一樣。

上面都是latin1單字節字符集的說明,那對于多字節字符集的情況怎么樣?

root@localhost : test 11:52:10>create table mytest(id int auto_increment,t2 varchar(10),t3 varchar(10) ,t4 char(10),primary key(id))engine=innodb charset = utf8 row_format=compact;
Query OK, 0 rows affected (0.17 sec)

root@localhost : test 11:52:11>insert into mytest(t2,t3,t4) values('bb','bb','ccc');
Query OK, 1 row affected (0.00 sec)

root@localhost : test 11:55:34>insert into mytest(t2,t3,t4) values('我們','他們','我們的');
Query OK, 1 row affected (0.00 sec)

ibd信息如下:

0000c070 73 75 70 72 65 6d 75 6d 0a 02 02 00 00 00 10 00 |supremum........|
0000c080 28 80 00 00 01 00 00 00 81 2d 27 80 00 00 00 32 |(........-'....2|
0000c090 01 10 62 62 62 62 63 63 63 20 20 20 20 20 20 20 |..bbbbccc  |
0000c0a0 0a 06 06 00 00 00 18 ff c7 80 00 00 02 00 00 00 |................|
0000c0b0 81 2d 28 80 00 00 00 32 01 10 e6 88 91 e4 bb ac |.-(....2........|
0000c0c0 e4 bb 96 e4 bb ac e6 88 91 e4 bb ac e7 9a 84 20 |............... |

因為表有了主鍵,所以ROWID(6字節)不見了。
特別注意的是:變長字段列表是3?表里面的varchar類型的列只有2個啊。經測試得出:在多字節字符集的條件下,char類型被當成可變長度的類型來處理,他們的行存儲基本沒有區別,所以這個就出現變長列表是3了,因為是utf8字符集,占用三個字節。所以一個漢字均占用了一個頁中3個字節的空間(”我們“ :e6 88 91 e4 bb ac)。
數據列的信息:
id列的1值,應該是 80 00 00 01,為什么這個顯示00 32 01 10,而且所有的id都是00 32 01 10。測試發現,id為自增主鍵的時候,id的4個字節長度都是以00 32 01 10 表示。否則和前面一個例子里說的,用select HEX(X) 表示。

總結2:
上面的測試都是基于COMPACT存儲格式的,不管是varchar還是char,NULL值是不需要占用存儲空間的;特別需要注意的是Redumdant的記錄頭信息需要6個固定字節;在多字節字符集的條件下,CHAR和VARCHAR的行存儲基本是沒有區別的。

到此這篇關于MySQL Innodb 存儲結構 和 存儲Null值 用法詳解的文章就介紹到這了,更多相關MySQL Innodb 存儲結構   存儲Null值內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:
  • MySQL InnoDB ReplicaSet(副本集)簡單介紹
  • 詳解MySQL InnoDB存儲引擎的內存管理
  • MySQL Innodb關鍵特性之插入緩沖(insert buffer)
  • MySQL InnoDB 鎖的相關總結
  • 修改MySQL數據庫引擎為InnoDB的操作
  • MySQL創建數據表時設定引擎MyISAM/InnoDB操作
  • MySQL InnoDB表空間加密示例詳解
  • MySQL InnoDB架構的相關總結

標簽:阜新 鷹潭 貴州 鎮江 日照 北京 臺灣 合肥

巨人網絡通訊聲明:本文標題《MySQL Innodb 存儲結構 和 存儲Null值 用法詳解》,本文關鍵詞  MySQL,Innodb,存儲,結構,和,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《MySQL Innodb 存儲結構 和 存儲Null值 用法詳解》相關的同類信息!
  • 本頁收集關于MySQL Innodb 存儲結構 和 存儲Null值 用法詳解的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    中文字幕一区二区三区四区 | 国产精品久久久久影视| 一区二区三区中文字幕精品精品 | 五月婷婷综合激情| 欧美一级理论性理论a| 日韩中文字幕亚洲一区二区va在线| 中文字幕不卡在线观看| 亚洲自拍偷拍欧美| 欧美精品乱码久久久久久按摩 | 天堂资源在线中文精品| 欧美偷拍一区二区| 首页国产丝袜综合| 久久综合精品国产一区二区三区| 国产麻豆精品95视频| 日韩视频免费直播| 成人av动漫网站| 久久精品视频在线免费观看| 免费观看30秒视频久久| 日韩欧美成人激情| 成人a级免费电影| 亚洲精品自拍动漫在线| 6080亚洲精品一区二区| 老司机一区二区| 国产精品美女久久久久久2018 | 奇米四色…亚洲| 久久精品无码一区二区三区| 理论片日本一区| 中文av一区特黄| 成人午夜精品在线| 亚洲一区在线免费观看| 7777女厕盗摄久久久| 国产乱妇无码大片在线观看| 成人免费在线视频| 久久在线观看免费| 欧美在线一二三| 国产麻豆日韩欧美久久| 一本大道久久a久久综合| 天天色图综合网| 最新不卡av在线| 日韩一区二区免费电影| 99这里都是精品| 爽爽淫人综合网网站| 国产精品美女www爽爽爽| 欧美怡红院视频| 卡一卡二国产精品| 国产农村妇女精品| 56国语精品自产拍在线观看| 成人av动漫在线| 国产乱子轮精品视频| 亚洲精品视频在线观看免费| 欧美精品一区二区三区在线播放| 视频一区二区不卡| 亚洲欧美影音先锋| 精品国产一二三区| 日韩一级黄色大片| 欧美日韩一区二区欧美激情| 99精品视频在线观看免费| 国产一区二区在线观看免费| 日本不卡不码高清免费观看| 石原莉奈在线亚洲三区| 亚洲一区二区精品视频| 亚洲天堂网中文字| 日韩美女精品在线| 亚洲欧洲日本在线| 亚洲欧洲韩国日本视频| 国产色产综合产在线视频| 久久久久亚洲蜜桃| 久久久亚洲高清| 国产校园另类小说区| www国产精品av| 亚洲精品在线一区二区| 欧美成人精品3d动漫h| 7777精品伊人久久久大香线蕉最新版| 欧美日韩精品久久久| 91精品国产综合久久久久久久| 欧美理论在线播放| 精品粉嫩aⅴ一区二区三区四区| 免费人成精品欧美精品 | 久久久91精品国产一区二区精品| 精品国产一区二区三区久久久蜜月| 欧美成人乱码一区二区三区| 精品免费国产一区二区三区四区| 日韩一级高清毛片| 久久综合九色综合久久久精品综合| 国产午夜精品在线观看| 久久精品一区八戒影视| 国产精品久99| 亚洲国产精品久久人人爱| 日韩福利电影在线观看| 国产91色综合久久免费分享| 91毛片在线观看| 欧美久久一二三四区| 精品日韩欧美在线| 中文字幕中文字幕在线一区 | 一区二区三区精品| 国产一区二区导航在线播放| 麻豆国产精品官网| 久久不见久久见免费视频7| 国产一区二区三区在线观看免费视频 | 色哟哟在线观看一区二区三区| 日韩avvvv在线播放| 精品亚洲成a人| 成人18视频日本| 欧美群妇大交群的观看方式| 久久久久久久综合狠狠综合| 亚洲欧美视频在线观看视频| 久久九九久精品国产免费直播| 制服.丝袜.亚洲.中文.综合 | 欧美视频一区二区三区| 91精品久久久久久蜜臀| 久久蜜桃av一区二区天堂 | 国产一区 二区| 欧美日韩免费观看一区二区三区| 欧美va亚洲va| 亚洲一区中文日韩| 成人激情小说乱人伦| 日韩欧美一区二区在线视频| 亚洲免费在线视频一区 二区| 爽好久久久欧美精品| 色婷婷一区二区三区四区| 精品国产不卡一区二区三区| 亚洲影视在线播放| 91麻豆视频网站| 国产欧美日韩精品a在线观看| 午夜精品一区二区三区三上悠亚| 337p日本欧洲亚洲大胆色噜噜| 欧美丰满一区二区免费视频| 国产欧美一区二区精品婷婷 | 热久久一区二区| 丰满岳乱妇一区二区三区| 日韩女优电影在线观看| 亚洲大型综合色站| 99综合电影在线视频| 欧美极品aⅴ影院| 国产一区视频在线看| 日韩你懂的在线播放| 偷拍与自拍一区| 在线中文字幕一区二区| 亚洲免费毛片网站| 99热在这里有精品免费| 中文字幕一区三区| av一区二区不卡| 国产精品久久精品日日| 欧美综合色免费| 日韩中文字幕一区二区三区| 亚洲综合激情小说| 色综合久久66| 亚洲一区在线视频观看| 在线亚洲一区观看| 亚洲午夜电影网| 欧美日韩久久久久久| 丝袜美腿亚洲综合| 欧美电影免费提供在线观看| 久久国产婷婷国产香蕉| 26uuu国产电影一区二区| 国产成人8x视频一区二区| 中文字幕亚洲欧美在线不卡| 在线看国产一区| 久久精品国产精品亚洲红杏| 2020国产精品自拍| 福利一区二区在线| 亚洲伦理在线免费看| 91麻豆精品国产综合久久久久久| 99视频国产精品| 国产在线精品视频| 精品理论电影在线观看| 蜜桃视频一区二区| 精品免费视频.| 国产成人精品亚洲777人妖| 国产精品护士白丝一区av| 色综合激情五月| 日本va欧美va瓶| www国产成人| 日本精品一级二级| 日本成人中文字幕| 国产精品美女久久久久久久久久久 | 亚洲免费av网站| 91精品国产综合久久久蜜臀粉嫩| 国产精品一区一区| 亚洲色图20p| 日韩欧美国产三级电影视频| 不卡一卡二卡三乱码免费网站| 一区二区三区在线观看欧美| 色哟哟在线观看一区二区三区| 亚洲第一av色| 久久综合狠狠综合久久激情| 日本高清成人免费播放| 免费看欧美美女黄的网站| 欧美国产精品劲爆| 欧美日韩一区 二区 三区 久久精品| 免费成人av在线播放| **欧美大码日韩| 精品国产一区二区三区av性色| 色综合网色综合| 国产精品主播直播| 亚洲一区在线观看网站| 久久久三级国产网站| 欧美日韩一区中文字幕| 97精品久久久久中文字幕| 精品一区二区日韩|