Sql-Server

一旦桌子變大,我能做些什麼來提高未來的性能嗎?

  • October 20, 2017

我創建了一個導入 600,000 行的 Excel 工作表的表。我將執行的大多數查詢都將使用C_CustomerID,它們將類似於下面的範例:

select * from testtable where C_CustomerID = 12345678

表定義為:

CREATE TABLE [dbo].[testtable](
   [id_card] [int] IDENTITY(1,1) NOT NULL,
   [C_CustomerID] [int] NOT NULL,
   [C_AccountID] [nvarchar](255) NULL,
   [C_ProductID] [varchar](20) NULL,
   .......... more columns here ...     
) ON [PRIMARY]

我創建了一個索引:

CREATE NONCLUSTERED INDEX [inx_profitability] ON [dbo].[testtable]
(
   [C_CustomerID] ASC
)

稍後我只會從 Excel 工作表中導入更多記錄。每 6 個月將導出大約 500,000 條新記錄。

一旦桌子變大,我能做些什麼來提高未來的性能嗎?

我正在執行 SQL Server 2012 和 Microsoft SQL Server Management Studio 11.0.3128.0。

如果所有查詢都採用以下形式:

select * from testtable where C_CustomerID = 12345678

那麼你已經擁有的並不是完全不合理的。從基表(目前是堆)中檢索非聚集索引未涵蓋的列是有成本的,但除非每個表有很多行,否則C_CustomerID這可能不是一個實際問題。

也就是說,目前的安排並不理想。SQL Server 可能會決定掃描整個堆以查找匹配項,而不是尋找非聚集 b 樹索引,然後執行多個單行查找。

在沒有任何其他考慮的情況下,我可能會用(非唯一)聚集索引替換非聚集索引:

DROP INDEX inx_profitability ON dbo.testtable;
GO
CREATE CLUSTERED INDEX [CX dbo.testtable C_CustomerID]
ON dbo.testtable (C_CustomerID);

聚集索引定義表中行的邏輯順序,並提供對整行的直接訪問(因此不需要查找)。在很大程度上,聚集索引在很大程度上是“免費的”,因為它不是具有(部分)數據副本的單獨結構。

對於具有相同 的行C_CustomerID,SQL Server 將添加一個隱藏的整數 ‘uniquifier’ 以確保每一行在內部都是唯一可辨識的。您不能直接引用此值,但它確實會增加一點成本。

如果您刪除行(問題提到導出),使其成為一個聚集表(通過添加聚集索引)也可能會改善表的未使用空間管理。

您可以選擇在上面(以及在執行維護時)建構的聚集索引上指定填充因子,例如通過添加WITH (FILLFACTOR = 70). 這將在葉級別為將來的插入保留一定比例的可用空間(請記住,行和頁面在邏輯上按 排序C_CustomerID)。70 的選擇完全是任意的。您選擇的值(如果有)完全取決於情況。如果所有查詢都如上所示,則可能幾乎不需要指定填充因子。

原則上,每個表都應該有一個鍵(主鍵或其他鍵),它強制執行任何真實世界的列組合唯一標識每一行。在您的情況下,這可能是非聚集主鍵或唯一約束。

引用自:https://dba.stackexchange.com/questions/188802