ContrAcct
asked on
SQL Server 2008 R2 Non-Clustered Candidate Indices
I have a SQL Server 2008 R2 database with tables that are shared by multiple different companies and multiple users. My tables all have one integer column that identifies which company the record belongs to. Through views, users will only be able to see the data that belongs to the company they are logged in under.
So my question is: when creating my non-clustered indices for speed (only on the columns mostly frequently referenced by where clauses) does it make sense to create all the indices as a candidate index, or only create indices on the individual fields I am trying to index?
So my question is: when creating my non-clustered indices for speed (only on the columns mostly frequently referenced by where clauses) does it make sense to create all the indices as a candidate index, or only create indices on the individual fields I am trying to index?
Create Table Department
(
DepartmentISN int Identity Primary Key,
CompanyISN int not null,
DepartmentID varchar(10) not null,
DepartmentName varchar(40) not null default '',
Extension varchar(10) not null default '',
LastModifiedDate datetime2 not null default SYSUTCDATETIME(),
LastModifiedUserISN int default NULL
)
-- This index is necessary to prevent duplicate department
-- IDs within the same company. I'm certain this is correct.
Create Unique Index "IX_DepartmentID" on Department (DepartmentID, CompanyISN)
-- Should I build indices like this?
Create Index "IX_DepartmentISN" on Department(DepartmentISN)
Create Index "IX_DepartmentName" on Department(DepartmentName)
-- Or like this?
Create Index "IX_DepartmentISN" on Department(DepartmentISN, CompanyISN)
Create Index "IX_DepartmentName" on Department(DepartmentName, CompanyISN)
>> My tables all have one integer column that identifies which company the record belongs to. Through views, users will only be able to see the data that belongs to the company they are logged in under. <<
Then that integer should 100% be the first column in the *clustered* index.
For non-clus indexes, your lead column in the index should be one you requently use in WHERE clauses and has a high selectivity. SQL is extremely restrictive about using a non-clus index, so a non-selective one will almost certainly almost never get used.
Then that integer should 100% be the first column in the *clustered* index.
For non-clus indexes, your lead column in the index should be one you requently use in WHERE clauses and has a high selectivity. SQL is extremely restrictive about using a non-clus index, so a non-selective one will almost certainly almost never get used.
By orders of magnitude the most important index is the clustered one. Get that right and the rest can be added later.
ASKER
Let me specify. I understand I need indices for columns that will be in my where clasuse. However, which option would be better, or are these essentially the same?
OR
Create Nonclustered Index [IX_CompanyISN] on [dbo].[Department]
(
[CompanyISN] ASC
)
Create Nonclustered Index [IX_DepartmentISN] on [dbo].[Department]
(
[DepartmentISN] ASC
)
OR
Create Nonclustered Index [IX_DepartmentISN] on [dbo].[Department]
(
[CompanyISN] ASC
[DepartmentISN] ASC
)
They are not the same thing one is creating to seperate indexes on 2 different columns that is the first option.
The bottom option is creating a single index on 2 columns.
If your where clause uses both columns then they both need to be included in the index. Are you able to provide the where clause as well?
The bottom option is creating a single index on 2 columns.
If your where clause uses both columns then they both need to be included in the index. Are you able to provide the where clause as well?
Again, the odds of a non-clus index being used are relatively low.
You should concentrate on getting the proper clustered index.
You can easily add and drop non-clus indexes live in relatively little time.
You should concentrate on getting the proper clustered index.
You can easily add and drop non-clus indexes live in relatively little time.
ASKER
Scott, my clustered index was just an ascending value on the unique integer DepartmentISN that was automatically generated by defining DepartmentISN as the primary key (which is also the identity field). Are you saying that the following code will not produce an adequate clustered index?
The DepartmentISN field will always be unique, and almost never used in a where clause, but it will often be used in join clauses. A user, however, will only be able to see the records that match the CompanyISN number (which is not a unique value to each record). Additionaly, the where clause will mostly likely filter results be the DepartmentID.
Are you saying it would be best to use the following code after having created the Department table?:
And as far as the order of the index columns, am I correct in assuming the keys should be ordered from least specific values to most specific values (like I have done in the above code example)?
FYI, I have a unique index to ensure that there are no duplicate DepartmentIDs per company:
Create Table Department
(
DepartmentISN int Identity Primary Key,
CompanyISN int not null,
DepartmentID varchar(10) not null,
DepartmentName varchar(40) not null default '',
Extension varchar(10) not null default '',
LastModifiedDate datetime2 not null default SYSUTCDATETIME(),
LastModifiedUserISN int default NULL
)
The DepartmentISN field will always be unique, and almost never used in a where clause, but it will often be used in join clauses. A user, however, will only be able to see the records that match the CompanyISN number (which is not a unique value to each record). Additionaly, the where clause will mostly likely filter results be the DepartmentID.
Are you saying it would be best to use the following code after having created the Department table?:
ALTER TABLE [dbo].[Department] DROP CONSTRAINT [PK__Departme__1853C0FB7F60ED59]
ALTER TABLE [dbo].[Department] ADD PRIMARY KEY NONCLUSTERED
(
[DepartmentISN] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
Create Clustered Index [IX_DepartmentISN] on [dbo].[Department]
(
[CompanyISN] Asc,
[DepartmentISN] Asc,
[DepartmentID] Asc
)
And as far as the order of the index columns, am I correct in assuming the keys should be ordered from least specific values to most specific values (like I have done in the above code example)?
FYI, I have a unique index to ensure that there are no duplicate DepartmentIDs per company:
Create Unique Index [IX_DepartmentID] on [dbo].[Department]
(
[CompanyISN] Asc,
[DepartmentID] Asc
)
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Some other columns might still need to be indexed, so naturally you can continue to investigate other WHERE columns for non-clus indexes. SQL can use mutliple indexes to satisfy one query if it makes sense for it to do so.
ASKER
Thank you very much for your help!
No problem !
REWORDING:
>>The first column should be the one that is specific (almost) all the time for most of queries<<
"Specified", not "specific", for "most queries".
REWORDING:
>>The first column should be the one that is specific (almost) all the time for most of queries<<
"Specified", not "specific", for "most queries".
Also, the order that you specify the columns of the index may impact performance.
It will probably look something like this:
Open in new window