中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么理解MYSQL數據類型存儲中數值型

發布時間:2021-11-17 09:24:23 來源:億速云 閱讀:152 作者:柒染 欄目:MySQL數據庫

怎么理解MYSQL數據類型存儲中數值型,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

探索MYSQL 數值類型的存儲,以及解讀方法.on Engine of myisam[@more@]1. 環境版本:
OS : LINUX AS4
MYSQL: 5.0.51a-log
ENGINE : Myisam  DEFAULT CHARSET=latin1

2. 本章研究的數值類型對象:

TINYINT 1個字節 FIXED
SMALLINT 2個字節 FIXED
MEDIUMINT 3個字節 FIXED
INT, INTEGER 4個字節 FIXED
BIGINT 8個字節 FIXED
DECIMAL(M,N) >=4字節 FIXED

3. 數值類型: TINYINT SMALLINT MEDIUMINT INT BIGINT

這幾種數據存取方式都是一樣的: 高位優先存儲,符號位(0正,1負)

drop table if exists heyf ;
create table heyf (id TINYINT ) type myisam  DEFAULT CHARSET=latin1;
insert into heyf values (10),(-10) ;
system hexdump /opt/mysql/data/test/heyf.MYD
------------------------------------------
0000000 0afd 0000 0000 fd00 00f6 0000 0000
000000e
------------------------------------------

其中:
ROW1:
--------------------------------
fd : 行header
0a : 值10
---------------------------------

ROW2:
--------------------------------
fd : 行header
f6 : 值-10的補碼
---------------------------------

如果是正數,第1位為"0", 直接讀出來即可;
如果是負數,第1位為"1", 則按常規辦法將值 取反+1.

比如:
原值 原二進制 取反 加1 十進制
-------------------------------------------------------
f6 --&gt 1111 0110 --&gt 0000 1001 --&gt 0000 1010 --&gt 10

其他幾個類型請讀者舉一反三.


4. 數值類型: DECIMAL(M,N) 或 DECIMAL(M)

4.1 存儲位計算
最小分配4個字節空間,比如decimal(4,2),實際用兩個字節就可以表示.但MYSQL在分配空間時還是用了4個字節.空閑部分用0填充
DECIMAL(M,N),如果9<M<17,至需要5~8個以上字節.如果18<M<36,則會需要8~12個字節.
(這里為什么要這樣算,詳見4.2中的實例解釋)

4.2 如何讀取數據.

4.2.1 讀取步驟

按照定義,從磁盤讀出該DECEMAL字段的所有數據(N位)后:

4.2.1.1 正數,帶小數,DECIMAL(4,2)
0)以1開頭,如果定義為UNSIGNED,則都為1
1)去掉第一位符號位,
2)用小數將剩余的位數分開, 前面(M位)是整數部分,后面(N位)是小數部分
(在這一步是怎么分M和N的,我們能根據字段的定義計算出來)
3)去掉小數點后面(整個字節)為0的情況,
4)將二進制轉換成十進制,即可讀出原值.
(注意,小數的讀取方法與整數的方法一樣,按二進制向十進制轉換即可)

4.2.1.2 負數,帶小數 DECIMAL(4,2)
0)以0開頭,
1)去掉第一位符號位,
2)剩余的數取反+1 ,
3)用小數將剩余的位數分開, 前面(M位)是整數部分,后面(N位)是小數部分
(在這一步是怎么分M和N的,我們能根據字段的定義計算出來)
4)去掉小數點后面(整個字節)為0的情況,
5)將二進制轉換成十進制,即可讀出原值.
(注意,小數的讀取方法與整數的方法一樣,按二進制向十進制轉換即可)

4.2.1.3 正數,不帶小數, DECIMAL(N)
0)以1開頭,如果定義為UNSIGNED,則都為1
1)去掉第一位符號位,
2)將剩余的數位直接按二進制向十進制轉換即可

4.2.1.4 負數,不帶小數, DECIMAL(N)
0)以0開頭
1)去掉第一位符號位,
2)將剩余的數取反+1
3)按二進制向十進制轉換即可讀到原值

4.2.1.5 超長數值,如何讀取
當需要表示的數值超過某個限值后,如果你按以上的方法去讀取數據,會發現讀出來的數值是不對的.

資料寫道:
********************************************************************
high byte first, four-byte chunks.
We call the four-byte chunks "*decimal* digits".
Since 2**32 = There is an implied decimal point. Details are in /strings/decimal.c.
Example: a MySQL 5.0 DECIMAL(21,9) column containing 111222333444.555666777
looks like: hexadecimal 80 6f 0d 40 8a 04 21 1e cd 59 -- (flag + '111', '222333444', '555666777').
********************************************************************

但經過測試, 似乎是當數值<=999999999 時,我們還可以用原來的方法去讀取.
一旦數值>999999999,我們就需要按CHUNK(4個字節)來讀取.

詳見4.2章節中的測試實例.


4.2.2 實例驗證

4.2.2.1 帶符號位的DECIMAL(M,N).

Drop table if exists heyf ;
create table heyf (id DECIMAL(4,2) ) type myisam ;
insert into heyf values (65),(-65),(23.34),(-23.34);
system hexdump /opt/mysql/data/test/heyf.MYD
----------------------------------------------
0000000 c1fd 0000 0000 fd00 ff3e 0000 0000 97fd
0000010 0022 0000 fd00 dd68 0000 0000
----------------------------------------------

