怎么理解MYSQL数据类型存储中数值型

网友投稿 341 2023-12-24

怎么理解MYSQL数据类型存储中数值型

怎么理解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

(这里为什么要这样算,详见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 --> 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 --> 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 --> 10000000 00111011 10011010 11001001 11111111

ROW2: 81 00 00 00 00 --> 10000001 00000000 00000000 00000000 00000000

ROW2: 82 08 ca 6c 00 --> 10000010 00001000 11001010 01101100 00000000

试着用原来的方法将数据进行转换:

ROW1: select conv(000000000111011100110101100100111111111,2,10) ;

--> 999999999 正确

ROW2: select conv(000000100000000000000000000000000000000,2,10) ;

--> 4294967296 与原值不符

ROW3: select conv(000001000001000110010100110110000000000,2,10) ;

--&gt 8737418240 与原值不符

其实,正如上面所说的,如果数值超过999999999,那么需要按CHUNK(4个字节)来读取,并在最后将数拼起来.

比如我们读第三行数据:

从右到左读:

1)先读4个字节:00001000 11001010 01101100 00000000 --> 147483648

2)再读剩余的1个字节:0000010 --> 2

把以上两个结果拼起来: "2" || "147483648" = "2147483648" 这里才与原值相符

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注行业资讯频道,感谢您对的支持。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:如何进行MySQL优化WHERE子句
下一篇:如何理解MySQL的转义字符
相关文章

 发表评论

暂时没有评论,来抢沙发吧~