我正在编写一个需要每晚同步自己的数据库和另一个数据库的应用程序。当数据被拉过来时,它也会以相当复杂的方式进行编程转换。
现在我看到两种可能的方法:
方法A:每晚我删除所有以前导入的行,并进行完全重新导入,这种方法很昂贵,但易于编程,维护,整体健壮
方法B:我为每个导入的行保存对原始数据的引用,如果数据分别是新的,更改的或删除的话,则执行插入,更新或删除操作(单独保留引用是非常复杂的,因为没有简单的一对一关系)
显然,方法B更复杂并且可能更容易导致错误,因此我更喜欢使用方法A.但是,由于每晚大约插入100,000行,因此标识列将随着时间的推移而运行得非常高。由于导入的行实际上与其他与数据传输无关的行混合,因此每晚进行简单的重置为1不是一种选择,最后设置的行必须不受传输的影响。
我对此的主要问题是,我们的标识栏是否会高涨(每年增加约3600万)是否是一个问题。它不整洁,但最终会有性能损失,如果我们达到最大int值会发生什么?有没有人面临类似的挑战,可以分享他们的经验?
答案 0 :(得分:1)
最终是否会有性能影响
我不明白为什么会这样。字段的大小是相同的(例如,32位),因此无论字段的值是10还是2,000,000,000,所有使用它的操作都将以相同的速度执行。
如果您的标识列是int(32位),那么它将持续2,147,483,647 / 36,000,000 = 59
年。
很容易检查达到最大值2,147,483,647时会发生什么。在tempdb中创建一个表。 (我正在使用SQL Server 2008进行此测试)。
USE [tempdb]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[BigTable](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Data] [int] NOT NULL,
CONSTRAINT [PK_BigTable] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
将标识设置为高值:
USE [tempdb]
GO
DBCC CHECKIDENT ("[dbo].[BigTable]", RESEED, 2147483645);
尝试插入10行:
USE [tempdb]
GO
INSERT INTO [dbo].[BigTable]
([Data])
VALUES
(0)
GO 10
这是我在输出窗口中得到的结果:
Beginning execution loop
(1 row(s) affected)
(1 row(s) affected)
(1 row(s) affected)
Msg 8115, Level 16, State 1, Line 2
Arithmetic overflow error converting IDENTITY to data type int.
Arithmetic overflow occurred.
** An error was encountered during execution of batch. Continuing.
Msg 8115, Level 16, State 1, Line 2
Arithmetic overflow error converting IDENTITY to data type int.
Arithmetic overflow occurred.
** An error was encountered during execution of batch. Continuing.
Msg 8115, Level 16, State 1, Line 2
Arithmetic overflow error converting IDENTITY to data type int.
Arithmetic overflow occurred.
** An error was encountered during execution of batch. Continuing.
Msg 8115, Level 16, State 1, Line 2
Arithmetic overflow error converting IDENTITY to data type int.
Arithmetic overflow occurred.
** An error was encountered during execution of batch. Continuing.
Msg 8115, Level 16, State 1, Line 2
Arithmetic overflow error converting IDENTITY to data type int.
Arithmetic overflow occurred.
** An error was encountered during execution of batch. Continuing.
Msg 8115, Level 16, State 1, Line 2
Arithmetic overflow error converting IDENTITY to data type int.
Arithmetic overflow occurred.
** An error was encountered during execution of batch. Continuing.
Msg 8115, Level 16, State 1, Line 2
Arithmetic overflow error converting IDENTITY to data type int.
Arithmetic overflow occurred.
** An error was encountered during execution of batch. Continuing.
Batch execution completed 10 times.
结果如下:
USE [tempdb]
GO
SELECT [ID] ,[Data]
FROM [dbo].[BigTable]
GO
ID Data
2147483645 0
2147483646 0
2147483647 0
DBCC CHECKIDENT ("[tempdb].[dbo].[BigTable]", NORESEED);
Checking identity information: current identity value '2147483647', current column value '2147483647'.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
所以,是的,当你耗尽所有int值时会出现问题。
您可以改用bigint。它是64位(8个字节,而不是16个),并且会持续更长的时间:9,223,372,036,854,775,807 / 36,000,000 = 256,204,778,801
年
bigint的性能与64位计算机上的int几乎相同。它可能比int慢,因为它的大小是它的两倍,服务器必须读取/写入磁盘的两倍字节并使用两倍的内存。
在性能方面,最重要的是在删除大量行并向其添加大量行后重建索引并更新表的统计信息,因为所有统计信息都会严重偏差。这里我的意思是使用此表的系统其余部分的性能,而不是删除和添加行的过程。
要提高删除大量行并添加大量行的夜间同步过程的性能,请考虑在更改之前禁用表上的所有索引,并在更改后启用(重建)它们。
答案 1 :(得分:0)
只要您的身份是64位或更高,您就可以管理。它不是理想的,但它会工作几年,直到你决定你真的需要真正的反射。
是的,你可以建立一个理想的解决方案,但听起来你现在需要一个“足够好”的解决方案......方法A是什么。