ROW1: c1 00 00 00 : 1 1000001 00000000 00000000 00000000
ROW2: 3e ff 00 00 : 0 0111100 ffffffff 00000000 00000000
ROW3: 97 22 00 00 : 1 0010111 00100010 00000000 00000000
ROW4: 68 dd 00 00 : 0 1101000 11011101 00000000 00000000
------------------------------------------------------------
磁盤數據 符號 整數 小數 空閑 空閑

我們來看上面的方法進行讀取:
ROW1:
符號位 : 1,正數.
整數部分: 1000001 = 65
小數部分: 0
原值 : 65
ROW2:
符號位 : 0,負數
取反+1 : 1000100 00000000
整數部分: 1000001 = 65
小數部分: 0
原值 : -65
ROW3:
符號位 : 1,正數
整數部分: 0010111 = 23
小數部分: 00100010 = 34
原值 : 23.34
ROW4:
符號位 : 0,負數
取反+1 : 0010111 00100010
整數部分: 0010111 = 23
小數部分: 00100010 = 34
原值 : -23,34

4.2.2.2 不帶符號位的,DECIMAL(M,N)UNSIGNED.

Drop table if exists heyf ;
create table heyf (id DECIMAL(4,2) UNSIGNED ) type myisam ;
insert into heyf values (65),(23.34);
system hexdump /opt/mysql/data/test/heyf.MYD
----------------------------------------------
0000000 c1fd 0000 0000 fd00 2297 0000 0000
000000e
----------------------------------------------

ROW1: c1 00 00 00 : 1 1000001 00000000 00000000 00000000
ROW3: 97 22 00 00 : 1 0010111 00100010 00000000 00000000
------------------------------------------------------------
磁盤數據 符號 整數 小數 空閑 空閑

注意:符號位都為"1".
整數部分和小數部分,該實例與4.2.2.1中實例的取值一樣,在這里不再贅述.


4.2.2.3 帶符號位的, DECIMAL(M)

Drop table if exists heyf ;
create table heyf (id DECIMAL(10)) type myisam ;
insert into heyf values (65),(-65 );
system hexdump /opt/mysql/data/test/heyf.MYD
----------------------------------------------
0000000 80fd 0000 4100 fd00 ff7f ffff 00be
----------------------------------------------

ROW1: 80 00 00 00 41 --&gt 10000000 00000000 00000000 00000000 01000001
ROW2: 7f ff ff ff be --&gt 01111111 11111111 11111111 11111111 10111110

到這里,如果你認真地讀完了4.2.2.1和4.2.2.2小節,那么下面的轉換對你來說將不再是難事了.
正數,去符號位后直接轉換成十進制;
負數,去符號位,剩余取反+1后,轉換成十進制;


4.2.2.4 不帶符號位的DECIMAL(M) UNSIGNED .

Drop table if exists heyf ;
create table heyf (id DECIMAL(10) UNSIGNED ) type myisam ;
insert into heyf values (65),(200000);
system hexdump /opt/mysql/data/test/heyf.MYD
----------------------------------------------
0000000 80fd 0000 4100 fd00 0080 0d03 0040
----------------------------------------------

ROW1: 80 00 00 00 41
ROW2: 80 00 03 0d 40

在這里用了五個字節來表示DECIMAL(10).關于原數值,我想大家應該都能看出來了.
0X41 --&gt 65
0X30d40 --&gt 20000

4.2.2.5 超長數值的讀取(>999999999)

Drop table if exists heyf ;
create table heyf (id DECIMAL(10) UNSIGNED ) type myisam ;
insert into heyf values (999999999),(1000000000),(2147483648);
system hexdump /opt/mysql/data/test/heyf.MYD
----------------------------------------------
0000000 80fd 9a3b ffc9 fd00 0081 0000 0000 82fd
0000010 ca08 006c
----------------------------------------------
ROW1: 80 3b 9a c9 ff --&gt 10000000 00111011 10011010 11001001 11111111
ROW2: 81 00 00 00 00 --&gt 10000001 00000000 00000000 00000000 00000000
ROW2: 82 08 ca 6c 00 --&gt 10000010 00001000 11001010 01101100 00000000

試著用原來的方法將數據進行轉換:
ROW1: select conv(000000000111011100110101100100111111111,2,10) ;
--&gt 999999999 正確
ROW2: select conv(000000100000000000000000000000000000000,2,10) ;
--&gt 4294967296 與原值不符
ROW3: select conv(000001000001000110010100110110000000000,2,10) ;
--&gt 8737418240 與原值不符

其實,正如上面所說的,如果數值超過999999999,那么需要按CHUNK(4個字節)來讀取,并在最后將數拼起來.
比如我們讀第三行數據:
從右到左讀:
1)先讀4個字節:00001000 11001010 01101100 00000000 --&gt 147483648
2)再讀剩余的1個字節:0000010 --&gt 2
把以上兩個結果拼起來: "2" || "147483648" = "2147483648" 這里才與原值相符

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

乌鲁木齐市| 资讯| 绍兴市| 南江县| 迭部县| 东乡| 精河县| 桂林市| 那坡县| 富锦市| 巴林右旗| 仁布县| 永和县| 古丈县| 西贡区| 诸暨市| 开封县| 威远县| 尼木县| SHOW| 芮城县| 武宁县| 莒南县| 阳东县| 石阡县| 平塘县| 白河县| 高邑县| 青海省| 武功县| 彭州市| 沂南县| 广平县| 黑水县| 虞城县| 姜堰市| 察哈| 鹤山市| 兰西县| 盐津县| 奉贤区|