| Author |
Topic |
|
fmardani
Constraint Violating Yak Guru
433 Posts |
Posted - 2005-06-22 : 09:00:58
|
| In the staff table there are several columns including ID, firstname and lastname, ...The queries in the stored procedures are mostly to do with passing firstname and/or lastname to searchIs it best to create a clustered index in the staff table for firstname, lastname ? or shall I create a non-clustered index? if so should I have one non-clustered for each of the two fields or one key for both?Thanks |
|
|
Merkin
Funky Drop Bear Fearing SQL Dude!
4970 Posts |
Posted - 2005-06-22 : 09:23:54
|
| Imagine your data like a huge list of names you want to publish as a phone book. Obviously you do want to have to search through a huge random list of names to find the one you want, so this is why we use indexes. But you know this....A clustered index physically reorders your data, a standard phone book is ordered like you suggest : lastname, firstname.This is great if you need to find all the "Smith" names, or if you need John Smith. But won't help you if you need to find anyone named John. You will have to scan all the rows to find people called John. This is what a Clustered Index Scan is.A non clustered index is like the index in the back of a book, if you look up "John" and you have a non-clustered index on first name it will tell you "there is one page 7, one on page 13 and one on page 273".So, if you will be searching on EITHER First name OR Last Name, I'd probably go for a separate Non Clustered index on each of those columns, because a combined index won't help you find only one of those criteria.Make sense ?Damian"A foolish consistency is the hobgoblin of little minds." - Emerson |
 |
|
|
nieurig
Starting Member
8 Posts |
Posted - 2005-06-22 : 09:29:19
|
| Hello,1. Clustered IndexI think you can't build a Clustered Index on firstname and lastname because your data will not fit to this unique key.Otherwise this would a good opertunity instead of having the ID as a clustered key.2. NonClustered IndexI have read that 2 Indexes are better because of the benefit for query which runs on one of this Index-Values. The best way was testing it using the Query Analyse (Strg+K to see the Execution plan)Good luckNiels |
 |
|
|
mwjdavidson
Aged Yak Warrior
735 Posts |
Posted - 2005-06-22 : 10:23:15
|
| I've rarely read a better explanation - Nice one Damian!Mark |
 |
|
|
Merkin
Funky Drop Bear Fearing SQL Dude!
4970 Posts |
Posted - 2005-06-22 : 10:57:22
|
Thanks Mark! Damian"A foolish consistency is the hobgoblin of little minds." - Emerson |
 |
|
|
byrmol
Shed Building SQL Farmer
1591 Posts |
Posted - 2005-06-22 : 19:42:59
|
| >>I think you can't build a Clustered Index on firstname and lastname >>because your data will not fit to this unique key.Clusterd Indexes and Keys are NOT the same thing.A key (in SQL Server) requires an index, but an index does not require a key.Here's a tip...Indexing is HARD.. there are so many factors involved.. transaction rates, transaction types, hardware, predicate use...DavidMA front-end is something that tries to violate a back-end. |
 |
|
|
paulrandal
Yak with Vast SQL Skills
899 Posts |
Posted - 2005-06-22 : 20:51:57
|
quote: Originally posted by byrmolClusterd Indexes and Keys are NOT the same thing.A key (in SQL Server) requires an index, but an index does not require a key.
Can you explain how an index (clustered or non-clustered) works if you don't have a key?A key only exists to provide the sort order (and hence inherent search predicate) of an index. An index cannot exist unless it has a key (sort order) defined for it.ThanksPaul RandalDev Lead, Microsoft SQL Server Storage Engine |
 |
|
|
paulrandal
Yak with Vast SQL Skills
899 Posts |
Posted - 2005-06-22 : 20:57:57
|
quote: Originally posted by Merkin So, if you will be searching on EITHER First name OR Last Name, I'd probably go for a separate Non Clustered index on each of those columns, because a combined index won't help you find only one of those criteria.
Unless one of the queries is _much_ more common than the other, in which case it may be more efficient to make one of the indexes clustered to avoid the extra IO of having to search the non-clustered index and then do another IO to get the row from the heap. The downside is that queries that go though the non-clustered index will have to then seek into the clustered index too, rather than doing a single page IO into a heap. Again, this tradeoff works if one query is way more common than the other.ThanksPaul RandalDev Lead, Microsoft SQL Server Storage Engine |
 |
