当前位置: 首页 > 编程日记 > 正文

如何提高增加包含大量记录的表的主键字段的效率

如何提高增加包含大量记录的表的主键字段的效率

LazyBee

1 问题的提出:

在给客户升级数据库系统时,由于报表的需要,系统中每一个表都需要有主键字段。系统审计表自然也有这个要求需要增加一个identify的字段,但这个表中有2000多万条记录,使用以下SQLl语句:alter table erAuditEventTime add EventTime_ID int IDENTITY primary key clustered来增加时需要4个多小时。客户要求我们对此进行提速。

2 抛砖--解决过程

问题出来之后,我第一时间上google去狂搜了一番,可是没有一条是关于对增加主键提速的。都是说建表增加主键提高效率的。这可怎么办?刚开始我以为是日志增长过快的原因,因为我在测试数据库上执行此语句时发现数据库日志文件在以“光速”狂飙,一段时间下来就长到十几个G,于是将数据库的恢复模式改成Simple(简单),效率还是没有多大改善,于是认为会不会是锁的问题呢,但是由于SQL Server会根据情况自动将锁升级的,应该没有问题,不管怎么样还是给加上了with nocheck选项。好像依然没戏,不知什么时候“灵光”一现,我能不能采用拷贝策略呢,不管三七二十一先试试再说,于是将上面的语句改写成下面的方式:

 1--Rename table
 2exec sp_rename 'erAuditEventTime','zxg_erAuditEventTime'
 3go
 4--Copy table schema
 5select top 0 * into erAuditEventTime from zxg_erAuditEventTime 
 6go
 7--Add identify field
 8alter table erAuditEventTime 
 9add EventTime_ID int IDENTITY primary key clustered
10go
11--Copy data
12insert into erAuditEventTime select * from zxg_erAuditEventTime 
13go
14


改完之后,测试发现,完成这些语句需要3826秒。欣喜……

3 反思

为什么将语句改成这种形式之后,效率能提高这么多呢?我觉得可能跟SQL Server的数据库物理存储有关。对此,让我们先了解一下SQL Server的物理存储:

数据库文件:SQL Server包含三种类型的数据库文件主数据文件(Primary Data Files)、次要数据文件(Secondary data files)、日志文件(Log files)。主数据文件是数据库的起点,指向数据库中的其他文件。每个数据库都只有一个主数据文件(扩展名为.mdf)。除主数据文件以外的其他数据文件都是次要数据文件。有些数据库可能不含任何次要数据文件,而有些数据库则含有多个次要数据文件(扩展名为.ndf)。日志文件包含用于恢复数据库的所有日志信息。每个数据库至少有一个日志文件,当然也可以有多个(扩展名为.ldf)。数据库中所有文件的位置都记录在数据库的主文件和master数据库中。大多数情况下,SQL Server数据库引擎使用master数据库中的文件信息。只有在下列情况下,数据库引擎使用主数据文件的文件位置信息初始化master数据库中的文件位置项:还原master数据库时、使用带有For AttachFor ATTACH_REBUILD_LOG选项的Create Database语句来附加数据库时、从SQL Server2000升级到SQL Server2005时。

数据库文件组:文件组是命名的文件集合,为了便于分配和管理,可以将数据库对象和文件一起分成文件组。有两种类型的文件组:主文件组、用户定义文件组。主文件组包含主数据文件和没有明确分配给其他文件组的其他文件。系统表的所有页均分配在主文件组中。用户定义的文件组是通过在Create Database Alter DataBase语句中使用FILEGROUP关键字指定的任何文件组。(日志文件不包括在文件组内,日志空间和数据空间分开管理)。并且一个文件只能属于一个文件组。每个数据库中均有一个文件组被指定为默认文件组,如果创建表或索引时未指定文件组,则将假定所有页都从默认文件组分配。一次只能有一个文件组作为默认文件组。db_owner成员可以将默认文件组从一个文件组切换到另一个。如果没有指定默认文件组,则将主文件组作为默认文件组。

