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.
Related
Here is one of the definitions I found for clustered Index:
When is a file is organized so that the ordering of data records is
the same as or close to the ordering of data entries in some index, we
say that the index is clustered.
I'm having trouble understanding the above sentence regarding the clustered Indexes. The things I know about clustered index are:
Clustered indexes reorders the way the records are physically stored in the table, so only one clustered index is possible
Clustered index is created on non key attribute
Well for clustered index we have many view to look into
A clustered index is a type of index where the table records are physically re-ordered to match the index.
Clustered indexes are efficient on columns that are searched for a range of values. After the row with first value is found using a clustered index, rows with subsequent index values are guaranteed to be physically adjacent, thus providing faster access for a user query or an application
You also have to understand the Non-Clustered Index
In other words, a clustered index stores the actual data, where a non-clustered index is a pointer to the data. In most DBMSs, you can only have one clustered index per table, though there are systems that support multiple clusters (DB2 being an example).
Like a regular index that is stored unsorted in a database table, a clustered index can be a composite index, such as a concatenation of first name and last name in a table of personal information.
There are several example and explanations. And this is What do Clustered and Non clustered index actually mean? one of them.
I have a database where all tables include a Site column (char(4)) and a PrimaryId column (int).
Currently the clustered index on all tables is the combination of these two columns. Many customers only have one site so in those cases I think it definitely makes sense to change the clustered index to only include the PrimaryId.
In cases where there are multiple sites though, I'm wondering whether it would still be advantageous to only use the PrimaryId as the clustered index? Might having a smaller clustered index produce better performance than having a unique one?
In case it's relevant, there are generally not going to be more than a few sites. 10 sites would be a lot.
The answer is simple UNIQUE index is always better then NON-UNIQUE. There is some maths behind it but the greater uniqueness is the faster server can look up a record from index.
CLUSTERED index is great as they physically order the records on disk and it always a good idea to use CLUSTERED INDEX on UNIQUE keys.
CLUSTER INDEX with PRIMARY KEY give very good performance with large data. If your data is not high in column then it will not matter much.
I have recently read a article about how nonclustered indexes are matching table rows. I will try to summarize what I believe is relevant to your question.
There are two types of tables (in the context of indexes):
heap - a table without clustered index
clustered index - a table with clustered index
In the first case a nonclustered index is matching rows using RIP-Based bookmarks which has the following format:
file number - page number - row number
and a nonclustered index is looking like this:
You can see the RIP bookmark is in red.
Generally speaking, the rows of a heap do not move; once they have
been inserted into a page they remain on that page. To be more
technically-precise: rows in a heap seldom move, and when they do
move, they leave a forwarding address at the old location. The rows of
a clustered index, however, can move; that is, they can be relocated
to another page during data modification or index reorganization.
In the second the nonclustered index is using the index key of the clustered index as a bookmark and the clustered index itself should meet several criteria:
it must be unique
it should be short
it should be static
I am going to describe the first criteria (the others are described in the link below):
Each index entry bookmark must allow SQL Server to find the one row in
the table that corresponds to that entry. If you create a clustered
index that is not unique, SQL Server will make the clustered index
unique by generating an additional value that "breaks the tie" for
duplicate keys. This extra value is generated by SQL Server to create
uniqueness is called the uniquifier and is transparent to any client
application. You should carefully consider whether or not to allow
duplicates in a clustered index, for the following reasons:
Generating uniquifiers is extra overhead. SQL Server must decide, at
insert time, if a new row's key is a duplicate of an existing row's
key; and, if so, generate a uniquifier values to add to the new row
The uniquifier is a meaningless piece of information; a meaningless
piece of information that is being propagated into the table's
nonclustered indexes. It's usually better to propagate a meaningful
piece of information into the nonclustered indexes.
The whole article can be found here.
Recently I found a couple of tables in a Database with no Clustered Indexes defined.
But there are non-clustered indexes defined, so they are on HEAP.
On analysis I found that select statements were using filter on the columns defined in non-clustered indexes.
Not having a clustered index on these tables affect performance?
It's hard to state this more succinctly than SQL Server MVP Brad McGehee:
As a rule of thumb, every table should have a clustered index. Generally, but not always, the clustered index should be on a column that monotonically increases–such as an identity column, or some other column where the value is increasing–and is unique. In many cases, the primary key is the ideal column for a clustered index.
BOL echoes this sentiment:
With few exceptions, every table should have a clustered index.
The reasons for doing this are many and are primarily based upon the fact that a clustered index physically orders your data in storage.
If your clustered index is on a single column monotonically increases, inserts occur in order on your storage device and page splits will not happen.
Clustered indexes are efficient for finding a specific row when the indexed value is unique, such as the common pattern of selecting a row based upon the primary key.
A clustered index often allows for efficient queries on columns that are often searched for ranges of values (between, >, etc.).
Clustering can speed up queries where data is commonly sorted by a specific column or columns.
A clustered index can be rebuilt or reorganized on demand to control table fragmentation.
These benefits can even be applied to views.
You may not want to have a clustered index on:
Columns that have frequent data changes, as SQL Server must then physically re-order the data in storage.
Columns that are already covered by other indexes.
Wide keys, as the clustered index is also used in non-clustered index lookups.
GUID columns, which are larger than identities and also effectively random values (not likely to be sorted upon), though newsequentialid() could be used to help mitigate physical reordering during inserts.
A rare reason to use a heap (table without a clustered index) is if the data is always accessed through nonclustered indexes and the RID (SQL Server internal row identifier) is known to be smaller than a clustered index key.
Because of these and other considerations, such as your particular application workloads, you should carefully select your clustered indexes to get maximum benefit for your queries.
Also note that when you create a primary key on a table in SQL Server, it will by default create a unique clustered index (if it doesn't already have one). This means that if you find a table that doesn't have a clustered index, but does have a primary key (as all tables should), a developer had previously made the decision to create it that way. You may want to have a compelling reason to change that (of which there are many, as we've seen). Adding, changing or dropping the clustered index requires rewriting the entire table and any non-clustered indexes, so this can take some time on a large table.
I would not say "Every table should have a clustered index", I would say "Look carefully at every table and how they are accessed and try to define a clustered index on it if it makes sense". It's a plus, like a Joker, you have only one Joker per table, but you don't have to use it. Other database systems don't have this, at least in this form, BTW.
Putting clustered indices everywhere without understanding what you're doing can also kill your performance (in general, the INSERT performance because a clustered index means physical re-ordering on the disk, or at least it's a good way to understand it), for example with GUID primary keys as we see more and more.
So, read Tim Lehner's exceptions and reason.
Performance is a big hairy problem. Make sure you are optimizing for the right thing.
Free advice is always worth it's price, and there is no substitute for actual experimentation.
The purpose of an index is to find matching rows and help retrieve the data when found.
A non-clustered index on your search criteria will help to find rows, but there needs to be additional operation to get at the row's data.
If there is no clustered index, SQL uses an internal rowId to point to the location of the data.
However, If there is a clustered index on the table, that rowId is replaced by the data values in the clustered index.
So the step of reading the rows data would not be needed, and would be covered by the values in the index.
Even if a clustered index isn't very good at being selective, if those keys are frequently most or all of the results requested - it may be helpful to have them as the leaf of the non-clustered index.
Yes you should have clustered index on a table.So that all nonclustered indexes perform in better way.
Consider using a clustered index when Columns that contain a large number of distinct values so to avoid the need for SQL Server to add a "uniqueifier" to duplicate key values
Disadvantage : It takes longer to update records if only when the fields in the clustering index are changed.
Avoid clustering index constructions where there is a risk that many concurrent inserts will happen on almost the same clustering index value
Searches against a nonclustered index will appear slower is the clustered index isn't build correctly, or it does not include all the columns needed to return the data back to the calling application. In the event that the non-clustered index doesn't contain all the needed data then the SQL Server will go to the clustered index to get the missing data (via a lookup) which will make the query run slower as the lookup is done row by row.
Yes, every table should have a clustered index. The clustered index sets the physical order of data in a table. You can compare this to the ordering of music at a store, by bands name and or Yellow pages ordered by a last name. Since this deals with the physical order you can have only one it can be comprised by many columns but you can only have one.
It’s best to place the clustered index on columns often searched for a range of values. Example would be a date range. Clustered indexes are also efficient for finding a specific row when the indexed value is unique. Microsoft SQL will place clustered indexes on a PRIMARY KEY constraint automatically if no clustered indexes are defined.
Clustered indexes are not a good choice for:
Columns that undergo frequent changes
This results in the entire row moving (because SQL Server must keep
the data values of a row in physical order). This is an important
consideration in high-volume transaction processing systems where
data tends to be volatile.
Wide keys
The key values from the clustered index are used by all
nonclustered indexes as lookup keys and therefore are stored in each
nonclustered index leaf entry.
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.
This question already has answers here:
What are the differences between a clustered and a non-clustered index?
(13 answers)
Closed 7 years ago.
I need to add proper index to my tables and need some help.
I'm confused and need to clarify a few points:
Should I use index for non-int columns? Why/why not
I've read a lot about clustered and non-clustered index yet I still can't decide when to use one over the other. A good example would help me and a lot of other developers.
I know that I shouldn't use indexes for columns or tables that are often updated. What else should I be careful about and how can I know that it is all good before going to test phase?
A clustered index alters the way that the rows are stored. When you create a clustered index on a column (or a number of columns), SQL server sorts the table’s rows by that column(s). It is like a dictionary, where all words are sorted in alphabetical order in the entire book.
A non-clustered index, on the other hand, does not alter the way the rows are stored in the table. It creates a completely different object within the table that contains the column(s) selected for indexing and a pointer back to the table’s rows containing the data. It is like an index in the last pages of a book, where keywords are sorted and contain the page number to the material of the book for faster reference.
You really need to keep two issues apart:
1) the primary key is a logical construct - one of the candidate keys that uniquely and reliably identifies every row in your table. This can be anything, really - an INT, a GUID, a string - pick what makes most sense for your scenario.
2) the clustering key (the column or columns that define the "clustered index" on the table) - this is a physical storage-related thing, and here, a small, stable, ever-increasing data type is your best pick - INT or BIGINT as your default option.
By default, the primary key on a SQL Server table is also used as the clustering key - but that doesn't need to be that way!
One rule of thumb I would apply is this: any "regular" table (one that you use to store data in, that is a lookup table etc.) should have a clustering key. There's really no point not to have a clustering key. Actually, contrary to common believe, having a clustering key actually speeds up all the common operations - even inserts and deletes (since the table organization is different and usually better than with a heap - a table without a clustering key).
Kimberly Tripp, the Queen of Indexing has a great many excellent articles on the topic of why to have a clustering key, and what kind of columns to best use as your clustering key. Since you only get one per table, it's of utmost importance to pick the right clustering key - and not just any clustering key.
GUIDs as PRIMARY KEY and/or clustered key
The clustered index debate continues
Ever-increasing clustering key - the Clustered Index Debate..........again!
Disk space is cheap - that's not the point!
Marc
You should be using indexes to help SQL server performance. Usually that implies that columns that are used to find rows in a table are indexed.
Clustered indexes makes SQL server order the rows on disk according to the index order. This implies that if you access data in the order of a clustered index, then the data will be present on disk in the correct order. However if the column(s) that have a clustered index is frequently changed, then the row(s) will move around on disk, causing overhead - which generally is not a good idea.
Having many indexes is not good either. They cost to maintain. So start out with the obvious ones, and then profile to see which ones you miss and would benefit from. You do not need them from start, they can be added later on.
Most column datatypes can be used when indexing, but it is better to have small columns indexed than large. Also it is common to create indexes on groups of columns (e.g. country + city + street).
Also you will not notice performance issues until you have quite a bit of data in your tables. And another thing to think about is that SQL server needs statistics to do its query optimizations the right way, so make sure that you do generate that.
A comparison of a non-clustered index with a clustered index with an example
As an example of a non-clustered index, let’s say that we have a non-clustered index on the EmployeeID column. A non-clustered index will store both the value of the
EmployeeID
AND a pointer to the row in the Employee table where that value is actually stored. But a clustered index, on the other hand, will actually store the row data for a particular EmployeeID – so if you are running a query that looks for an EmployeeID of 15, the data from other columns in the table like
EmployeeName, EmployeeAddress, etc
. will all actually be stored in the leaf node of the clustered index itself.
This means that with a non-clustered index extra work is required to follow that pointer to the row in the table to retrieve any other desired values, as opposed to a clustered index which can just access the row directly since it is being stored in the same order as the clustered index itself. So, reading from a clustered index is generally faster than reading from a non-clustered index.
In general, use an index on a column that's going to be used (a lot) to search the table, such as a primary key (which by default has a clustered index). For example, if you have the query (in pseudocode)
SELECT * FROM FOO WHERE FOO.BAR = 2
You might want to put an index on FOO.BAR. A clustered index should be used on a column that will be used for sorting. A clustered index is used to sort the rows on disk, so you can only have one per table. For example if you have the query
SELECT * FROM FOO ORDER BY FOO.BAR ASCENDING
You might want to consider a clustered index on FOO.BAR.
Probably the most important consideration is how much time your queries are taking. If a query doesn't take much time or isn't used very often, it may not be worth adding indexes. As always, profile first, then optimize. SQL Server Studio can give you suggestions on where to optimize, and MSDN has some information1 that you might find useful
faster to read than non cluster as data is physically storted in index order
we can create only one per table.(cluster index)
quicker for insert and update operation than a cluster index.
we can create n number of non cluster index.