|
|
byrmol
Shed Building SQL Farmer
1591 Posts |
Posted - 2005-06-22 : 21:10:20
|
| >>Can you explain how an index (clustered or non-clustered) works if you don't have a key?You've been spending too much time at the disk level... A good thing for the lead on the storage engine... Love your work by the way!I was speaking about the difference between a KEY (Relational model) vs SQL Server's implmentation of them.. I am pretty sure I can create an index on a non-key column in sql server...Paul, are you aware of the TransRelationalModel (TM)? Seems right up your alley. [url]http://www.dbdebunk.com/page/page/1548800.htm[/url]EDIT: Spelling (what a shock!) and questionDavidMA front-end is something that tries to violate a back-end. |
 |
|
|
paulrandal
Yak with Vast SQL Skills
899 Posts |
Posted - 2005-06-22 : 21:54:13
|
quote: Originally posted by byrmol >>Can you explain how an index (clustered or non-clustered) works if you don't have a key?You've been spending too much time at the disk level... A good thing for the lead on the storage engine... Love your work by the way!I was speaking about the difference between a KEY (Relational model) vs SQL Server's implmentation of them.. I am pretty sure I can create an index on a non-key column in sql server...Paul, are you aware of the TransRelationalModel (TM)? Seems right up your alley. [url]http://www.dbdebunk.com/page/page/1548800.htm[/url]EDIT: Spelling (what a shock!) and questionDavidMA front-end is something that tries to violate a back-end.
Of course, you're absolutely right. In pure relational terms a key is just defined and does not have to be physically manifested in any way. Even in SQL Server , a foreign-key relationship is not manifested. Its easy to become blinkered by implementation details :-)No - haven't seen that, I'll check it out.You can't create an index on a non-key column - the columns that are indexed form its key, by definition. In SQL Server 2005, you can include non-key columns in a non-clustered index so you can fully cover queries and avoid the situation I described in my other reply to this thread.ThanksPaul RandalDev Lead, Microsoft SQL Server Storage Engine |
 |
|
|
byrmol
Shed Building SQL Farmer
1591 Posts |
Posted - 2005-06-22 : 22:16:10
|
>>You can't create an index on a non-key column - the columns that are indexed form its key, by >>definitionYou are speaking internally again arn't you? So SQL Server creates an internal "row index key" if there is none defined declaratively?Given this example of a bag...create table TestIndex(NonKey INT NOT NULL)GOCREATE NONCLUSTERED INDEX IDX_NONKEY ON TestIndex (NonKey)--CREATE CLUSTERED INDEX IDX_NONKEY ON TestIndex (NonKey)GODECLARE @Count INTSET @Count = 0WHILE @Count < 1000BEGIN INSERT TestIndex(NonKey) VALUES (@Count) SET @Count = @Count + 1END--Duplicate value INSERT TestIndex(NonKey) VALUES (1)GOSelect * from TestIndexWHERE NonKey = 1Select * from TestIndexWHERE NonKey BETWEEN 5 and 8--DROP table TestIndex So what is happening internally here?DavidMA front-end is something that tries to violate a back-end. |
 |
|
|
paulrandal
Yak with Vast SQL Skills
899 Posts |
Posted - 2005-06-23 : 12:31:08
|
quote: Originally posted by byrmol >>You can't create an index on a non-key column - the columns that are indexed form its key, by >>definitionYou are speaking internally again arn't you? So SQL Server creates an internal "row index key" if there is none defined declaratively?Given this example of a bag...create table TestIndex(NonKey INT NOT NULL)GOCREATE NONCLUSTERED INDEX IDX_NONKEY ON TestIndex (NonKey)--CREATE CLUSTERED INDEX IDX_NONKEY ON TestIndex (NonKey)GODECLARE @Count INTSET @Count = 0WHILE @Count < 1000BEGIN INSERT TestIndex(NonKey) VALUES (@Count) SET @Count = @Count + 1END--Duplicate value INSERT TestIndex(NonKey) VALUES (1)GOSelect * from TestIndexWHERE NonKey = 1Select * from TestIndexWHERE NonKey BETWEEN 5 and 8--DROP table TestIndex So what is happening internally here?DavidMA front-end is something that tries to violate a back-end.
Yes, you've implicitly defined an index key, as opposed to a relational key of the table. You have to make sure you qualify the term 'key'. This was my initial confusion in the thread - I assumed you were talking about an index key.Internally, the nonclustered index is sorted by the index key 'nonKey'. Each row will have the nonKey value and the row-identifier of the data row in the heap or clustered index.ThanksPaul RandalDev Lead, Microsoft SQL Server Storage Engine |
 |
