ana*_*123 2 database-design sql-server index-tuning sql-server-2012
我创建了一个导入 600,000 行 Excel 工作表的表格。我将运行的大多数查询都将使用C_CustomerID
,它们将如下例所示:
select * from testtable where C_CustomerID = 12345678
Run Code Online (Sandbox Code Playgroud)
表定义为:
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]
Run Code Online (Sandbox Code Playgroud)
我创建了一个索引:
CREATE NONCLUSTERED INDEX [inx_profitability] ON [dbo].[testtable]
(
[C_CustomerID] ASC
)
Run Code Online (Sandbox Code Playgroud)
稍后我只会从 Excel 工作表导入更多记录。每 6 个月将导出约 500,000 条新记录。
一旦表变大,我可以做些什么来提高未来的性能?
我正在运行 SQL Server 2012 和 Microsoft SQL Server Management Studio 11.0.3128.0。
如果所有查询都是以下形式:
select * from testtable where C_CustomerID = 12345678
Run Code Online (Sandbox Code Playgroud)
那么你已经拥有的也不是完全没有道理的。从基表(当前为堆)检索非聚集索引未涵盖的列是有成本的,但除非每个 有很多行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);
Run Code Online (Sandbox Code Playgroud)
聚集索引定义了表中行的逻辑顺序,并提供对整行的直接访问(因此不需要查找)。在很大程度上,聚集索引在很大程度上是“免费的”,因为它不是带有(部分)数据副本的单独结构。
对于具有相同C_CustomerID
. 您不能直接引用此值,但它确实会增加一些开销。
如果您删除行(问题提到导出),则将其设为聚簇表(通过添加聚簇索引)也可能会改善表的未使用的未来空间管理。
您可以选择在上面的聚集索引构建上(以及在执行维护时)指定填充因子,例如通过添加WITH (FILLFACTOR = 70)
. 这将在叶级保留一定比例的空闲空间以供将来插入(请记住,行和页按 逻辑排序C_CustomerID
)。70 的选择完全是任意的。您选择的值(如果有)完全取决于情况。如果所有查询都如上所示,则可能几乎不需要指定填充因子。
原则上,每个表都应该有一个键(主键或其他键),以强制执行任何真实世界的列组合唯一标识每一行。在您的情况下,这可能是非聚集主键或唯一约束。