Author |
Topic |
arkiboys
Master Smack Fu Yak Hacker
1433 Posts |
Posted - 2012-06-13 : 07:42:11
|
Hi, I know if there is no clustered index in the table i.e. heap table, then the system automatically builds a PK. Is there a link you can refer me to for further reading on this very topic where the system creates a PK when the table is a heap? Thanks |
|
robvolk
Most Valuable Yak
15732 Posts |
Posted - 2012-06-13 : 07:53:08
|
quote: I know if there is no clustered index in the table i.e. heap table, then the system automatically builds a PK.
False. A primary key is a logical construct. Heaps are physical. You're probably confusing primary key with clustered index, they are not the same thing. Heaps maintain a unique row identifier (RID) but they are not a primary key. Primary keys are never automatically created.quote: Is there a link you can refer me to for further reading on this very topic where the system creates a PK when the table is a heap?
Read up on heaps here: http://goo.gl/Cz9Ky |
|
|
Sachin.Nand
2937 Posts |
Posted - 2012-06-13 : 08:07:10
|
quote: Originally posted by robvolk ...Heaps maintain a unique row identifier (RID) but they are not a primary key...
I think that is not true.A heap will never maintain a unique identifier until a primary or unique key is defined on it.After Monday and Tuesday even the calendar says W T F .... |
|
|
arkiboys
Master Smack Fu Yak Hacker
1433 Posts |
Posted - 2012-06-13 : 08:09:46
|
quote: Originally posted by robvolk
quote: I know if there is no clustered index in the table i.e. heap table, then the system automatically builds a PK.
False. A primary key is a logical construct. Heaps are physical. You're probably confusing primary key with clustered index, they are not the same thing. Heaps maintain a unique row identifier (RID) but they are not a primary key. Primary keys are never automatically created.quote: Is there a link you can refer me to for further reading on this very topic where the system creates a PK when the table is a heap?
Read up on heaps here: http://goo.gl/Cz9Ky Hi, can you please refer me to a link which show the RID is created if the table is a heap?Thanks |
|
|
Transact Charlie
Master Smack Fu Yak Hacker
3451 Posts |
Posted - 2012-06-13 : 09:34:05
|
quote: Originally posted by Sachin.Nand
quote: Originally posted by robvolk ...Heaps maintain a unique row identifier (RID) but they are not a primary key...
I think that is not true.A heap will never maintain a unique identifier until a primary or unique key is defined on it.After Monday and Tuesday even the calendar says W T F ....
NAh -- they do. Otherwise how would the engine be able to identify rows?When you do a seek on an index on a heap you see RID lookups in the execution plan. Even without a unique or primary key. Consider:IF OBJECT_ID('tempdb..#foo') IS NOT NULL DROP TABLE #fooCREATE TABLE #foo ( [key] INT , [value] VARCHAR(255) ) CREATE INDEX keys ON #foo ([key])INSERT #fooSELECT CAST(CAST(NEWID() AS VARBINARY(255)) AS INT) , CAST(CAST(NEWID() AS VARBINARY(255)) AS VARCHAR(255))FROM sys.objects AS a CROSS JOIN sys.objects AS bINSERT #foo VALUES (10, 'HI THERE')SELECT * FROM #foo WHERE [key] = 10 The last statement generates this plan[code] |--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1000])) |--Index Seek(OBJECT:([tempdb].[dbo].[#foo]), SEEK:([tempdb].[dbo].[#foo].[key]=(10)) ORDERED FORWARD) |--RID Lookup(OBJECT:([tempdb].[dbo].[#foo]), SEEK:([Bmk1000]=[Bmk1000]) LOOKUP ORDERED FORWARD)Transact CharlieMsg 3903.. The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION. |
|
|
robvolk
Most Valuable Yak
15732 Posts |
Posted - 2012-06-13 : 09:42:49
|
quote: Hi, can you please refer me to a link which show the RID is created if the table is a heap?
How about reading the link I provided and clicking on the other links inside it? And Google works for everyone, not just me.quote: I think that is not true.A heap will never maintain a unique identifier until a primary or unique key is defined on it.
The RID has to be unique, it consists of file ID, page ID and slot number. You can't store two rows in the exact same location. Moreover you can't create a unique index on the RID because it's not accessible (not in a documented way anyhow, and I just tried it anyway and failed). Here's an example:create table #a(a int null)insert #a default valuesinsert #a default valuesinsert #a default valuesinsert #a default valuesselect *,sys.fn_PhysLocFormatter(%%physloc%%) from #a That's another reason why RID is not a primary key, a primary key cannot be applied to a nullable column. RID is not a column and, technically, not a value either.More info on heaps at Paul Randal's blog: http://goo.gl/eJwBbThere's more than that, but that's the only one I could find quickly. Read Paul. |
|
|
nigelrivett
Master Smack Fu Yak Hacker
3385 Posts |
Posted - 2012-06-13 : 09:47:27
|
If the server has a clustered index then the rid is the clustered index columns plus a sequence number if the index is not unique.If there is no clustered index then it is generated.The rid is included in the leaf level of every non-clustered index - which is why a wide clustered index can be bad for performance and disk space but give more covering indexes than you might expect.==========================================Cursors are useful if you don't know sql.SSIS can be used in a similar way.Beer is not cold and it isn't fizzy. |
|
|
robvolk
Most Valuable Yak
15732 Posts |
Posted - 2012-06-13 : 10:16:25
|
quote: If the server has a clustered index then the rid is the clustered index columns
Technically that's not correct either. RIDs do not reference the clustering key at all.quote: plus a sequence number if the index is not unique.
Ummm, the INDEX is unique, I think you mean the key columns, by themselves, are not unique. The unique-ifier is a 4 byte integer that is padded to the clustering key to make it unique.I apologize for being pedantic, it happens after you hear Paul describe it and complain about the misconceptions around it. |
|
|
Sachin.Nand
2937 Posts |
Posted - 2012-06-13 : 15:31:09
|
quote: Originally posted by robvolk
quote: Hi, can you please refer me to a link which show the RID is created if the table is a heap?
How about reading the link I provided and clicking on the other links inside it? And Google works for everyone, not just me.quote: I think that is not true.A heap will never maintain a unique identifier until a primary or unique key is defined on it.
The RID has to be unique, it consists of file ID, page ID and slot number. You can't store two rows in the exact same location. Moreover you can't create a unique index on the RID because it's not accessible (not in a documented way anyhow, and I just tried it anyway and failed). Here's an example:create table #a(a int null)insert #a default valuesinsert #a default valuesinsert #a default valuesinsert #a default valuesselect *,sys.fn_PhysLocFormatter(%%physloc%%) from #a That's another reason why RID is not a primary key, a primary key cannot be applied to a nullable column. RID is not a column and, technically, not a value either.More info on heaps at Paul Randal's blog: http://goo.gl/eJwBbThere's more than that, but that's the only one I could find quickly. Read Paul. Again I would say RID key does not have to be unique in a heap table.Also what you are pointing out is the physical location of the data returned by sys.fn_PhysLocFormatter(%%physloc%%). Optimizer does not use that value to identify rows from heaps.After Monday and Tuesday even the calendar says W T F .... |
|
|
robvolk
Most Valuable Yak
15732 Posts |
Posted - 2012-06-13 : 16:11:24
|
quote: Again I would say RID key does not have to be unique in a heap table.
Alright, please post an example where 1 RID points to 2 or more rows. RID is not a key either.quote: Also what you are pointing out is the physical location of the data returned by sys.fn_PhysLocFormatter(%%physloc%%). Optimizer does not use that value to identify rows from heaps.
I know that too. A RID isn't recorded anywhere except in the leaf level of a non-clustered index on a heap table. The optimizer doesn't care whether the non-clustered index is based on a heap or a B-tree structure. |
|
|
Sachin.Nand
2937 Posts |
Posted - 2012-06-13 : 16:43:32
|
quote: Originally posted by robvolk
quote: Again I would say RID key does not have to be unique in a heap table.
Alright, please post an example where 1 RID points to 2 or more rows. RID is not a key either.quote: Also what you are pointing out is the physical location of the data returned by sys.fn_PhysLocFormatter(%%physloc%%). Optimizer does not use that value to identify rows from heaps.
I know that too. A RID isn't recorded anywhere except in the leaf level of a non-clustered index on a heap table. The optimizer doesn't care whether the non-clustered index is based on a heap or a B-tree structure. See the following.I have created a table with NC indexes on two different columns.use tempdbgocreate table a(number1 int,number2 int)create nonclustered index ix_id1 on a(number1)gocreate nonclustered index ix_id on a(number2)goinsert a values(2,10),(3,100),(4,1000) I am using the DBCC IND command to get the details on the pages used by indexes.DBCC TRACEON(3604)DBCC IND(tempdb,a,-1) In my case I am getting the pagepid 4840 and 4845 as the page ids of index pages.Now I would use DBCC PAGE command to get the details of the indexes stored in these two pagesDBCC PAGE (tempdb, 1, 4840, 3)GODBCC PAGE (tempdb, 1, 4845, 3) Now if you carefully see the heap RID returned by these command you will see that they are exactly the same.So in short this proves that RID keys does not have to be unique across heaps..Now let us break down the RID value to get the file:page:rowid returned by fn_PhysLocFormatter.In my case one of the value returned by DBCC PAGE is 0xA312000001000000I have used this function to convert itdeclare @rowid BINARY(8)set @rowid = 0xA312000001000000select CONVERT (VARCHAR(5), CONVERT(INT, SUBSTRING(@rowid, 6, 1) + SUBSTRING(@rowid, 5, 1))) + ':' + CONVERT(VARCHAR(10), CONVERT(INT, SUBSTRING(@rowid, 4, 1) + SUBSTRING(@rowid, 3, 1) + SUBSTRING(@rowid, 2, 1) + SUBSTRING(@rowid, 1, 1))) + ':' + CONVERT(VARCHAR(5), CONVERT(INT, SUBSTRING(@rowid, 8, 1) + SUBSTRING(@rowid, 7, 1))) So if you see the value returned by the above function it is exactly the same what is returned by fn_PhysLocFormatter(%%physloc%%).So in short an RID key can point to the same location which does not have to be necessarily unique.I am off to bed now...its midnight here in India.After Monday and Tuesday even the calendar says W T F .... |
|
|
Alexander Suprun
Starting Member
4 Posts |
Posted - 2012-06-18 : 16:05:52
|
quote: Originally posted by Sachin.NandAlso what you are pointing out is the physical location of the data returned by sys.fn_PhysLocFormatter(%%physloc%%). Optimizer does not use that value to identify rows from heaps.After Monday and Tuesday even the calendar says W T F ....
I don't know why are referring to Optimizer but I'll assume that you mean SQL Server Query Processor. So it definitely uses RID, then it converts it to "file:page:slot" using fn_PhysLocFormatter (or something similar) and then uses this value to identify and extract rows from heap. That's the only way how it can be done! |
|
|
Alexander Suprun
Starting Member
4 Posts |
Posted - 2012-06-18 : 16:39:23
|
quote: Originally posted by Sachin.NandSo if you see the value returned by the above function it is exactly the same what is returned by fn_PhysLocFormatter(%%physloc%%).So in short an RID key can point to the same location which does not have to be necessarily unique.
Are you deliberately trying to confuse everyone in this topic?You took RIDs from 2 different non-clustered indexes! Which are just pointers in this case, certainly you can create multiple pointers that point to the same record, that's basically the whole purpose of the pointer and of course these RIDs must be the same, otherwise how they can point to the same record? But robvolk was talking about RID values in heap, and if you look at the heap only you will never find 2 RIDs with the same value, because they must be unique. |
|
|
Sachin.Nand
2937 Posts |
Posted - 2012-06-19 : 04:14:47
|
quote: Originally posted by Alexander Suprun Are you deliberately trying to confuse everyone in this topic?You took RIDs from 2 different non-clustered indexes! Which are just pointers in this case, certainly you can create multiple pointers that point to the same record, that's basically the whole purpose of the pointer and of course these RIDs must be the same, otherwise how they can point to the same record? But robvolk was talking about RID values in heap, and if you look at the heap only you will never find 2 RIDs with the same value, because they must be unique.
Did you even made an effort to understand what the discussion was all about or just jumped on your guns to bash me ??The whole point of the discussion in the fist place was that will SQL Server create unique RID keys for a heap irrespective whether they point to same record or not ,whether the heap has multiple indexes or not which I proved with an example that it is a FALSE assumption.Only free men can negotiate.. |
|
|
robvolk
Most Valuable Yak
15732 Posts |
Posted - 2012-06-19 : 07:34:44
|
quote: The whole point of the discussion in the fist place was that will SQL Server create unique RID keys for a heap irrespective whether they point to same record or not ,whether the heap has multiple indexes or not which I proved with an example that it is a FALSE assumption.
With the example you posted I couldn't replicate the output you showed. I could very well be missing something but I don't think you've proven it yet. And from a common sense perspective I cannot see how RID wouldn't be unique since it's a physical storage reference. Again, if it weren't unique you could have 2 rows in the same physical location, and that makes no sense at all.quote: Did you even made an effort to understand what the discussion was all about or just jumped on your guns to bash me ??
I think you're taking this too personally. Also be aware that you're contradicting information provided by the person who wrote the storage engine while he worked at Microsoft. In the words of Carl Sagan, "extraordinary claims require extraordinary evidence". Sorry if it sounds like we're bashing you, but if you're right you need to go the extra mile to prove it. And it's a cheap shot to simply accuse us of not understanding. |
|
|
Alexander Suprun
Starting Member
4 Posts |
Posted - 2012-06-19 : 20:00:54
|
quote: Originally posted by Sachin.Nand The whole point of the discussion in the fist place was that will SQL Server create unique RID keys for a heap
Which is true. For each record in a heap table there is only one RID and for one RID there is only one record in a table. quote: Originally posted by Sachin.Nandwhether the heap has multiple indexes or not which I proved with an example that it is a FALSE assumption.
Using your logic I can easily prove that Primary Key is not unique. Create a table with clustered index and then two non-clustered indexes. Then look at the pages of these 2 indexes and you will find 2 IDs with the same values. OMG! Primary Key is not unique. I found the biggest bug in SQL Server. But I doubt that anyone will believe in this. You are simply making conclusions based on misinterpretation. |
|
|
Sachin.Nand
2937 Posts |
Posted - 2012-06-20 : 01:41:02
|
quote: Which is true. For each record in a heap table there is only one RID and for one RID there is only one record in a table.
I know that but what I am saying is that the RID KEY (MAKE AN EFFORT TO FOCUS YOUR EYES ON THE WORD KEY) does not have to be unique.Without making any effort of whatsoever of running my example maybe because of your INABILITY to do so you are getting over my head.If guys like you are on the forum I am better off this forum.@RobovolkAs you quoted some saying for me.I would also like to quote something for you.."Wise men learn more from fools than fools from the wise"...Marcus Porcius CatoOnly free men can negotiate.. |
|
|
robvolk
Most Valuable Yak
15732 Posts |
Posted - 2012-06-20 : 06:28:03
|
quote: Originally posted by Sachin.Nand"Wise men learn more from fools than fools from the wise"...Marcus Porcius Cato
Can't tell which one you take me for, and it seems everyone in this thread is not learning from the other, therefore I think it's best to close it and move on before it gets acrimonious. |
|
|
|