|
|
rockmoose
SQL Natt Alfen
3279 Posts |
Posted - 2005-06-24 : 19:16:44
|
| >> I assumed you were talking about an index keyWhoa,I always thought a key was a key when talking about databases.But then I am not programming the database, just using it...Interesting.rockmoose |
 |
|
|
byrmol
Shed Building SQL Farmer
1591 Posts |
Posted - 2005-06-26 : 06:25:04
|
Thanks for the explanation Paul..I (and rockmoose) am what Codd refers to as a "user". A key to me, is a relational key signifying identity. How that happens underneath is mostly none of my concern as long as the logical key holds! The idea that the logical is abstracted from the physical is a central tenant of RM and I believe that SQL Server goes closer than most to this goal in regard to file/index management. As I said earlier, great job!Do CHECK constraints get an index key? Because I can create a logical key without an index by using UDF's and CHECK constraints...iecreate function keycount(@Key INT)returns intasbegindeclare @return intselect @return = COUNT(*) from test where derivedkey = @keyRETURN @returnendgocreate table test(derivedkey int not null CHECK (dbo.keycount(derivedkey) = 1))GOinsert test (derivedkey) SELECT 1 UNION ALL SELECT 2goinsert test (derivedkey) SELECT 3 UNION ALL SELECT 2 I'm just trying to reinforce the notion that relational identity is distinct from any physical implemetation..And I think I speak for everyone here in saying that we appreciate the interaction with the SQL Server dev team members and would love to see more of it!Thanks again for the insight.DavidMA front-end is something that tries to violate a back-end. |
 |
|
|
paulrandal
Yak with Vast SQL Skills
899 Posts |
Posted - 2005-06-26 : 09:12:31
|
quote: Originally posted by byrmol Do CHECK constraints get an index key? Because I can create a logical key without an index by using UDF's and CHECK constraints...
No they don't.quote: And I think I speak for everyone here in saying that we appreciate the interaction with the SQL Server dev team members and would love to see more of it!
Cool - its difficult to persuade more people to get on the newsgroups and forum sites like this but we're working on it.ThanksPaul RandalDev Lead, Microsoft SQL Server Storage Engine |
 |
|
|
rockmoose
SQL Natt Alfen
3279 Posts |
Posted - 2005-06-26 : 17:40:08
|
Yes, it's great to see You here Paul!You guys are always welcome...Is there a physical difference in creating a UNIQUE CONTRAINT or a UNIQUE INDEX ?Are they basically the same thing, or are they treated differently by SQL Server?When I look in sysindexes table UC / UIX look the same apart from the status.CREATE TABLE t(c INT NOT NULL)ALTER TABLE t ADD CONSTRAINT UC_x_c UNIQUE(c) WITH FILLFACTOR = 80 -- UNIQUE CONSTRAINTCREATE UNIQUE INDEX UIX_x_c ON t(c) WITH FILLFACTOR = 80 -- UNIQUE INDEXEXEC sp_helpindex tEXEC sp_helpconstraint tSELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLe_CONSTRAINTS WHERE TABLE_NAME = 't'--SELECT * FROM sysindexes WHERE id = OBJECT_ID('t')DROP TABLE t/*index_name index_description index_keys --------------------------------------------------- --------------------------------------------------- ----------UC_x_c nonclustered, unique, unique key located on FG_LAB1 cUIX_x_c nonclustered, unique located on FG_LAB1 cconstraint_type constraint_name--------------------------------------------------- ---------------UNIQUE (non-clustered) UC_x_cCONSTRAINT_NAME---------------UC_x_c*/Sometimes I need to retrieve all the relational keys of a table, i.e. all PK's + UIX's + UC's defined on a table.I look for UIX's in the sysindexes system table, PK's and UC's can be found in INFORMATION_SCHEMA.I would have liked to be able to access this metadata in one place!rockmoose |
 |
|
|
paulrandal
Yak with Vast SQL Skills
899 Posts |
Posted - 2005-06-27 : 13:12:18
|
quote: Originally posted by rockmoose Is there a physical difference in creating a UNIQUE CONTRAINT or a UNIQUE INDEX ?Are they basically the same thing, or are they treated differently by SQL Server?
They're the same thing under the covers although I think the error returned when uniqueness is violated may be different.ThanksPaul RandalDev Lead, Microsoft SQL Server Storage Engine |
 |
