【问题标题】:Better insert performance on a table only with a clustered index or a table without any index on SqlServer 2008?在 SqlServer 2008 上仅具有聚集索引的表或没有任何索引的表上的插入性能更好?
【发布时间】:2024-04-12 00:10:03
【问题描述】:

注意,我不是在谈论聚集索引与非聚集索引的对比,我是指聚集索引与完全没有索引相比的插入性能。

我看到很多链接如下所述,由于 IAM/PFS/bitmap/...,即使对于插入操作,聚集索引也具有更好的性能,但根据我的测试,似乎没有索引比簇索引,有什么问题?

Removing a Primary Key (Clustered Index) to increase Insert performance http://support.microsoft.com/kb/297861

我的测试脚本:

-------------------------------------------
--prepare table with clustered index
CREATE TABLE [dbo].[BigTable_CI](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [BigChar] [char](4100) NOT NULL
) 
GO

CREATE CLUSTERED INDEX CIX_BigTable_CI
    ON BigTable_CI(id)
GO


ALTER TABLE [dbo].[BigTable_CI] 
ADD CONSTRAINT [DF_BigTable_BigChar_CI]  DEFAULT ('a') FOR [BigChar]
GO

CREATE PROCEDURE [dbo].[AddDataToBigTable_CI]
(@NumberOfRows bigint)    
AS
    SET NOCOUNT ON;

    DECLARE @Counter int = 0;
    DECLARE @Start   datetime = GETDATE();
    DECLARE @End     datetime;
    DECLARE @ElapsedTime int = 0; 
    DECLARE @RowsPerSecond int = 0;

    WHILE (@Counter < @NumberOfRows)
        BEGIN
           INSERT INTO dbo.BigTable_CI DEFAULT VALUES;
           SELECT @Counter += 1;
        END; 

    -- Calculate elapsed time and rows/second
    SET @End = GETDATE(); 
    SET @ElapsedTime = CONVERT(INTEGER, DATEDIFF (second, @Start, @End));
    SET @RowsPerSecond = @NumberOfRows/@ElapsedTime;

    -- Record results in local table
    INSERT INTO dbo.Results
    (StartTime, EndTime, ElapsedTime, NumberOfRows, RowsPerSecond) 
    VALUES (@Start, @End, @ElapsedTime, @NumberOfRows, @RowsPerSecond);

    RETURN;


-------------------------------------------
--prepare table without any index at all.
CREATE TABLE [dbo].[BigTable_NI](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [BigChar] [char](4100) NOT NULL
) 
GO

ALTER TABLE [dbo].[BigTable_NI] 
ADD CONSTRAINT [DF_BigTable_BigChar_NI]  DEFAULT ('a') FOR [BigChar]
GO

CREATE PROCEDURE [dbo].[AddDataToBigTable_NI]
(@NumberOfRows bigint)    
AS
    SET NOCOUNT ON;

    DECLARE @Counter int = 0;
    DECLARE @Start   datetime = GETDATE();
    DECLARE @End     datetime;
    DECLARE @ElapsedTime int = 0; 
    DECLARE @RowsPerSecond int = 0;

    WHILE (@Counter < @NumberOfRows)
        BEGIN
           INSERT INTO dbo.BigTable_NI DEFAULT VALUES;
           SELECT @Counter += 1;
        END; 

    -- Calculate elapsed time and rows/second
    SET @End = GETDATE(); 
    SET @ElapsedTime = CONVERT(INTEGER, DATEDIFF (second, @Start, @End));
    SET @RowsPerSecond = @NumberOfRows/@ElapsedTime;

    -- Record results in local table
    INSERT INTO dbo.Results
    (StartTime, EndTime, ElapsedTime, NumberOfRows, RowsPerSecond) 
    VALUES (@Start, @End, @ElapsedTime, @NumberOfRows, @RowsPerSecond);

    RETURN;   

-------------------------------------------
--prepare the results table
    create table dbo.Results 
    (
        StartTime datetime, 
        EndTime datetime, 
        ElapsedTime int, 
        NumberOfRows int, 
        RowsPerSecond int
    )

-------------------------------------------
--run scripts:
    exec [dbo].[AddDataToBigTable_NI] 1000000
    exec [dbo].[AddDataToBigTable_CI] 1000000

【问题讨论】:

标签: sql-server performance insert clustered-index


【解决方案1】:

对于任何插入操作,没有索引比使用索引更快。当您在表上有索引时,在插入每一行之后,数据库服务器必须在位图索引或索引存储库中分配对该行的引用,这对服务器来说是开销。这会影响每秒插入的行数。

【讨论】: