Int*_*rel 7 sql-server sql-server-2019
我的 SQL Server 数据库上的文件大小有一个大问题。
让我把一切都放在上下文中:
在一个空数据库上,我正在创建一个新表:
CREATE TABLE mytable
(
id int identity(1,1) NOT NULL,
description varchar(255) NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
=> 在磁盘上,我有 datafile=8192K 和 logfile=8192k
我将 1'000'000 行插入到我的表中,如下所示:
INSERT INTO mytable(description)
SELECT TOP (1000000)
'test test test test test test test test test test test'
FROM sys.all_objects AS o1
CROSS JOIN sys.all_objects AS o2
CROSS JOIN sys.all_objects AS o3;
Run Code Online (Sandbox Code Playgroud)
=> 在磁盘上,我有 datafile=73M 和 logfile=376M
我正在更改描述列,将其数据类型更改为nvarchar
:
ALTER TABLE mytable
ALTER COLUMN description nvarchar(255) NOT NULL;
Run Code Online (Sandbox Code Playgroud)
=> 在磁盘上,我有 datafile=204M 和 logfile=1.3G
我ALTER
多次执行这些SQL 命令:
ALTER TABLE mytable
ALTER COLUMN description varchar(255) NOT NULL;
ALTER TABLE mytable
ALTER COLUMN description nvarchar(255) NOT NULL;
Run Code Online (Sandbox Code Playgroud)
=> 在磁盘上,我有 datafile=816M 和 logfile=3G
问题 1:当我在 2 列类型之间切换时,数据库像这样增长是否正常?
问题2:应用Database Shrink,日志文件被重置(返回8192K),但数据文件大小仍然保持为816M。正常吗?
SQL Server 数据库中是否有选项可以进行自动收缩或类似的操作?这是在一个测试数据库中,但在生产中,我从一个 150G 的数据库开始,所以我无法想象一些ALTER
.
我正在使用 SQL Server 2019。
在此先感谢您的帮助。
将列类型从 varchar 更改为 nvarchar 会更改数据在磁盘上的物理存储方式。Nvarchar 是 unicode,需要两个字节来存储每个字符(或多或少,有例外,但它们超出了此处的范围),而 varchar 存储为常规 8 位数据(每个字符 1 个字节)。当您更改数据类型时,数据将被复制到新页面,因为必须以新形式重写数据,因此数据库将会增长。
由于您的表是一个堆(没有聚集索引),因此分配算法不会更新 GAM,而是将数据移动到新页面并在旧页面上创建一个指针。要回收空间,您需要ALTER TABLE mytable REBUILD
在表上执行或创建聚集索引,然后可以收缩数据库文件。
Paul Randall 发表了很多有关SQL Server 磁盘结构的博客。如果你感兴趣。这些都是强烈推荐的,尤其是页面帖子的剖析,Hugo Kornelis 可以告诉你来自地狱的表扫描的故事
阅读本文时您会发现的一件事是,缩小数据库文件并不是一个好主意。您可以在数据库上设置一个选项来自动收缩它,ALTER DATABASE Empty SET AUTO_SHRINK ON
但这确实不是一个好主意!
如果您想对转换的大小进行有根据的猜测,您可以计算转换后当前 varchar 列有多大,这不会计算这些列上增加的空间索引,并且仅基于最大长度列的大小,但不取决于其中存储的数据的大小。
select
sum(c.max_length) as current_max_length_in_varchar,
sum(c.max_length)*2 as required_max_length_in_nvarchar
from sys.tables t
inner join sys.columns c
on c.[object_id] = t.[object_id]
where t.type = 'U'
and c.system_type_id = 167 -- Type 167 is varchar, see sys.types
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
315 次 |
最近记录: |