SQL Server datetime数据类型设计、优化误区

一、场景

在SQL Server 2005中,有一个表TestDatetime,其中Dates这个字段的数据类型是datetime,如果你看到表的记录如下图所示,你最先想到的是什么呢?

(图1:数据列表)

你看到这些数据,是不是觉得这样的设计既浪费了存储空间,又使得这个列的索引增大,查询起来更慢,你也想使用一些其它的数据类型来代替这个datetime吧?

其实大家都是这么想的,这个方向是100%正确的,但是在写这篇文章以前,我进入了两个误区:(如果你中了下面的两个误区,那么请你看看这篇文章吧。)

误区一: 把Dates字段的datetime数据类型换成smalldatetime,这样数据就由:‘2009-04-09 00:00:00.000’变为‘2009-04-09 00:00:00’,这个看起来没有减少多少存储空间哦。

误区二:把Dates字段的datetime数据类型换成char(10),这样数据就由:‘2009-04-09 00:00:00.000’变为‘2009-04-09’,这好像能减少很多存储空间哦。

二、分析

在SQL Server 2005版本中保存日期的数据类型只有两种:datetimesmalldatetime,但是在SQL Server 2008版本中新增了一些日期数据类型:timedatesmalldatetimedatetimedatetime2datetimeoffset,其中的date类型就能满足我们场景中的需求了,如果你幸运的在使用SQL Server 2008的话,那么恭喜你,请使用date数据类型吧。

但是我就比较可悲一点了,在使用SQL Server 2005的前提下,我进入了误区一、误区二。其实这也是因为自己忽略了一下基础性的东西,如果知道不同数据类型的存储空间大小,也许就很轻易的避免这样低级的错误了。

其实你查看表TestDatetime中的Dates字段的时候,看到查询结果中的:“-”、“:”只是用于显示的,并不是真实保存的时候就这样格式的。

datetime占用8个字节,前4个字节存储base date(即1900年1月1日)之前或之后的天数,后4个字节存储午夜后的毫秒数。值范围:1753-01-01 到 9999-12-31。

smalldatetime占用4个字节,前2个字节存储base date(1900年1月1日)之后的天数。后2个字节存储午夜后的分钟数。值范围:1900-01-01 到 2079-06-06。

date占用3个字节,它比smalldatetime的前2个字节多了1字节,所以值的范围更广了。值范围:0001-01-01 到 9999-12-31。

所以,如果你使用char(10)来保存截断的日期,那么你的存储空间反而更大了。

结论: 如果是SQL Server 2005,那么请你使用smalldatetime吧,数据能节约一半,虽然查询的时候看起来没什么改变;如果你是SQL Server 2008,那么请你使用date吧,

虽然3个字节跟4个字节没有多大的差距,但是从设计上和逻辑清晰度上都有很大的提升,而且差距有些时候并不是1个字节的问题,比如当表数据量达到几个亿的时候,还是有差别的,又或者一条记录可能因为差1个字节就刚刚好给8060字节的页瓜分,这些都不容忽视的。

三、测试

下面我们就从数据存储的大小、索引存储的大小、索引使用时候的速度这几个方面进行测试:(这里只测试数据类型:,,数据的内容都是一样的)

  • 测试前奏:
  • 创建三种数据类型char(10)、datetime、smalldatetime的表;(表结构如下面SQL)

CREATE TABLE [dbo].[TestDatetime](    [Id] [int] IDENTITY(1,1) NOT NULL,    [Dates] [datetime] NULL, CONSTRAINT [PK_TestDatetime] PRIMARY KEY CLUSTERED(    [Id] ASC)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]) ON [PRIMARY]

  1. 2.      插入相同记录到三个表中;(这里插入1210000条记录)
  2. 3.      为[Dates]字段创建索引;(在创建索引的时候可以设置填充因子为100%)
  3. 4.      查看索引属性中的索引碎片信息,查看表数据和索引占用的空间,测试[Dates]字段索引的查询效率;
  4. (二)  测试结果:
  5. 1.      数据存储大小:

(图2:数据空间对比)

  1. 2.      索引存储信息:

(图3:char(10))

(图4:datetime)

(图5:smalldatetime)

  1. 3.      索引查询的情况:

多次执行,SQL Server执行时间为:[char(10)] 大部分在43~59徘徊,偶尔出现小于10的;[datetime]平均在1~2毫秒;[smalldatetime]均在1毫秒;而且大家会发现[smalldatetime]有其它的9次逻辑读取变为8次了。

--[TestChar10]

SQL Server 分析和编译时间:

CPU 时间= 0 毫秒,占用时间= 1 毫秒。

(2200 行受影响)

表‘TestChar10‘。扫描计数1,逻辑读取9 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。

SQL Server 执行时间:

CPU 时间= 0 毫秒,占用时间= 59 毫秒。

SQL Server 执行时间:

CPU 时间= 0 毫秒,占用时间= 1 毫秒。

--[TestDatetime]

SQL Server 分析和编译时间:

CPU 时间= 0 毫秒,占用时间= 1 毫秒。

(2200 行受影响)

表‘TestDatetime‘。扫描计数1,逻辑读取9 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。

SQL Server 执行时间:

CPU 时间= 0 毫秒,占用时间= 2 毫秒。

SQL Server 执行时间:

CPU 时间= 0 毫秒,占用时间= 1 毫秒。

--[TestSmalldatetime]

SQL Server 分析和编译时间:

CPU 时间= 0 毫秒,占用时间= 1 毫秒。

(2200 行受影响)

表‘TestSmalldatetime‘。扫描计数1,逻辑读取8 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。

SQL Server 执行时间:

CPU 时间= 0 毫秒,占用时间= 1 毫秒。

SQL Server 执行时间:

CPU 时间= 0 毫秒,占用时间= 1 毫秒。

--SQL Server 2008新数据类型SELECTCAST(‘2007-05-08 12:35:29. 1234567 +12:15‘ AS time(7)) AS ‘time‘,CAST(‘2007-05-08 12:35:29. 1234567 +12:15‘ AS date) AS ‘date‘,CAST(‘2007-05-08 12:35:29.123‘ AS smalldatetime) AS‘smalldatetime‘,CAST(‘2007-05-08 12:35:29.123‘ AS datetime) AS ‘datetime‘,CAST(‘2007-05-08 12:35:29. 1234567 +12:15‘ AS datetime2(7)) AS ‘datetime2‘,CAST(‘2007-05-08 12:35:29.1234567 +12:15‘ AS datetimeoffset(7)) AS ‘datetimeoffset‘;

时间: 2024-10-23 19:49:47

SQL Server datetime数据类型设计、优化误区的相关文章

SQL Server datetime 数据类型的问题

近日,在查一个收银报表时,发现一个问题,就是SQL Server中时间日期的字符串值转datetime 类型时,出现了奇怪的事情. 查询如下: 需查询2015-07-01这天的收银数据.传入的日期为:开始日期 '2015-07-01 00:00:00.000' , 结束日期 '2015-07-01 23:59:59.999' . 查询后,发现此收银报表的赠送金额和其它报表的赠送金额对不上.经跟踪发现,赠送金额是有一个表A存储的,A表的日期字段为char类型,仅保存了日期部分的值. 当我们传人的结

SQL Server 2008数据类型

在创建表时,必须为表中的每列指派一种数据类型.本节将介绍SQL Server中最常用的一些数据类型.即使创建自定义数据类型,它也必须基于一种标准的SQL Server数据类型.例如,可以使用如下语法创建一种自定义数据类型(Address),但要注意,它基于SQL Server标准的varchar数据类型. CREATE TYPE Address FROM varchar(35) NOT NULL 如果在SQL Server Management Studio的表设计界面中更改一个大型表中某列的数

SQL Server常见数据类型的介绍

