[英]Insert sorted data to a table with nonclustered index
我的数据库模式:
point
( point_id int PK, name varchar
); point_log
( point_log_id int PK, point_id int FK, timestamp datetime, value int
) point_log
有一个索引:
point_log_idx1 (point_id asc, timestamp asc)
我需要将点日志样本插入到point_log表中,在每个事务中,仅插入一个point_id的日志样本,并且日志样本已经按升序排序。 这意味着事务中的所有日志样本数据的index( point_log_idx1)
顺序都相同,我如何才能使SQL Server充分利用这一点,从而避免树搜索成本?
这看起来像改变聚集索引的好机会Point_Log
其父集群point_id
外键:
CREATE TABLE Point_log
(
point_log_id int PRIMARY KEY NONCLUSTERED,
point_id int,
timestamp datetime,
value int
);
接着:
CREATE CLUSTERED INDEX C_PointLog ON dbo.Point_log(point_id);
原理:在获取给定pointid
point_log
记录时,这将减少point_log
上的读取IO
此外,鉴于Sql Server将向非唯一的聚集索引添加一个4字节的唯一化符 ,您也可以在群集上也包括替代PK,以使其唯一,即:
CREATE UNIQUE CLUSTERED INDEX C_PointLog ON dbo.Point_log(point_id, point_log_id);
如果每个point
都有很多point_logs
,并且假设对point_log.pointid
和point_log.timestamp
筛选的查询具有良好的选择性,则需要保留非聚集索引point_log_idx1 ( point_id asc, timestamp asc)
与物理写入磁盘,页面拆分和日志记录的成本相比,树搜索的成本可以忽略不计。
1)您绝对应该批量插入数据,而不是逐行插入数据。
2)为了减少point_log_idx1索引的页面拆分,您可以尝试在INSERT
语句中使用ORDER BY
。 它仍然不能保证磁盘上的物理顺序,但是可以保证将生成point_log_id IDENTITY
的顺序,并希望它将提示以该顺序处理源数据。 如果按请求的顺序处理源数据,则point_log_idx1索引的b树结构可能会增长,而不会造成不必要的昂贵页面拆分。
我正在使用SQL Server2008。我有一个系统在24/7中央数据库中收集大量监视数据。 最初,我是逐行插入数据。 然后我意识到每个插入都是一个单独的事务,并且系统大部分时间都花在了写入事务日志中。
最终,我开始使用接受表值参数的存储过程来批量插入数据。 就我而言,一批是几百到几千行。 在我的系统中,我仅将数据保留给定的天数,因此我会定期删除过时的数据。 为了保持系统性能稳定,我还定期重建索引。
在您的示例中,它可能如下所示。
首先,创建一个表类型:
CREATE TYPE [dbo].[PointValuesTableType] AS TABLE(
point_id int,
timestamp datetime,
value int
)
然后过程如下所示:
CREATE PROCEDURE [dbo].[InsertPointValues]
-- Add the parameters for the stored procedure here
@ParamRows dbo.PointValuesTableType READONLY
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
BEGIN TRANSACTION;
BEGIN TRY
INSERT INTO dbo.point_log
(point_id
,timestamp
,value)
SELECT
TT.point_id
,TT.timestamp
,TT.value
FROM @ParamRows AS TT
ORDER BY TT.point_id, TT.timestamp;
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
END CATCH;
END
在实践中,无论使用ORDER BY
还是不使用ORDER BY
,您都应该为系统测量更有效的方法。 您确实需要考虑INSERT
操作的性能以及后续查询的性能。
更快的插入可能导致更高的索引碎片,从而导致更慢的查询。
因此,在使用ORDER BY
或不使用ORDER BY
INSERT
之后,应该检查索引的碎片。 您可以使用sys.dm_db_index_physical_stats来获取索引统计信息。
返回SQL Server中指定表或视图的数据和索引的大小和碎片信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.