|
|
rockmoose
SQL Natt Alfen
3279 Posts |
Posted - 2005-06-27 : 13:54:21
|
Thanks, nice to know that they are the same under the covers.Found a quirk in BOL / SQL server, a 3604 (IGNORE_DUP_KEY) gets higher severity than PK violation,contrary to what BOL says !?Different errors:CREATE TABLE t(c INT NOT NULL)--ALTER TABLE t ADD CONSTRAINT PK_t_c PRIMARY KEY(c) -- PRIMARY KEY/*Server: Msg 2627, Level 14, State 1, Line 1Violation of PRIMARY KEY constraint 'PK_t_c'. Cannot insert duplicate key in object 't'.The statement has been terminated.*/--ALTER TABLE t ADD CONSTRAINT UC_t_c UNIQUE(c) WITH FILLFACTOR = 80 -- UNIQUE CONSTRAINT/*Server: Msg 2627, Level 14, State 2, Line 1Violation of UNIQUE KEY constraint 'UC_t_c'. Cannot insert duplicate key in object 't'.The statement has been terminated.*/--CREATE UNIQUE INDEX UIX_t_c ON t(c) -- UNIQUE INDEX/*Server: Msg 2601, Level 14, State 3, Line 1Cannot insert duplicate key row in object 't' with unique index 'UIX_t_c'.The statement has been terminated.*/CREATE UNIQUE INDEX UIX_t_c ON t(c) WITH IGNORE_DUP_KEY -- UNIQUE INDEX/*Server: Msg 3604, Level 16, State 1, Line 27Duplicate key was ignored.*/--BOL on 3604 : Severity Level 10 !!!???--Funny this get's caught before a PK violationINSERT T SELECT 1INSERT T SELECT 1GODROP TABLE TGO rockmoose |
 |
|
|
paulrandal
Yak with Vast SQL Skills
899 Posts |
Posted - 2005-06-27 : 14:27:05
|
quote: Originally posted by rockmoose Thanks, nice to know that they are the same under the covers.Found a quirk in BOL / SQL server, a 3604 (IGNORE_DUP_KEY) gets higher severity than PK violation,contrary to what BOL says !?Different errors:CREATE TABLE t(c INT NOT NULL)--ALTER TABLE t ADD CONSTRAINT PK_t_c PRIMARY KEY(c) -- PRIMARY KEY/*Server: Msg 2627, Level 14, State 1, Line 1Violation of PRIMARY KEY constraint 'PK_t_c'. Cannot insert duplicate key in object 't'.The statement has been terminated.*/--ALTER TABLE t ADD CONSTRAINT UC_t_c UNIQUE(c) WITH FILLFACTOR = 80 -- UNIQUE CONSTRAINT/*Server: Msg 2627, Level 14, State 2, Line 1Violation of UNIQUE KEY constraint 'UC_t_c'. Cannot insert duplicate key in object 't'.The statement has been terminated.*/--CREATE UNIQUE INDEX UIX_t_c ON t(c) -- UNIQUE INDEX/*Server: Msg 2601, Level 14, State 3, Line 1Cannot insert duplicate key row in object 't' with unique index 'UIX_t_c'.The statement has been terminated.*/CREATE UNIQUE INDEX UIX_t_c ON t(c) WITH IGNORE_DUP_KEY -- UNIQUE INDEX/*Server: Msg 3604, Level 16, State 1, Line 27Duplicate key was ignored.*/--BOL on 3604 : Severity Level 10 !!!???--Funny this get's caught before a PK violationINSERT T SELECT 1INSERT T SELECT 1GODROP TABLE TGO rockmoose
BOL is correct - its an informational message.There's a problem with that message in the translation table that OLEDB uses and so it comes out as sev 16. This is fixed in SQL Server 2005.ThanksPaul RandalDev Lead, Microsoft SQL Server Storage Engine |
 |
|
|
rockmoose
SQL Natt Alfen
3279 Posts |
Posted - 2005-06-27 : 14:39:28
|
quote: BOL is correct - its an informational message.There's a problem with that message in the translation table that OLEDB uses and so it comes out as sev 16. This is fixed in SQL Server 2005.
Thank You for the information.rockmoose |
 |
|
|
|