怎么了解MYSQL数据类型存储中数值型
发布时间:2021-12-17 12:41:57 所属栏目:MySql教程 来源:互联网
导读:怎么理解MYSQL数据类型存储中数值型,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。 探索MYSQL 数值类型的存储,以及解读方法.on Engine of myisam[@more@]1. 环境版本: OS
怎么理解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 --> 1111 0110 --> 0000 1001 --> 0000 1010 --> 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中实例的取值一样,在这里不再赘述. ROW1: 80 00 00 00 41 --> 10000000 00000000 00000000 00000000 01000001 ROW2: 7f ff ff ff be --> 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 --> 20000 试着用原来的方法将数据进行转换: ROW1: select conv(000000000111011100110101100100111111111,2,10) ; --> 999999999 正确 ROW2: select conv(000000100000000000000000000000000000000,2,10) ; --> 4294967296 与原值不符 ROW3: select conv(000001000001000110010100110110000000000,2,10) ; --> 8737418240 与原值不符 其实,正如上面所说的,如果数值超过999999999,那么需要按CHUNK(4个字节)来读取,并在最后将数拼起来. 比如我们读第三行数据: 从右到左读: 1)先读4个字节:00001000 11001010 01101100 00000000 --> 147483648 2)再读剩余的1个字节:0000010 --> 2 把以上两个结果拼起来: "2" || "147483648" = "2147483648" 这里才与原值相符 看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注亿速云行业资讯频道,感谢您对亿速云的支持。 (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |