我正在将大量数据导入SQL Server数据库。源数据源自PgSql(包括表defs),我通过一些相当简单的正则表达式转换为TSql。这将创建没有主键的表。
据我了解,缺少主键/群集索引意味着数据存储在堆中。
导入完成后,我按如下方式添加PK:
ALTER TABLE someTable ADD CONSTRAINT PK_someTable PRIMARY KEY (id);
(请注意缺少CLUSTERED
关键字)。现在发生了什么?还是一堆?主键对查找有什么影响?这与添加标准索引有什么不同吗?
现在,请说如下我添加PK:
ALTER TABLE someTable ADD CONSTRAINT PK_someTable PRIMARY KEY CLUSTERED (id);
我认为这现在完全将表重组为基于行的结构,通过PK进行更有效的查找,但不太理想的插入特性。
我的假设是否正确?
如果我的导入按PK顺序插入数据,那么首先省略PK是否有任何好处?
答案 0 :(得分:3)
执行时
ALTER TABLE someTable ADD CONSTRAINT PK_someTable PRIMARY KEY (id);
如果someTable
上没有聚集索引,那么PK将是一个聚类PK。否则,如果在执行ALTER .. ADD ... PRIMARY KEY (id)
之前存在聚集索引,则PK将是非聚集PK。
- 测试#1
BEGIN TRAN;
CREATE TABLE dbo.MyTable
(
id INT NOT NULL,
Col1 INT NOT NULL,
Col2 VARCHAR(50) NOT NULL
);
SELECT i.name, i.index_id, i.type_desc
FROM sys.indexes i
WHERE i.object_id = OBJECT_ID(N'dbo.MyTable');
/*
name index_id type_desc
---- ----------- ---------
NULL 0 HEAP
*/
ALTER TABLE dbo.MyTable
ADD CONSTRAINT PK_MyTable PRIMARY KEY (id);
SELECT i.name, i.index_id, i.type_desc
FROM sys.indexes i
WHERE i.object_id = OBJECT_ID(N'dbo.MyTable');
/*
name index_id type_desc
----------- ----------- ---------
PK_MyTable 1 CLUSTERED
*/
ROLLBACK;
- 测试#2
BEGIN TRAN;
CREATE TABLE dbo.MyTable
(
id INT NOT NULL,
Col1 INT NOT NULL,
Col2 VARCHAR(50) NOT NULL
);
SELECT i.name, i.index_id, i.type_desc FROM sys.indexes i WHERE i.object_id = OBJECT_ID(N'dbo.MyTable');
/*
name index_id type_desc
---- ----------- ---------
NULL 0 HEAP
*/
CREATE CLUSTERED INDEX ix1
ON dbo.MyTable(Col1);
SELECT i.name, i.index_id, i.type_desc FROM sys.indexes i WHERE i.object_id = OBJECT_ID(N'dbo.MyTable');
/*
name index_id type_desc
---- ----------- ---------
ix1 1 CLUSTERED
*/
ALTER TABLE dbo.MyTable
ADD CONSTRAINT PK_MyTable PRIMARY KEY (id);
SELECT i.name, i.index_id, i.type_desc FROM sys.indexes i WHERE i.object_id = OBJECT_ID(N'dbo.MyTable');
/*
name index_id type_desc
---------- ----------- ------------
ix1 1 CLUSTERED
PK_MyTable 2 NONCLUSTERED
*/
ROLLBACK;
答案 1 :(得分:1)
在sql server中,如果不存在聚簇索引,则主键默认为聚簇。聚簇索引实际上意味着“索引”不会保存在单独的存储区域中(因为是非聚集索引),而是指数数据与相应的常规表数据“散布”。如果你对此有所了解,你会发现它们只能是1个集群索引。
聚集索引的真正优势在于数据接近索引数据,因此您可以在驱动器头“在区域内”时抓取两者。当您正在处理的数据表现出引用的位置时 - 当几乎相同值的行倾向于同时读取时,聚簇索引明显快于非clusted索引。
例如,如果您的主键是SSN,除非您正在处理相对于SSN随机排序的数据,否则您不会获得大的优势 - 尽管由于数据接近而您确实获得了优势。但是,如果您可以通过SSN预先输入聚类密钥,那么这是一个很大的优势。
所以,是的,聚集索引会对数据进行重新排序,以便与聚集索引混合。
答案 2 :(得分:0)
感谢您对该主题的精彩演示!
上面的结论是不错误,但它显示了索引的结构,而不是表格的结构。我认为以下SQL将显示实际表的信息:
select
o.name,
o.object_id,
case
when p.index_id = 0 then 'Heap'
when p.index_id = 1 then 'Clustered Index/b-tree'
when p.index_id > 1 then 'Non-clustered Index/b-tree'
end as 'Type'
from sys.objects o
inner join sys.partitions p on p.object_id = o.object_id
where o.name = 'MyTable';
您将看到MyTable已群集:
name object_id Type
------- ----------- -------------------
MyTable 1237579447 Clustered Index/b-tree