数据表是由多个列组成,创建表时必须明确每个列的数据类型.以下列举SQL Server常见数据类型的使用规则. 整数类型 int 存储范围是-2,147,483,648到2,147,483,647之间的整数,主键列常设置此类型.(每个数值占用 4字节) smallint 存储范围是-32,768 到 32,767 之间的整数,用来存储限定在特定数值范围内的数据.(每个数值占用 2 字节) tinyint 存储范围是0到255 之间的整数,用来存储有限数目的数值.(每个数值占用 1 字节) bigi

说说SQL Server的数据类型

以SQL Server为例,SQL Server的数据类型总共有33种,归纳为一下类别: 精确数字 Unicode字符串 近似数字 二进制字符串 日期和时间 其他数据类型 字符串   1.数字数据类型 1.1 整数数据类型 数据类别 范围 存储 bigint -2的63次方到2的63次方-1 8字节 int -2的31次方到2的31次方-1 4字节 smallint -2的15次方到2的15次方-1 2字节 tinyint 0~255 1字节 int数据类型是主要的整数数据类型,而超过int的存

SQL SERVER的数据类型(转载)

SQL SERVER的数据类型 1.SQL SERVER的数据类型 数据类型是数据的一种属性,表示数据所表示信息的类型.任何一种计算机语言都定义了自己的数据类型.当然,不同的程序语言都具有不同的特点,所定义的数据类型的各类和名称都或多或少有些不同.SQLServer 提供了 25 种数据类型: ·Binary [(n)] ·Varbinary [(n)] ·Char [(n)] ·Varchar[(n)] ·Nchar[(n)] ·Nvarchar[(n)] ·Datetime ·Smallda

Sql Server之数据类型详解

  数据类型是一种属性,用于指定对象可保存的数据的类型,SQL Server中支持多种数据类型,包括字符类型.数值类型以及日期类型等.数据类型相当于一个容器,容器的大小决定了装的东西的多少,将数据分为不同的类型可以节省磁盘空间和资源.  Sql Server 还能自动限制每个数据类型的取值范围,例如定义了一个类型为int的字段,如果插入数据时插入的值的大小在smallint或者tinyint范围之内, Sql Server 会自动将类型转换为smallint 或者tinyint,这样一来,在存储

SQL Server常见数据类型介绍

数据表是由多个列组成,创建表时必须明确每个列的数据类型,以下列举SQL Server常见数据类型的使用规则,方便查阅 Character 字符串: 数据类型 描述 存储 char(n) 固定长度的字符串.最多 8,000 个字符. n varchar(n) 可变长度的字符串.最多 8,000 个字符.   varchar(max) 可变长度的字符串.最多 1,073,741,824 个字符.   text 可变长度的字符串.最多 2GB 字符数据.   Unicode 字符串: 数据类型 描述

SQL Server 聚合函数算法优化技巧

Sql server聚合函数在实际工作中应对各种需求使用的还是很广泛的,对于聚合函数的优化自然也就成为了一个重点,一个程序优化的好不好直接决定了这个程序的声明周期.Sql server聚合函数对一组值执行计算并返回单一的值.聚合函数对一组值执行计算,并返回单个值.除了 COUNT 以外,聚合函数都会忽略空值. 聚合函数经常与 SELECT 语句的 GROUP BY 子句一起使用. v1.写在前面 如果有对Sql server聚合函数不熟或者忘记了的可以看我之前的一片博客.sql server 基

sql server DateTime 取时间间隔不是1毫秒,时间间隔是3.33毫秒,3.33ms C#开发

sql server  DateTime 取时间的间隔是3.33毫秒(3.33ms),所以如果增加1毫秒,数据库默认时间没有增加 C#开发时 DateTime dt=new DateTime(); dt=DateTime.Now; dt=dt.AddMilliseconds(1) ; // dt 的值在数据库没有变化,时间差是1毫秒,sqlserver 默认时间没有增加 dt=dt.AddMilliseconds(3) ;//dt的值在数据库增加3毫秒  获取到的时间差是3毫秒