Moving an index which underlies a PK constraint - sql-server

SQL Server 2012 SP3
I've got a table with a clustered unique index which I want to move to the SECONDARY filegroup.
The standard method is to ALTER TABLE ... DROP CONSTRAINT and then ALTER TABLE ... ADD CONSTRAINT it back again in the new filegroup. However, there's a chain of FKs which I'd have to drop and recreate.
Is there any other way to move the underlying data without lots of drops?

Use CREATE UNIQUE CLUSTERED INDEX...WITH(DROP_EXISTING=ON) to move the primary key index to a different filegroup. This will also avoid the sort.
CREATE UNIQUE CLUSTERED INDEX PK_YourTable ON dbo.YourTable(YourPrimaryKeyColumn)
WITH(DROP_EXISTING=ON)
ON [YourSecondaryFileGroup];

Related

Clustering key goes up to tree with non-clustered index in SQL Server

It seems in SQL Server before version 2019, the clustering key/keys goes up to tree structure with not unique non-clustered index. With bigger and multiple clustering key/keys, you gain much more wider and taller tree that costs you more storage size and memory size.
Because of that we used to separate PK from clustered key my questions are
Have SQL Server 2019 and Azure changed in non-clustered indexing or not?
Heaps do not have clustering key/keys at all, what's the way of indexing in heaps?
Have SQL Server 2019 and Azure changed in non-clustered indexing or not
This behavior is older than many people on this site.
Because of that we used to separate PK from clustered
That is an almost-always-unnecessary micro-optimization.
Heaps do not have clustering key/keys at all, what's the way of indexing in heaps
Non-clustered non-unique indexes always have the row locator as index keys. For heaps the row locator is the ROWID (FileNo,PageNo,SlotNo).
If you want move the rows out from the leaf level of your wide PK, it's typically for a very large table. And so moving the rows to a clustered columstore index can be a good option. To do that just drop the clustered PK (this will leave the leaf level as a heap), create the CCI, and then recreate the PK as a nonclustered PK. eg
drop table if exists t
go
create table t(id int not null, a int, b int)
alter table t
add constraint pk_t
primary key clustered(id)
go
alter table t drop constraint pk_t
create clustered columnstore index cci_t on t
alter table t
add constraint pk_t
primary key nonclustered (id)
And if you have other non-clustered indexes drop them first, and only recreate them afterwords if you really need to. IE unique indexes, indexes supporting a foreign key, or indexes need to support specific queries. A CCI typically doesn't need lots of indexes since it's so efficient to scan.

Creating clustered primary key index takes a very long time in SQL Server?

I have a table with millions of records and it is taking a very long time to create the clustered index on its primary key.
What are the factors required in consideration to faster the process to creating PK clustered on it?
I have triggers, views, non-clustered indexes, foreign keys and some auto created statistics & statistics on non-clustered indexes.
Do the following:
Create a new table
Create a clustered index for it
Create the trigger and disable them
Copy all data from the old table to the new table
Finally, do the following:
sp_rename '<Current_old_Table>',<Current_old_Table_BAK>'
sp_rename '<New_Table>',<Current_Table_BAK>'

Effects of dropping PK on other indexes

I need to update a large number of keys in a large SQL Server 2005 database and will be dropping FKs and PKs on a bunch of tables, doing the update (which replaces the values of the PK/FK) and then adding the FK and PK again.
My questions are:
Will this process have any effect on exsiting indexes that exist on those tables, either
indexes that include the PK/FK fields or indexes on other unaffected fields. ie will all indexes still exists, will they need a rebuild?
Will this process affect table statistics, requiring a recalc?
Many thanks
If you drop a PK (which is usually a clustered index) SQL Server will drop and recreate all non clustered indexes(this is needed because if you have a clustered index the non clustered indexes point to the clustered index). If you don't have a clustered index (a heap) the non clustered indexes point to the data row
rebuilding a clustered index will automatically update statistics, a reorg won't
If you created the keys with cascade update then they should be updated automatically
example
create table pri(id int not null primary key)
go
create table ForeignK(fid int not null)
go
ALTER TABLE dbo.ForeignK ADD CONSTRAINT
FK_ForeignK_pri FOREIGN KEY
(fid) REFERENCES dbo.pri(id) ON UPDATE CASCADE
ON DELETE NO ACTION
insert pri values(1)
insert ForeignK values(1)
now update the PK table
update pri set id = 5
go
this will now be 5 also
select * from ForeignK
Every change in indexed column has a propagation in structure change.
For foreign key you could disable them and then rebuild. For private key only thing you can do is to rebuild them. I think that SQLMenace explained it clearly why.
More

SQL Server: changing the filegroup of an index (which is also a PK)

We're doing a cleanup on a group of databases, and the first step is to get all indexes in the database into the correct filegroups.
Currently, those indexes are mixed between the DATA filegroup and the INDEXES filegroup; they all need to move to the INDEXES filegroup.
This can be done easily enough in script I guess, however how do you best handle an index on a Primary Key?
The following command
DROP INDEX table.indexname
produces the error:
An explicit DROP INDEX is not allowed
on index 'Answer.PK_Answer'. It is
being used for PRIMARY KEY constraint
enforcement.
So what is the best way? Do I need to drop the Primary Key, then drop the Index, then re-create the primary key and finally re-create the index on the correct filegroup? Are there any drawbacks to this method?
You can try the below statement which drops and recreates the index on the index filegroup
CREATE CLUSTERED INDEX PK_Answer
ON tablename(Answer)
WITH (DROP_EXISTING = ON);
Since he has a primary key:
CREATE UNIQUE CLUSTERED INDEX PK_Answer ON tablename(Answer) WITH (DROP_EXISTING = ON);
In case anyone else needed this information (I did), add the FILEGROUP at the end if you wish to MOVE the recreated PRIMARY KEY to another location. Neither of the previous answers stipulated this portion:
CREATE UNIQUE CLUSTERED INDEX PK_TableName_Answer ON TableName(Answer) WITH(DROP_EXISTING = ON) ON [INDEX];

SQL Server: Alter a clustered primary index to an non-clustered

How do I alter a primary clustered index to become a non-clustured index. (Being a "secondary" table I want to use the clustured index for the foreign key column of the "header" table.)
This doen't work for me (error seems reasonable :)
DROP INDEX ClientUsers.PK_ClientUsers
CREATE UNIQUE CLUSTERED INDEX IDX_ClientUsers_Id ON ClientUsers(Id)
Msg 3723, Level 16, State 4, Line 7
An explicit DROP INDEX is not allowed on index 'ClientUsers.PK_ClientUsers'.
It is being used for PRIMARY KEY constraint enforcement.
I think you will have to:
Drop the FK
Drop the PK
Drop the clustered index
Recreate the PK
Recreate the FK
Recreate the clustered index on the FK column
and then optionally create a secondry index on the PK column
Have you tried dropping the PRIMARY KEY constraint on the table as well - then dropping the index - then re-adding both?
ALTER TABLE table_name DROP primary key

Resources