SQL Server composite unique key performance - sql

I have 6 columns where I want to apply composite unique key for prevent duplication, is it safe as performance respect?
Consider we will perform CRUD on behave of that 6 composite keys.

If you are asking whether an index with six columns is "safe", then it is perfectly fine. If your data model wants the combination of the six columns to be unique, then a unique index or unique constraint (which is implemented using a unique index) is how this is enforced.
There is overhead to an index -- whether it has one column or six. Generally, the cost is low enough to not be an issue. And the gains in data integrity and faster queries outweigh cost.
Do note that there is a limit to the overall size of the keys for any index. If your data values exceed that size, then you will not be able to maintain the index.

composite unique key on 6 columns
It depend upon real example.First thing come to mind is whether how this table is Normalize,or Denormalize ?
It also depend upon each column data type,and how each combination are populated.
This will be really very wide index.Cost of index will increase.
There will be very high Index fragmentation.
So not only cost of CRUD will increase,Select query will also suffer.
Because of high index cost ,optimizer will often choose Index Scan.
However, if you create Clsutered index on INT Identity column.
This will improve your CRUD performance.
Then Create Composite Unique keys with most selective column first.
In other word order of columns in composite index is important.

Related

Is unique composite index as effective as non-composite for queries on first column?

I have a table with b-tree index on column A (non-unique). Now I want to add a check for uniqueness of column A and column B combination when inserting, so I want to add a unique composite index (A, B).
Should I drop existing non-composite index? (queries in most cases use single index, as I have read)?
Will unique composite index be as effective as non-unique non-composite one for queries only on column A?
If you have a lot of queries going for column A only in a where clause, then most likely you should keep the index on column A in addition to the new one.
The amount of queries which would use the index and the query cost difference are the 2 most important criteria for deciding whether or not to leave the index. As it depends on many factors like amount of content in the table and also query parameters, as Frank Heikens comment says, you can use the EXPLAIN ANALYZE statements to check important queries with and without the index to confirm your hypothesis.
There is a very small probability it would make sense to keep both indexes. If the unique index is almost never exercised (because you never do inserts or non-HOT updates, or queries that benefit from both columns) and you have precisely the right amount of memory and memory usage patterns, then it is possible for the single-column index to be small enough to stay in cache while the composite would not be.
But most likely what would happen is that the composite index would be used at least enough of the time that both indexes would be fighting with each other for cache space, making it overall less effective.

How best to update row where composite primary key values change

We have numerous tables where we have composite keys with MULTIPLE entries. In some cases as many as SIX values that make up the primary key for a table that is not super large, maybe a few thousand entries, and is not accessed very heavily.
A better solution to this would be to use a primary key that is a single auto-incremented ID field and in order to make sure the combination of the six different fields now used as a primary key are unique you can create an index with a unique constraint. The performance might not be quite so good, but the code complexity would be DRASTICALLY reduced.
I was told that making the primary key so complex is necessary because the primary key is the only clustered index on a table and that this enhances the performance. I can understand how this would help, but is it THAT big of a performance enhancement? It seems to be a premature optimization.
Is it common practice to use composite primary keys? I understand that if you had a very large table, with many thousands of entries, and that was hit constantly, then even a small performance enhancement could be worth adding the complexity I am seeing.
It also seems like having a primary key made up of values that can be updated/changed is just asking for trouble. If other tables are referencing it couldn't that lead to issues?
This would mostly be for adding new tables, since changing the structure of the existing tables could be too drastic a change for them to accept. But I want to know if I am out of line before trying to push back against this practice.
Generally using many columns to form a PRIMARY KEY is the worst practice that I found regularly in my databases audits. In fact it was used in the hierarchical database model dating in the 50's... This was dropped due to poor performance !
Database relational model says that the key can be any column or group of columns, but the database experts and practionners have all demonstrates that the best way to have performances in order to ensure the scalability, is to have a key that is only one column, and with a datatype that is :
the shortest in terms of bytes
the biggest in terms of values
with asemantic values
in a monotonous order
The only way to assume all these considerations is to have a PRIMARY KEY with an auto-increment dataype such as IDENTITY or SEQUENCE.
Every other datatype or ways to do so have some extraoverhead or performs poorly.
In the case of PK with compound columns, the statistics for the optimizer are accurate only for the first column of the key. The statistics of the combination of multiple columns does not exists in any accurate way (except for a complete set of all value of the key in the case of a strict equality and of course this is always equal to 1) and conducts the optimizer to get an average of the global selectivity or worst, compute a correlated cardinality. In both case the execution plan will be of poor quality and sometime catastrophic...
For MS SQL Server clustered indexes are the best choice for PK, only if all the specification I wrote are strictly applied.

Issue with the big tables ( no primary key available)

Tabe1 has around 10 Lack records (1 Million) and does not contain any primary key. Retrieving the data by using SELECT command ( With a specific WHERE condition) is taking large amount of time. Can we reduce the time of retrieval by adding a primary key to the table or do we need to follow any other ways to do the same. Kindly help me.
A primary key does not have a direct affect on performance. But indirectly, it does. This is because when you add a primary key to a table, SQL Server creates a unique index (clustered by default) that is used to enforce entity integrity. But you can create your own unique indexes on a table. So, strictly speaking, a primary index does not affect performance, but the index used by the primary key does.
WHEN SHOULD PRIMARY KEY BE USED?
Primary key is needed for referring to a specific record.
To make your SELECTs run fast you should consider adding an index on an appropriate columns you're using in your WHERE.
E.g. to speed-up SELECT * FROM "Customers" WHERE "State" = 'CA' one should create an index on State column.
Primarykey will not help if you don't have Primarykey in where cause.
If you would like to make you quesry faster, you can create non-cluster index on columns in where cause. You may want include columns on top of your index(it depend on your select cause)
The SQL optimizer will seek on your indexs that will make your query faster.
(but you should think about when data adding in your table. Insert operation might takes time if you create index on many columns.)
It depends on the SELECT statement, and the size of each row in the table, the number of rows in the table, and whether you are retrieving all the data in each row or only a small subset of the data (and if a subset, whether the data columns that are needed are all present in a single index), and on whether the rows must be sorted.
If all the columns of all the rows in the table must be returned, then you can't speed things up by adding an index. If, on the other hand, you are only trying to retrieve a tiny fraction of the rows, then providing appropriate indexes on the columns involved in the filter conditions will greatly improve the performance of the query. If you are selecting all, or most, of the rows but only selecting a few of the columns, then if all those columns are present in a single index and there are no conditions on columns not in the index, an index can help.
Without a lot more information, it is hard to be more specific. There are whole books written on the subject, including:
Relational Database Index Design and the Optimizers
One way you can do it is to create indexes on your table. It's always better to create a primary key, which creates a unique index that by default will reduce the retrieval time .........
The optimizer chooses an index scan if the index columns are referenced in the SELECT statement and if the optimizer estimates that an index scan will be faster than a table scan. Index files generally are smaller and require less time to read than an entire table, particularly as tables grow larger. In addition, the entire index may not need to be scanned. The predicates that are applied to the index reduce the number of rows to be read from the data pages.
Read more: Advantages of using indexes in database?

Having an index on a database field that is VARCHAR can increase the speed in the insertions?

I have two tables in my database: page and link. In each one I define that the URL field is UNIQUE because I don't want repetead URLs.
Being a UNIQUE field, it automatically have an index? Creating an index for these field can speed up the insertions? What is the most appropriate index for a VARCHAR field?
Having a lot of rows can slow the insert because this UNIQUE field? At the moment, I have 1,200,000 rows.
Yes, adding a UNIQUE constraint will create an index:
Adding a unique constraint will automatically create a unique btree index on the column or group of columns used in the constraint.
This won't speed up your INSERTs though, it will actually slow them down:
Every insert will have to be checked (using the index) to ensure that uniqueness is maintained.
Inserts will also update the index and this doesn't come for free.
Logically speaking, a constraint is one thing, and an index is another. Constraints have to do with data integrity; indexes have to do with speed.
Practically speaking, most dbms implement a unique constraint by building a unique index. A unique index lets the dbms determine more quickly whether the values you're trying to insert are already in the table.
I suppose an index on a VARCHAR() column might speed up an insert under certain circumstances. But generally an index slows inserts, because the dbms has to
check all the constraints, then
insert the data, and finally
update the index.
A suitable index will speed up updates, because the dbms can find the rows to be updated more quickly. (But it might have to update the index, too, which costs you a little bit.)
PostgreSQL can tell you which indexes it's using. See EXPLAIN.
Usually b-tree/b+tree index is the most common indexes, and most likely inserts and updates are slower with these indexes, whereas selection of single row, selection of ranges and ORDER BY (ascending in most cases) would be very quick. This is because this index is ordered and so insertion would have to find out where to insert, instead of just inserting it at the end of the table. In the case of a clustered index, insertion/updates are even worse because of page splits.
Being unique would probably make it a bit slower since it has to scan more rows to make sure it is unique.
Also varchar is generally not the best choice for indexes if you are looking for optimal performance, integer is much much faster if it can be used. So there really is no 'best' index for varchar, each index has its own strengths and weaknesses and theres always a tradeoff. It really depends on the situation and what you plan to do with it, do you only need inserts/updates? Or do you also need to make selections? These are the things you need to ask.

Does clustered index on foreign key column increase join performance vs non-clustered?

