Composite Clustered Index in SQL Server - sql-server

I have a table with a IDENTITY Column as Primary Key (a classic ID column).
SQL Server create automatically a Clustered Index for that Primary Key.
My question is:
Can I have a only single CLUSTERED INDEX composite with more columns?
If yes, how can I drop the default clustered index and recreate a new one with this attributes.
Thanks for your support

Yes, you can only have a single clustered index per table - the data is physically arranged by that index, so you cannot have more than one.
I would however not advise to use a composite clustered index. Why? Because the clustered index should always be:
as small as possible - INT with 4 byte is perfect
stable - never change, so you don't have rippling updates through all your indices
unique - otherwise, SQL Server will have to "uniquify" your entries with artifical 4-byte values
optimal would be: ever increasing
INT IDENTITY is perfect as a clustered index - I would advise you keep it that way.
The clustered index column (or set of columns) is also added to each and every entry of each and every nonclustered index on that same table - so if you make your clustered index large, 20, 50 bytes or more, you begin to be wasting a lot of space - on disk and in your server's memory, which generally degrades your system performance.
Read all about clustered indices and what they should be to be good clustered indices here:
GUIDs as PRIMARY KEYs and/or the clustering key
The Clustered Index Debate Continues...
Ever-increasing clustering key - the Clustered Index Debate..........again!

Related

Is there a difference if I don't define a Primary Key in a table

I've been using SQL Server for quite a while, I always create database with design view.
The steps I took to create the table is:
Right Click Table -> New Table
I always have the first column as SOMETHING_ID (int) -> I make SOMETHING_ID as Identity with auto increment of 1
-> Then I add other columns
-> Save and use
As you can see, I didn't define SOMETHING_ID by right clicking it and SET AS PRIMARY.
Will there be any performance impact in this case?
Yes, it can impact performance because creating the primary key essentially makes an index for it. So when you join tables on that key it will improve performance greatly if there are indexes.... particularly if you have lots of data.
What you really need to do is to create a clustered index. A primary index, by default is a clustered index (but you can create a primary index that is not a clustered index). A table without a clustered index is called a heap and except for very special occasions you should have a clustered index on every table. A primary index is a index that has only unique values and does not have any (not even one) null index value.
A query that uses a clustered index is usually a very effective one but if there is not clustered index (even if the table has indexes) it can end up with forwarding pointers all over the place and searching for all the rows for a given customer can require SQL Server to read many, many pages.
To create a clustered index on a table you can use syntax such as
create clustered index ix1_table1 on table1(id)
The column(s) used in a index of any kind can occur anywhere in a table and does not necessarily have to be identity columns.
By not creating Primary key you're breaking the rule of First Normal Form in Normalization.
Disadvantages of not having Primary Key
Chances of Duplicates
Your table won't be clustered with clustered index
You won't be able to do Primary Key-Foreign Key relationship with other table.

Index performance, clustered vs non clustered

If a table only needs 1 index, it seems like clustered is generally the way to go. It is faster because it does not have to reference back to the data via a key, and it also doesn't take disk space the way a non clustered index does.
My question is with multiple indexes, is it better to remove clustered index all together? The logic behind this is that if you have non clustered indexes WITH a clustered index, they don't directly refer back to the actual data rows anymore, but to the clustered index instead. So it seems like there would be a significant performance hit by using the clustered index as a proxy. It seems like the best thing to do would be to not use clustered indexes at all if you think you will need more than 1 index on the table.
If the table has a proper clustered index there is no benefit to removing it.
If you have several indexes then pick the best candidate for clustered.
Typically it is your PK.
When you create a PK by default it clustered.
PK is your best candidate for clustered unless you have specific reason not to use it.
I don't follow your assertion.
"If you have non clustered indexes WITH a clustered index, they don't
refer back to the actual data rows anymore, but to the clustered index
instead. So it seems like there would be a significant performance
hit."
If the clustered index is in the data then referring to the clustered index is referring to the data. The data is physically organized by the clustered index. Where is the significant performance hit?
Clustered Index Design Guidelines
With few exceptions, every table should have a clustered index defined
If one of those few exception was another index then it would be called out.
Another non-clustered index is not a reason to not have a clustered index.
Nonclustered Index Structures
The row locators in nonclustered index rows are either a pointer to a row or are a clustered index key for a row, as described in the following:
If the table is a heap, which means it does not have a clustered
index, the row locator is a pointer to the row. The pointer is built
from the file identifier (ID), page number, and number of the row on
the page. The whole pointer is known as a Row ID (RID).
If the table has a clustered index, or the index is on an indexed
view, the row locator is the clustered index key for the row. If the
clustered index is not a unique index, SQL Server makes any duplicate
keys unique by adding an internally generated value called a
uniqueifier. This four-byte value is not visible to users. It is only
added when required to make the clustered key unique for use in
nonclustered indexes. SQL Server retrieves the data row by searching
the clustered index using the clustered index key stored in the leaf
row of the nonclustered index.
They had the option use a RID even if there was a PK. Why do you think clustered index is slower?