页(Page:是SQL Server中存储数据的基本单位是页(Page),页的大小是8K,也就是SQL Server数据库中每MB中有128页。每页的开头是96个字节的标头,用于存储有关页的系统信息,包括页码、页的类型、页的可用空间以及拥有该页的对象的分配单元ID。下表说明SQL Server的数据库文件中使用的页类型:

页类型

内容

Data

text in row设置为 ON 时,包含除 text ntextimagenvarchar(max)varchar(max)varbinary(max) xml数据之外的所有数据的数据行。

Index

索引条目。

Text/Image

大型对象数据类型:

·                      text ntextimagenvarchar(max)varchar(max)varbinary(max) xml数据。

数据行超过 8 KB 时为可变长度数据类型列:

·                      varcharnvarcharvarbinary sql_variant

Global Allocation MapShared Global Allocation Map

有关区是否分配的信息。

Page Free Space

有关页分配和页的可用空间的信息。

Index Allocation Map

有关每个分配单元中表或索引所使用的区的信息。

Bulk Changed Map

有关每个分配单元中自最后一条 BACKUP LOG 语句之后的大容量操作所修改的区的信息。

Differential Changed Map

有关每个分配单元中自最后一条 BACKUP DATABASE 语句之后更改的区的信息。

注意:日志文件不包含页,而是包含一系列的日志记录。数据库的每个文件都有一个唯一的文件ID号,并且数据文件中的页是按顺序编号的,文件的首页以0开始。若要唯一表示数据库中的页,需要同时使用文件ID和页码。

(Extents)8个物理上连续的页为一个区(即64k.区是SQL Server管理空间的基本单位,也就是说SQL Server为了提高效率,给对象分配空间时是以区为单位的,而不是以页为单位。为了使分配空间更有效,SQL Server不会将某一个区中的所有空间分配给包含少量数据的表。为此,SQL Server包含两种类型的区:统一区和混合区统一区由单个对象所有。区中的所有 8 页只能由所属对象使用。混合区,最多可由八个对象共享。区中八页的每页可由不同的对象所有。通常从混合区向新表或索引分配页。当表或索引增长到 8 页时,将变成使用统一区进行后续分配。如果对现有表创建索引,并且该表包含的行足以在索引中生成 8 页,则对该索引的所有分配都使用统一区进行。

结论:由于在对含有大量数据的erAuditEventTime表增加一个Identify字段的时,对每一行数据都需要进行变更,SQL Server为了保证同一行数据都位于同一页中,所以需要频繁移动原有页中的数据,导致大量而且频繁的IO操作;而采用另外新建一个表,然后使用insert into 语句来进行数据拷贝工作时,SQL Server只需要给新的表分配一系列的没有使用的统一区就可以了,大大减少了IO操作。而且这两种方式创建和保存索引的性能是一样的没有区别,这可能就是性能相差这么大的真正原因。

4 引玉

由于本人对SQL Server也不是特别懂,所以也请园子里的大虾们也发表发表高论,看看是否是这个原因导致的性能差异,以及针对这种案例是否有更好的解决方案?(转载请注明出处:http://lazybee.cnblogs.com/,谢谢!)

转载于:https://www.cnblogs.com/LazyBee/archive/2008/07/15/1243491.html

相关文章:

${pageContext.request.contextPath} JSP取得绝对路径

在使用的时候可以使用${pageContext.request.contextPath}&#xff0c;也同时可以使用<%request.getContextPath()%>达到同样的效果&#xff0c;同时&#xff0c;也可以将${pageContext.request.contextPath}&#xff0c;放入一个JSP文件中&#xff0c;将用C&#xff1a;…

Matlab与线性代数 -- 矩阵的水平连接和垂直连接

本图文详细介绍了Matlab中矩阵的水平连接和垂直连接。

Matlab与线性代数 -- 矩阵的复制

本图文详细介绍了Matlab中矩阵复制函数repmat(A,m,n)。

用C#实现抽象工厂模式

大家都知道&#xff0c;在开发中&#xff0c;如果用好了某种模式&#xff0c;那效率…… 嘿嘿 我就不说了 进入正题吧&#xff1a; 以下都为源代码&#xff0c;可直接拷贝&#xff0c;然后自己研究 由于是讲解&#xff0c;所以只涉及基本的架构 项目名为&#xff1a;Ab…

树莓派 raspberry安全关机命令重启命令

树莓派可以通过下面几个命令来实现安全关机&#xff1a;sudo shutdown -h now sudo halt sudo poweroff sudo init 0上面四行代码都可以&#xff0c;执行一行都可以安全关机, ^_^树莓派重启 定时重启方法&#xff1a;sudo reboot shutdown -r now shutdown -r 04:00:00 #定时重…

jps命令(Java Virtual Machine Process Status Tool)(转)

1、介绍 用来查看基于HotSpot的JVM里面中&#xff0c;所有具有访问权限的Java进程的具体状态, 包括进程ID&#xff0c;进程启动的路径及启动参数等等&#xff0c;与unix上的ps类似&#xff0c;只不过jps是用来显示java进程&#xff0c;可以把jps理解为ps的一个子集。 使用jps时…

使用 Smartmontools 检测硬盘坏道

2019独角兽企业重金招聘Python工程师标准>>> 在这篇文章中&#xff0c;我们通过几个必要的步骤&#xff0c;使用特定的磁盘扫描工具让你能够判断 Linux 磁盘或闪存是否存在坏道。 在Linux上使用坏块工具检查坏道 坏块工具可以让用户扫描设备检查坏道或坏块&#xff…

如何使用Github管理自己的代码

本文介绍了使用Github管理代码的基本操作方法。由LSGO软件技术团队的安晟提供。

javassist 初步学习

javassist简介 javassist可以对一个已经编译好了的.class文件的字节码进行改动&#xff0c;比如说我可以为一个类添加一个方法&#xff0c;添加一个属性&#xff0c;也可以修改一个方法等&#xff0c;还可以对一个方法&#xff0c;异常进行拦截等。 我们常用到的动态特性主要…

.NET环境下有关打印页面设置、打印机设置、打印预览对话框的实现

原文:.NET环境下有关打印页面设置、打印机设置、打印预览对话框的实现我个人认为&#xff0c;开发MIS&#xff0c;首先就得解决网格的问题,而开发工具为我们提供了如DataGrid、MSHFlexGrid的控件。其次&#xff0c;是打印的问题&#xff0c;将业务单据与数据报表打印出来。可想…

Silverlight 2 beta 2 中目前不支持共享 WCF 的客户端类型

在调用多个 WCF Service 的时候经常会遇到的一个问题是&#xff0c;某些同样的类型因为在不同的 Service 里用到&#xff0c;就被重复生成了好几个版本的代理类型&#xff0c;分别处在不同的名称空间下。这样&#xff0c;如果一个操作需要同时调用几个 Service&#xff0c;就会…

Matlab与线性代数 -- 逆矩阵

本微信图文详细介绍了Matlab中各种求逆矩阵的方法。

使用intellij idea制作可执行jar文件

可执行jar文件 一个可执行的 jar文件是一个自包含的 Java 应用程序&#xff0c;它存储在特别配置的 JAR 文件中&#xff0c;可以由 JVM 直接执行它而无需事先提取文件或者设置类路径。要运行存储在非可执行的 JAR 中的应用程序&#xff0c;必须将它加入到您的类路径中&#xf…

c# 一些控件常用屬性

Form&#xff1a;ControlBox&#xff1a;移除窗體按鈕(最大化、最小化、關閉組&#xff09;&#xff0c;並從左側移除「系統菜單」Opacity&#xff1a;控制窗體透明度ActiveControl&#xff1a;指出窗體上當前哪一個擦傷擁有焦點BackColor&#xff1a;窗體中任何文本和圖形的默…

centos设置固定IP方法

首先网络模式设为桥接 [rootcentos64 ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICEeth0HWADDR00:0C:29:80:9D:41TYPEEthernetUUID29784981-a8cc-4405-8923-264df546350eONBOOTyesNM_CONTROLLEDyesBOOTPROTOstatic #设为静态的IPADDR192.168.0.99 #设置固定ipNETMA…

如何利用离散Hopfield神经网络进行数字识别(1)

如何利用离散Hopfield神经网络进行数字识别&#xff0c;代码部分。

You can't specify target table for update in FROM clause

今天使用mysql,写出一个sql语句&#xff1a; update service_re set is_deleted0 where id(select id from service_re where p_id21000122321 limit 1);执行这样的sql会报一个异常&#xff1a; You cant specify target table for update in FROM clause 查了资料&#xf…

在C# Express 2005中配置 NUnit

在C# Express 2005中配置 NUnit www.cnblogs.com/Pamigo/ 2008-7-28 在网上有很多关于在C#中使用NUnit的相关文章&#xff0c;但是我安装了NUnit后却不知道在C# Express中应该如何配置&#xff0c;相信很多人也遇到了同样的问题。根据自己的摸索总结了一下&#xff0c;希望对大…

如何利用离散Hopfield神经网络进行数字识别(2)

如何利用离散Hopfield神经网络进行数字识别

SQL语句实现取消自增列属性

由于在SQL-SERVER中&#xff0c;自增列属性不能直接修改&#xff0c;但可以通过以下方式变向实现 1、如果仅仅是指定值插入&#xff0c;可用以下语句&#xff0c;临时取消 SET IDENTITY_INSERT TableName ONINSERT INTO tableName(xx,xx) values(xx,xx)SET IDENTITY_INSERT Tab…

Mac OS 提高工作效率的几个快捷键

Mac OS X 命令行中组快捷键 几组导航快捷键 跳至行首 – ControlA 跳至行尾 – ControlE 跳至上一个单词 – Control<- 跳至下一个单词 – Control-> 跳至下一行 – ControlN 跳至上一行 – ControlP 删除上一个单词 – ControlW 删除当前光标位置到行首的文字 – Cont…

什么是离散的Hopfield网络?

什么是离散的Hopfield网络&#xff1f;

《OpenStack实战》——第1章 介绍OpenStack 1.1OpenStack是什么

本节书摘来自异步社区《OpenStack实战》一书中的第1章&#xff0c;第1.1节&#xff0c;作者&#xff1a; 【美】V. K. Cody Bumgardner&#xff08;V. K. 科迪•布姆加德纳&#xff09;著&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看 第一部分 入门指南 本…

【转】 一些NET的实用类,不错

http://www.cnblogs.com/9who/archive/2008/08/01/1258248.html转载于:https://www.cnblogs.com/niuniu502/archive/2008/08/01/1258331.html

/dev/null

把/dev/null看作"黑洞". 它非常等价于一个只写文件. 所有写入它的内容都会永远丢失. 而尝试从它那儿读取内容则什么也读不到. 然而, /dev/null对命令行和脚本都非常的有用. 禁止标准输出. 1 cat $filename >/dev/null2 # 文件内容丢失&#xff0c;而不会输出到标…

backup restore On Ubuntu

详见&#xff1a;https://help.ubuntu.com/community/BackupYourSystem/TAR 在 使用Ubuntu之前&#xff0c;相信很多人都有过使用Windows系统的经历。如果你备份过Windows系统&#xff0c;那么你一定记忆犹新&#xff1a;首先需要找到一个备份工 具(通常都是私有软件)&#xff…

.net 连接ORACLE 数据库的例子

利用 System.Data.OracleClient.Dll 的组件进行连接&#xff1a; 首先配置WebConfig 文件&#xff1b; <connectionStrings> <add name"oracleconn" connectionString"Data Source"";User IDryq;Password123456" providerName&quo…

什么是SESSION?(一)

本图文通过三个问题的回答&#xff0c;详细介绍了Session的机制。本图文由钟锦提供。

linux下字符串处理工具一:grep

grep常见选项 grep -A &#xff1a;显示匹配行和之后的几行 grep -A 4 "NullPointerException" test.log 找到NullPointerException之后的几行-c &#xff1a;打印匹配到的行数 c:count[adminv069164233.sqa.<pre name"code" class"html"&…

Matlab与随机变量和样本的数字特征

本文主要介绍了常见分布的期望和方差以及样本的数字特征。贡献人为孔令才。