数据库中将数字类型存储成字符型有哪些坏处?

2024-02-29 22:32

本文主要是介绍数据库中将数字类型存储成字符型有哪些坏处?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

    工作中经常见到一些设计粗糙的数据库,其中将数字类型的字段定义和存储成字符型是一种比较常见的情况。部分开发同学或者非数据库岗位很多为了图方便,往往又不在意这些细节,除非等到出现可见的或者一些不可见的问题时才会去研究隐藏其后的真相。所以,这里简单总结一下,在数据库系统中,将数字类型存储成字符类型会有哪些不好的地方。以关系型数据库MySQL示例。

    ①字符类型往往比数字类型占用更多的存储

    首先,字符类型往往占用更多的存储,但非总是占用更多的存储。MySQL以固定长度存储数字类型:TINYINT、SMALLINT、MEDIUMINT、INT和BIGINT分别占用1、2、3、4和8个Byte存储。所以,就“1024”这个数值,如果以BIGINT、CHAR(4)和VARCHAR存储,不考虑其他,分别需要8、4和5个Byte存储(VARCHAR类型以是否存储了超过255个字符为界限分别需要额外1个或者2个Byte来记录存储长度)。但实际使用中,我们遇到的数字类型,其值域或者说取值空间是很宽大的,或者刚好可以放入一个较小的数字类型定义中。绝大多数情况下,总是可以通过选用数字类型从而节省存储空间。文件型数据库,数据最终是存储在磁盘上的文件,当需要对其查询时再读取到内存中。所以,更少的存储空间消耗与更高的查询性能是直接相关的。

    ②数字类型存储成字符类型可能使索引失效

    字段间进行比较时,如果字段类型不一致,在查询之前需要类型转换,否则无法直接进行比较。因为额外的类型转换操作,使得字段上的索引不可用。因此,将数字类型存储成字符类型,并且为其定义了索引,当其与其他数字类型字段关联查询时,该索引就失效了。

    ③数字类型存储成字符类型可能使部分SQL函数和命令失效

    数字的计算比较是作为一个整体在CPU中进行的。当数字类型存储成字符型时,会受到编码和排序规则影响;对字符型的查询是从左往右一个字符一个字符依次进行的,即最左前缀匹配。因此,将字符型数字直接传入部分函数或命令会使结果失真。

    首先创建两张示例表,插入相同的数据,但数据类型定义不一致。

CREATE TABLE `i` (`i` INT(11) NULL DEFAULT NULL
)
;
INSERT INTO `i` (`i`) VALUES (4);
INSERT INTO `i` (`i`) VALUES (8);
INSERT INTO `i` (`i`) VALUES (11);
INSERT INTO `i` (`i`) VALUES (23);
INSERT INTO `i` (`i`) VALUES (1024);
INSERT INTO `i` (`i`) VALUES (2147483647);
CREATE TABLE `s` (`s` VARCHAR(50) NULL DEFAULT NULL
)
;
INSERT INTO `s` (`s`) VALUES ('4');
INSERT INTO `s` (`s`) VALUES ('8');
INSERT INTO `s` (`s`) VALUES ('11');
INSERT INTO `s` (`s`) VALUES ('23');
INSERT INTO `s` (`s`) VALUES ('1024');
INSERT INTO `s` (`s`) VALUES ('2147483647');

    数字类型存储成字符型使得SQL查询结果失真。

mysql> SELECT MAX(i.i) FROM i;
+------------+
| MAX(i.i)   |
+------------+
| 2147483647 |
+------------+
1 row in set (0.00 sec)mysql> SELECT MAX(s.s) FROM s;
+----------+
| MAX(s.s) |
+----------+
| 8        |
+----------+
1 row in set (0.00 sec)
mysql> SELECT i.i FROM i ORDER BY i.i;
+------------+
| i          |
+------------+
|          4 |
|          8 |
|         11 |
|         23 |
|       1024 |
| 2147483647 |
+------------+
6 rows in set (0.00 sec)mysql> SELECT s.s FROM s ORDER BY s.s;
+------------+
| s          |
+------------+
| 1024       |
| 11         |
| 2147483647 |
| 23         |
| 4          |
| 8          |
+------------+
6 rows in set (0.00 sec)

    为了得到预想的数值结果,必须额外进行一次数据类型转换操作,包括隐式转换和显式转换两种方式。隐式转换是进行一个简单的不改变数值大小的数学计算;显式转换是借助CAST或者CONVERT函数。隐式操作在开发维护工作中往往就是出问题的根源,所以如果真的到了需要进行类型转换的时候,建议使用标准SQL规范的CAST。

mysql> SELECT MAX(s.s + 0) FROM s;
+--------------+
| MAX(s.s + 0) |
+--------------+
|   2147483647 |
+--------------+
1 row in set (0.01 sec)mysql> SELECT MAX(CAST(s.s AS DECIMAL)) FROM s;
+---------------------------+
| MAX(CAST(s.s AS DECIMAL)) |
+---------------------------+
|                2147483647 |
+---------------------------+
1 row in set (0.00 sec)

 

 

    参考:

https://dev.mysql.com/doc/refman/5.7/en/mysql-indexes.html

https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_max

https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_cast

这篇关于数据库中将数字类型存储成字符型有哪些坏处?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/760316

相关文章

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

HDFS—存储优化(纠删码)

纠删码原理 HDFS 默认情况下,一个文件有3个副本,这样提高了数据的可靠性,但也带来了2倍的冗余开销。 Hadoop3.x 引入了纠删码,采用计算的方式,可以节省约50%左右的存储空间。 此种方式节约了空间,但是会增加 cpu 的计算。 纠删码策略是给具体一个路径设置。所有往此路径下存储的文件,都会执行此策略。 默认只开启对 RS-6-3-1024k

从去中心化到智能化:Web3如何与AI共同塑造数字生态

在数字时代的演进中,Web3和人工智能(AI)正成为塑造未来互联网的两大核心力量。Web3的去中心化理念与AI的智能化技术,正相互交织,共同推动数字生态的变革。本文将探讨Web3与AI的融合如何改变数字世界,并展望这一新兴组合如何重塑我们的在线体验。 Web3的去中心化愿景 Web3代表了互联网的第三代发展,它基于去中心化的区块链技术,旨在创建一个开放、透明且用户主导的数字生态。不同于传统

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

usaco 1.2 Name That Number(数字字母转化)

巧妙的利用code[b[0]-'A'] 将字符ABC...Z转换为数字 需要注意的是重新开一个数组 c [ ] 存储字符串 应人为的在末尾附上 ‘ \ 0 ’ 详见代码: /*ID: who jayLANG: C++TASK: namenum*/#include<stdio.h>#include<string.h>int main(){FILE *fin = fopen (

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0