Nonclustered index uses key into clustered index instead of address?

In the documentation for SQL server 2008 R2 is stated:
Wide keys are a composite of several columns or several large-size columns. The key values from the clustered index are used by all nonclustered indexes as lookup keys. Any nonclustered indexes defined on the same table will be significantly larger because the nonclustered index entries contain the clustering key and also the key columns defined for that nonclustered index.
Does this mean, that when there is a search using non-clustered index, than the clustered indes is search also? I originally thought that the non-clustered index contains ditrectly the address of the page (block) with the row it references. From the text above it seems that it contains just the key from the non-clustered index instead of the address.
Could somebody explain please?
Yes, that's exactly what happens:
SQL Server searches for your search value in the non-clustered index
if a match is found, in that index entry, there's also the clustering key (the column or columns that make up the clustered index)
with that clustered key, a key lookup (often also called bookmark lookup) is now performed - the clustered index is searched for that value given
when the item is found, the entire data record at the leaf level of the clustered index navigation structure is present and can be returned
SQL Server does this, because using a physical address would be really really bad:
if a page split occurs, all the entries that are moved to a new page would be updated
for all those entries, all nonclustered indices would also have to be updated
and this is really really bad for performance.
This is one of the reasons why it is beneficial to use limited column lists in SELECT (instead of always SELECT *) and possibly even include a few extra columns in the nonclustered index (to make it a covering index). That way, you can avoid unnecessary and expensive bookmark lookups.
And because the clustering key is included in each and every nonclustered index, it's highly important that this be a small and narrow key - optimally an INT IDENTITY or something like that - and not a huge structure; the clustering key is the most replicated data structure in SQL Server and should be a small as possible.
The fact that these bookmark lookups are relatively expensive is also one of the reasons why the query optimizer might opt for an index scan as soon as you select a larger number of rows - at at time, just scanning the clustered index might be cheaper than doing a lot of key lookups.

Primary Key without any index in a table?

I am just wondering can we create a Primary key on a table in sql server without any type of index on it?
No. As an implementation detail, SQL Server maintains the primary key using an index. You cannot prevent it from doing so. The primary key:
Ensures that no duplicate key values exist
Allows individual rows to be identified/accessed
SQL Server already has mechanisms that offer these features - unique indexes - so it uses those to enforce the constraint.
You can create a table with a primary key that is not a clustered index by adding the keyword NONCLUSTERED after the primary key word.
Actually indexing functions in the same way a book is traversed. One cannot go to a particular page or topic unless there is page number and their relation to the topics. This "Paging" (ordering) of rows is done physically by Clustered Index in SQL Server. If there is no PK in a table one can add clustered index on any unique-key qualifying column(s). As there cannot be more than one clustered index on a table, and all other non-clustered indices depend on clustered index for search/traversal, you cannot make a column PK without clustered index.

SQL Server Indexes - Non-Clustered Index on HEAP

We have got 221gb table in our SQL Database, mainly duplicate data.
Team has created NON-CLUSTERED index on HEAP. Does really this help in terms of performannce?
Should we put IDENTITY column in table and then create CLUSTERED index AND after that we can create NON clustered indexes.
It Depends
On the usage pattern and structure of the data.
Is the non-clustered index covering?
Is the data in the table ever changing?
A heap table with a non-clustered index (or indexes) which are covering can outperform a clustered index where the clustered index is the only "index" (a clustered index is obviously always covering, but may not be optimal for seeks)
Remember a clustered index is not an index (in the sense of a lookup based on a key into a location where the data is stored), it's the whole table organized by a choice of index. In a real (non-clustered) index, only the keys and included columns are included in the index and this means that (generally) more rows can be stored per database page and less data is read unnecessarily.
Most tables should have a clustered index, but the choice of non-clustered indexes is where most of your performance comes from.

Resources