3

我们有一个带有相当大的表(但不是很大)的 SQL Server - 每个可能有 30-40 百万条记录。

我们要

a)每秒插入大约 1000 条记录(在某些时间 - 但我们不能批量插入)到其中一个表,比如 TABLE_A 和 b)同时 select * from TABLE_B where id = _SOME_GUID_ID

我注意到(a)当前在负载下需要 500-600 毫秒(每个插入,因为我们无法对它们进行批处理)和(b)大约需要 400 毫秒(有一个索引)

这与我们正在寻找的性能相去甚远。有没有办法优化这些表/操作?

当前服务器有 16gb 的内存,总数据库大小约为 40gb。我们预计这些表格将在未来几个月内扩大 10 倍。我们可以使用 Sql Server 进行任何类型的分片吗?我们会看到使用 MySQL Percona 构建的任何性能改进吗?

希望这是有道理的。我想补充一点,我们正在使用 NHibernate,但上述性能是插入数据库所花费的毫秒数 - 不包括应用程序或 nh 开销。

谢谢, 雅尼斯

4

2 回答 2

3

有几件事浮现在脑海。主键是 GUID 还是整数,如果它是 GUID 并且您在其上进行了集群,那么 SQL Server 将不得不在许多不同的位置插入而不是按顺序插入。你是数据库大小,是你的日志大小还是它们一直自动增长,请参阅调整数据库文件大小

运行分析器并查看 nhibernate 创建了什么样的 SQL。每秒 1000 次插入不再那么令人印象深刻,瓶颈也可能是硬件,确保它的大小和配置正确。tempdb、日志和数据文件是否在同一个驱动器上?如果是这样,请将它们移动到单独的驱动器

另一种选择是重写执行这些插入的部分并将它们批处理而不是单行插入

这是我从 SSMS 运行的一个示例,它在 166 毫秒内插入 4999 次,在 40 毫秒内插入 1000 次

CREATE TABLE Sometest(id INT PRIMARY KEY, 
SomeCol VARCHAR(200), SomeDate DATETIME,SomeCol2 VARCHAR(200), 
SomeDate2 DATETIME,SomeCol3 VARCHAR(200), 
SomeDate3 DATETIME,SomeCol4 VARCHAR(200), SomeDate4 DATETIME)
GO




DECLARE @start DATETIME = GETDATE()
SET NOCOUNT ON
DECLARE @id INT =1
WHILE @id < 1000
BEGIN
    INSERT Sometest
    SELECT @id ,'BlaBlaBlaBlaBlaBlaBlaBlaBlaBla111111',GETDATE(),
    'BlaBlaBlaBlaBlaBlaBlaBlaBlaBla2222',GETDATE(),
    'BlaBlaBlaBlaBlaBlaBlaBlaBlaBla3333',GETDATE(),
    'BlaBlaBlaBlaBlaBlaBlaBlaBlaBla4444',GETDATE()
SET @id+=1
END




SELECT DATEDIFF(ms,@start,GETDATE())
SELECT COUNT(*) FROM Sometest

如果你将整个事情包装在一个事务中,它会快得多,50000 次插入在 800 毫秒内,5000 次插入在 103 毫秒内,1000 次插入在 23 毫秒内

TRUNCATE TABLE Sometest
DECLARE @start DATETIME = GETDATE()
SET NOCOUNT ON
BEGIN tran
DECLARE @id INT =1
WHILE @id < 50000
BEGIN
    INSERT Sometest
    SELECT @id ,'BlaBlaBlaBlaBlaBlaBlaBlaBlaBla111111',GETDATE(),
    'BlaBlaBlaBlaBlaBlaBlaBlaBlaBla2222',GETDATE(),
    'BlaBlaBlaBlaBlaBlaBlaBlaBlaBla3333',GETDATE(),
    'BlaBlaBlaBlaBlaBlaBlaBlaBlaBla4444',GETDATE()
SET @id+=1
END
commit
SELECT DATEDIFF(ms,@start,GETDATE())
SELECT COUNT(*) FROM Sometest

在您的系统上使用看起来像您的表的表运行类似的东西并调查问题所在,也许您需要预先调整文件大小、分离文件、对表进行碎片整理等等等

于 2013-03-13T15:26:34.843 回答
0

您的 Guid 可以是顺序 guid 或随机 guid,您需要知道哪个。您可以暂时禁用非聚集索引并在插入结束时重建它们,前提是您不介意(可能)在那段时间内对该表进行较慢的选择。你有多少核心和多少临时数据库?尝试每个核心 1 个 tempdb(最多 8 个核心),但确保设置了正确的跟踪标志以均衡 tempdb 的使用。如下所述,批量插入

于 2013-03-13T15:52:25.593 回答