CREATE TABLE tb4039
(
c1 INT IDENTITY,
c2 CHAR(4035) NOT NULL
)
CREATE TABLE tb4040
(
c1 INT IDENTITY,
c2 CHAR(4036) NOT NULL
)
DECLARE @i INT
SET @i = 1
WHILE @i <= 100
BEGIN
INSERT INTO tb4039
(c2)
VALUES ( 'test' + CONVERT(VARCHAR(5), @i) );
INSERT INTO tb4040
(c2)
VALUES ( 'test' + CONVERT(VARCHAR(5), @i) );
SET @i = @i + 1
END
SELECT Object_name(i.object_id) AS TableName,data_pages * 8 AS DataSize
FROM sys.indexes AS i
JOIN sys.partitions AS p
ON p.object_id = i.object_id
AND p.index_id = i.index_id
JOIN sys.allocation_units AS a
ON a.container_id = p.partition_id
WHERE i.object_id = Object_id('tb4039')
OR i.object_id = Object_id('tb4040')
/*
TableName DataSize
tb4039 400
tb4040 800
*/
/*
SQL Server最小的存储单位是页(Page),一个页的大小是8K=8192字节。
2个表tb4039和tb4040,要存储tb4039中的一行数据需要1+1+2+4039+2+1=4046字节,
所以正好可以在一个页中保存2行数据。所以插入了100行数据,实际上是保存在50个数据页中,大小就是8K*50=400K。
而对于tb4040表,要存储一行数据需要4047个字节,没法在一个页中保存2行数据,所以一行数据就占用一个数据页,
100行数据占用了100个数据页,大小就是8K*100=800K。
*/
/*
实际上我们要让一个数据页中存放更多行的数据主要是出于性能的考虑。
SQL Server进行数据库读写操作的基本单位是页,如果一页中存放了更多的数据,
那么对表进行扫描和查找时进行的IO操作将减少,毕竟IO操作是非常消耗时间影响性能的。
假设tb4039中有100W条数据,那么进行全表扫描就要读取50W个数据页,如果读取10W个数据页花费1秒钟,
那么对表tb4039进行扫描需要花费5秒钟时间,而如果是使用tb4040存储这100W条数据,
进行全表扫描则需要读取100W个数据页,总共花费10秒钟时间。就一个字节的差别,
一个是5秒另一个是10秒,对性能的影响非常明显。
为了提高数据库查询的性能,在表设计时可以遵循以下建议:
主键尽可能的短,能用tinyint的就不要用int,能用char(5)的就不要用成varchar(50)。
计算好表列的长度,能够在一个页中存放5条数据的,那就不要将字段设置的太长使得一个页中只能存放3条或者4条数据。
尽量将字段设置为不允许为NULL,因为NULL值在存储和数据处理时系统需要专门的处理,降低了性能。
能够用固定长度的就不要用变长字段,比如身份证号就可以使用CHAR(18),而不应该使用VARCHAR(18)。
不要在一个表中建立太多的列,如果一个实体的属性太多时可以考虑进行垂直分割,将常用的字段放在一个表,
不常用的字段放另外的表,这样可以减小常用字段表中数据列占用的空间,使得一个数据页中存储更多的数据行。
不要将大对象、长字符串和常用的字段放在同一个表中。同样还是出于性能上的考虑,
比如有个产品表,里面有产品ID、产品名字、产品售价、产品图片、产品描述等字段,那么我们可以将产品ID、产品名字、
产品售价这几个常用的而且占用空间小的列放在一个表,然后建立产品ID、产品图片、产品描述这样的表,
通过外键约束的方式将大对象数据和长字符串数据放在另一个表中。
*/
(
c1 INT IDENTITY,
c2 CHAR(4035) NOT NULL
)
CREATE TABLE tb4040
(
c1 INT IDENTITY,
c2 CHAR(4036) NOT NULL
)
DECLARE @i INT
SET @i = 1
WHILE @i <= 100
BEGIN
INSERT INTO tb4039
(c2)
VALUES ( 'test' + CONVERT(VARCHAR(5), @i) );
INSERT INTO tb4040
(c2)
VALUES ( 'test' + CONVERT(VARCHAR(5), @i) );
SET @i = @i + 1
END
SELECT Object_name(i.object_id) AS TableName,data_pages * 8 AS DataSize
FROM sys.indexes AS i
JOIN sys.partitions AS p
ON p.object_id = i.object_id
AND p.index_id = i.index_id
JOIN sys.allocation_units AS a
ON a.container_id = p.partition_id
WHERE i.object_id = Object_id('tb4039')
OR i.object_id = Object_id('tb4040')
/*
TableName DataSize
tb4039 400
tb4040 800
*/
/*
SQL Server最小的存储单位是页(Page),一个页的大小是8K=8192字节。
2个表tb4039和tb4040,要存储tb4039中的一行数据需要1+1+2+4039+2+1=4046字节,
所以正好可以在一个页中保存2行数据。所以插入了100行数据,实际上是保存在50个数据页中,大小就是8K*50=400K。
而对于tb4040表,要存储一行数据需要4047个字节,没法在一个页中保存2行数据,所以一行数据就占用一个数据页,
100行数据占用了100个数据页,大小就是8K*100=800K。
*/
/*
实际上我们要让一个数据页中存放更多行的数据主要是出于性能的考虑。
SQL Server进行数据库读写操作的基本单位是页,如果一页中存放了更多的数据,
那么对表进行扫描和查找时进行的IO操作将减少,毕竟IO操作是非常消耗时间影响性能的。
假设tb4039中有100W条数据,那么进行全表扫描就要读取50W个数据页,如果读取10W个数据页花费1秒钟,
那么对表tb4039进行扫描需要花费5秒钟时间,而如果是使用tb4040存储这100W条数据,
进行全表扫描则需要读取100W个数据页,总共花费10秒钟时间。就一个字节的差别,
一个是5秒另一个是10秒,对性能的影响非常明显。
为了提高数据库查询的性能,在表设计时可以遵循以下建议:
主键尽可能的短,能用tinyint的就不要用int,能用char(5)的就不要用成varchar(50)。
计算好表列的长度,能够在一个页中存放5条数据的,那就不要将字段设置的太长使得一个页中只能存放3条或者4条数据。
尽量将字段设置为不允许为NULL,因为NULL值在存储和数据处理时系统需要专门的处理,降低了性能。
能够用固定长度的就不要用变长字段,比如身份证号就可以使用CHAR(18),而不应该使用VARCHAR(18)。
不要在一个表中建立太多的列,如果一个实体的属性太多时可以考虑进行垂直分割,将常用的字段放在一个表,
不常用的字段放另外的表,这样可以减小常用字段表中数据列占用的空间,使得一个数据页中存储更多的数据行。
不要将大对象、长字符串和常用的字段放在同一个表中。同样还是出于性能上的考虑,
比如有个产品表,里面有产品ID、产品名字、产品售价、产品图片、产品描述等字段,那么我们可以将产品ID、产品名字、
产品售价这几个常用的而且占用空间小的列放在一个表,然后建立产品ID、产品图片、产品描述这样的表,
通过外键约束的方式将大对象数据和长字符串数据放在另一个表中。
*/