In many places it's recommended that clustered indexes are better utilized when used to select range of rows using BETWEEN statement. When I select joining by foreign key field in such a way that this clustered index is used, I guess, that clusterization should help too because range of rows is being selected even though they all have same clustered key value and BETWEEN is not used.
Considering that I care only about that one select with join and nothing else, am I wrong with my guess ?
Discussing this type of issue in the absolute isn't very useful.
It is always a case-by-case situation !
Essentially, access by way of a clustered index saves one indirection, period.
Assuming the key used in the JOIN, is that of the clustered index, in a single read [whether from an index seek or from a scan or partial scan, doesn't matter], you get the whole row (record).
One problem with clustered indexes, is that you only get one per table. Therefore you need to use it wisely. Indeed in some cases, it is even wiser not to use any clustered index at all because of INSERT overhead and fragmentation (depending on the key and the order of new keys etc.)
Sometimes one gets the equivalent benefits of a clustered index, with a covering index, i.e. a index with the desired key(s) sequence, followed by the column values we are interested in. Just like a clustered index, a covering index doesn't require the indirection to the underlying table. Indeed the covering index may be slightly more efficient than the clustered index, because it is smaller.
However, and also, just like clustered indexes, and aside from the storage overhead, there is a performance cost associated with any extra index, during INSERT (and DELETE or UPDATE) queries.
And, yes, as indicated in other answers, the "foreign-key-ness" of the key used for the clustered index, has absolutely no bearing on the the performance of the index. FKs are constraints aimed at easing the maintenance of the integrity of the database but the underlying fields (columns) are otherwise just like any other field in the table.
To make wise decisions about index structure, one needs
to understands the way the various index types (and the heap) work
(and, BTW, this varies somewhat between SQL implementations)
to have a good image of the statistical profile of the database(s) at hand:
which are the big tables, which are the relations, what's the average/maximum cardinality of relation, what's the typical growth rate of the database etc.
to have good insight regarding the way the database(s) is (are) going to be be used/queried
Then and only then, can one can make educated guesses about the interest [or lack thereof] to have a given clustered index.
I would ask something else: would it be wise to put my clustered index on a foreign key column just to speed a single JOIN up? It probably helps, but..... at a price!
A clustered index makes a table faster, for every operation. YES! It does. See Kim Tripp's excellent The Clustered Index Debate continues for background info. She also mentions her main criteria for a clustered index:
narrow
static (never changes)
unique
if ever possible: ever increasing
INT IDENTITY fulfills this perfectly - GUID's do not. See GUID's as Primary Key for extensive background info.
Why narrow? Because the clustering key is added to each and every index page of each and every non-clustered index on the same table (in order to be able to actually look up the data row, if needed). You don't want to have VARCHAR(200) in your clustering key....
Why unique?? See above - the clustering key is the item and mechanism that SQL Server uses to uniquely find a data row. It has to be unique. If you pick a non-unique clustering key, SQL Server itself will add a 4-byte uniqueifier to your keys. Be careful of that!
So those are my criteria - put your clustering key on a narrow, stable, unique, hopefully ever-increasing column. If your foreign key column matches those - perfect!
However, I would not under any circumstances put my clustering key on a wide or even compound foreign key. Remember: the value(s) of the clustering key are being added to each and every non-clustered index entry on that table! If you have 10 non-clustered indices, 100'000 rows in your table - that's one million entries. It makes a huge difference whether that's a 4-byte integer, or a 200-byte VARCHAR - HUGE. And not just on disk - in server memory as well. Think very very carefully about what to make your clustered index!
SQL Server might need to add a uniquifier - making things even worse. If the values will ever change, SQL Server would have to do a lot of bookkeeping and updating all over the place.
So in short:
putting an index on your foreign keys is definitely a great idea - do it all the time!
I would be very very careful about making that a clustered index. First of all, you only get one clustered index, so which FK relationship are you going to pick? And don't put the clustering key on a wide and constantly changing column
An index on the FK column will help the JOIN because the index itself is ordered: clustered just means that the data on disk (leaf) is ordered rather then the B-tree.
If you change it to a covering index, then clustered vs non-clustered is irrelevant. What's important is to have a useful index.
It depends on the database implementation.
For SQL Server, a clustered index is a data structure where the data is stored as pages and there are B-Trees and are stored as a separate data structure. The reason you get fast performance, is that you can get to the start of the chain quickly and ranges are an easy linked list to follow.
Non-Clustered indexes is a data structure that contains pointers to the actual records and as such different concerns.
Refer to the documentation regarding Clustered Index Structures.
An index will not help in relation to a Foreign Key relationship, but it will help due to the concept of "covered" index. If your WHERE clause contains a constraint based upon the index. it will be able to generate the returned data set faster. That is where the performance comes from.
The performance gains usually come if you are selecting data sequentially within the cluster. Also, it depends entirely on the size of the table (data) and the conditions in your between statement.