sqlschool.gr logo

articles

Articles of SQLschool.gr Team

Uniqueidentifier data type as table primary key or clustered index

Antonios Chatzipavlis
Tuesday 18 January 2011

Περιμένοντας να έρθουν συγγενείς και φίλοι σπίτι να μου ευχηθούν για την γιορτή μου, σκεφτόμουν πώς να ευχαριστήσω όλους που σήμερα είτε με email είτε με μηνύματα στο facebook ή στο messenger μου ευχήθηκαν χρόνια πολλά.

Στο μυαλό μου ήρθε κάτι το οποίο το είδα πάλι να χρησιμοποιείται αλλά όχι και τόσο καλά το αντίθετο θα έλεγα. Aυτό δεν είναι από το sql server data type uniqueidentifier σαν primary key σε table.

Ας δούμε λοιπόν τα πράγματα με την σειρά για να καταλάβουμε το πρόβλημα

Φτιάχνουμε μια νέα βάση που θα γίνει το πείραμα μας

USE master
GO

CREATE DATABASE test
GO

Σε αυτή φτιάχνουμε ένα πίνακα με την εξής δομή

USE test
GO
CREATE TABLE t1 
(
    id UNIQUEIDENTIFIER NOT NULL PRIMARY KEY DEFAULT(NEWID()),
    aa INT IDENTITY NOT NULL,
    otherdata NCHAR(2000) DEFAULT (N'other data')
)

Ο πίνακας αυτός είναι έτσι φτιαγμένος ώστε να χωράνε δύο rows ανά page (1 page = 8K)

Όπως βλέπετε έχω το πεδίο id το οποίο είναι uniquidentifier και το έχω ορίσει σαν primary key και επειδή αυτό πρέπει να παίρνει τιμές έχω βάλει σαν default την function NEWID() η οποία σε κάθε εκτέλεση της μας δίνει ένα μοναδικό GUID.

Επίσης έχω βάλει ένα πεδίο aa το οποίο όπως βλέπετε είναι identity που σημαίνει ότι για κάθε έγγραφή δίνει σειριακό αριθμό ξεκινώντας από το ένα.

Τέλος για φτιάξω τη λογική που ανέφερα παραπάνω να χωράνε δηλαδή δύο rows ανά σελίδα βάζω το πεδίο otherdata nchar(2000) ώστε να έχω ένα record length 4024 bytes απλά του βάζω μια default τιμή ώστε να έχει κάτι.

Εκτελώντας το παραπάνω create command φτιάχνω τον πίνακα μου.

Όπως είναι γνωστό ο SQL Server όταν φτιάχνω ένα πίνακα και του ορίζω το primary key αυτός φτιάχνει ένα unique index για να το υλοποιήσει. Στη περίπτωση δε που δεν υπάρχει ήδη clustered index αυτός είναι unique clustered index, όπως και στο παράδειγμα μας.

Αυτό είναι εύκολα μπορούμε να το επιβεβαιώσουμε εκτελώντας την

sp_helpindex t1
GO
index_name               index_description                                 index_keys
------------------------ ------------------------------------------------- ----------
PK__t1__3213E83F7F60ED59 clustered, unique, primary key located on PRIMARY id

Αφού λοιπόν έχουμε επιβεβαιώσει την υπαρξη του index ας έρθουμε να δούμε πως αυτό είναι φυσικά δομημένος, θυμίζω ότι ακόμα δεν έχουμε βάλει δεδομένα στον πίνακα μας. Αυτό μπορούμε να το δούμε εύκολα με τη χρήση ενός DMV το οποίο δεν είναι άλλο από το sys.dm_db_index_physical_stats.

Έτσι εκτελώντας την παρακάτω εντολή

SELECT index_id, avg_fragmentation_in_percent, page_count 
FROM sys.dm_db_index_physical_stats(DB_ID('test'),OBJECT_ID('t1'),1,NULL,'LIMITED')
GO
 

έχουμε το παρακάτω αποτέλεσμα

index_id    avg_fragmentation_in_percent page_count
----------- ---------------------------- -------------------- 
1           0                            0

Παρατηρούμε ότι όλα τα πεδία μετά από index_id είναι μηδενικά και αυτό είναι σωστό καθώς δεν έχουμε ακόμα βάλει δεδομένα στο πίνακα μας.

Ας έρθουμε όμως να βάλουμε δύο γραμμές σε αυτόν

INSERT INTO t1 DEFAULT VALUES
INSERT INTO t1 DEFAULT VALUES
GO

Και ας ξαναδούμε πως είναι τώρα ο index μας

SELECT index_id, avg_fragmentation_in_percent, page_count
FROM sys.dm_db_index_physical_stats(DB_ID('test'),OBJECT_ID('t1'),1,NULL,'LIMITED') 
GO 

Το αποτέλεσμα θα είναι το παρακάτω

Θα παρατηρήσουμε ότι το page_count είναι ίσο με το έν

index_id    avg_fragmentation_in_percent page_count
----------- ---------------------------- -------------------- 
1           0                            1

α. Άρα έχουμε δύο rows/page. Περίφημα μέχρι έδω!!!

Ας βάλουμε ακόμα δύο γραμμές στον πίνακα μας

INSERT INTO t1 DEFAULT VALUES
INSERT INTO t1 DEFAULT VALUES
GO

Και ας ξαναδούμε την δομή του index μας.

SELECT index_id, avg_fragmentation_in_percent, page_count
FROM sys.dm_db_index_physical_stats(DB_ID('test'),OBJECT_ID('t1'),1,NULL,'LIMITED') 
GO 

Το αποτέλεσμα είναι το παρακάτω

index_id    avg_fragmentation_in_percent page_count
----------- ---------------------------- -------------------- 
1           66,6666666666667             3

Εδώ τώρα παρατηρώ κάτι πολύ περίεργο πρώτα από όλα ότι το row_count είναι ίσο με τρία!!! Και το avg_fragmentation_in_percent είναι ίσο με 66,6666666666667

Αυτό δεν μου αρέσει καθόλου μα καθόλου και φυσικά δεν έχει καμία πιθανότητα να έχω ένα σωστά δομημένο index καθώς επίσης δεν πρόκειται να έχω το επιθυμητό αποτέλεσμα από την χρήση του index.

Πριν προχωρήσω στην αποκάλυψη του γιατί αυτό έχει συμβεί θα βάλω ακόμα μερικές γραμμές στο πίνακα μου ώστε στο σύνολο να είναι εκατό

INSERT INTO t1 DEFAULT VALUES
GO 96

Ας έρθω να δω τι γίνεται με τον index μου

SELECT index_id, avg_fragmentation_in_percent, page_count
FROM sys.dm_db_index_physical_stats(DB_ID('test'),OBJECT_ID('t1'),1,NULL,'LIMITED') 
GO 

Το αποτέλεσμα είναι το παρακάτω και είναι άκρως απογοητευτικό

index_id    avg_fragmentation_in_percent page_count
----------- ---------------------------- -------------------- 
1           98,4615384615385             65

Το fragementation είναι στο θεό αλλά έχω 65 σελίδες αντί για 50 που θα έπρεπε να έχω. Οι 15 αυτές σελίδες διαφορά είναι μόνο για τις 100 γραμμές και φυσικά είναι ένα αρκετά σημαντικό performance penalty καθώς αυτό σημαίνει ΙΟ.

Ας δούμε όμως τα δεδομένα μας

SELECT * FROM t1
GO

Το αποτέλεσμα είναι το παρακάτω

id                                   aa          otherdata
------------------------------------ ----------- -----------
F028B3AF-1415-4081-A006-06DDA3D9FAD2 66          other data 
D58551AF-B632-4297-90A2-10D97AB854D0 51          other data 
A28C272C-1FA3-4506-8C62-1230E0E6926F 75          other data 
2B510EF2-E831-4CC0-BF7C-18B08C932934 24          other data 
394B5429-C8CD-4360-9768-18CE5775A8AE 73          other data 
5950B503-923D-4F33-9B21-1BEECBA1286C 79          other data 
16132ED8-B445-4217-B1E0-1E2D9FA40302 84          other data 
9887FCE3-F229-4236-AEA0-1EBFB5A73CA5 25          other data 
147DEAA4-8725-4797-9EBC-2B341889F9BD 57          other data 
BACC0008-F522-44EE-8A76-2E11BFAFCF80 33          other data 
5DEFA505-EFC3-44AB-9746-2F3AF2838E2D 20          other data 
5BD55DF8-757D-47FA-A53C-35E9AE7B428C 87          other data 
17F09983-33CF-4C48-8D06-36B64CDE3371 98          other data 
9EF858ED-E7B1-4A57-9491-38CB31F62844 90          other data 
3D26646B-DBFC-4D7C-8D9B-419BFF7D0350 47          other data 
7E04E79D-B728-4D8C-8F9E-47700C332433 97          other data 
8B4D0F05-B1F8-40BD-A32C-4D039BACB511 21          other data 
B065A2C4-C4C2-4375-93C8-4DDEF719A278 67          other data 
21C7F7A4-5120-4690-A5B8-5022BDE15233 7           other data 
56ACA620-B7C0-47D1-8821-53D3F2FBDA71 22          other data 
F3D55D7F-F089-424C-AFC8-53E5A76F2B23 31          other data 
2DF49ED6-3113-43AD-A7F4-556CC3328DD8 27          other data 
A7770D81-6818-4A9E-B3FA-57F682DAFFE9 63          other data 
02A840B7-B761-477D-9EB3-598A07A2401F 13          other data 
483B2183-5E03-4618-A39E-5BEF31470CFF 48          other data 
0C702D0F-E9D2-4E63-A5FB-5F66395CA97B 85          other data 
84A84DC9-4F78-4F98-A676-61B89B045A06 76          other data 
03CF97FA-0232-4107-A4FF-61E6FC01CEEA 28          other data 
B1BFB116-44B2-4D2E-BAF6-629854E236EC 64          other data 
95D0F80C-D07D-48B5-93EE-63C1CF67E1DF 95          other data 
BAA630CA-1A98-4DDA-B69B-650FF989B623 55          other data 
9FB18286-7BE6-4BBF-A75D-663961D11F30 71          other data 
D7D4335E-33B7-4FBB-995F-66E15D770284 41          other data 
EBF8C763-6425-4078-9BEF-6A7ADB618F49 58          other data 
2DF2516A-076C-458E-A61C-6A8D379A0F8A 78          other data 
85745D8E-122C-458A-A25C-6B203EEDDDD0 6           other data 
3B53D6A3-5E3D-4672-8FF5-6B725DD50094 77          other data 
F2A31C7E-F409-4FA6-A5AB-6F86F5F0CD21 42          other data 
A4318A22-9055-4FB1-B8BE-71497C1B203B 43          other data 
73923CE8-1F21-471D-BE58-7173C47B8633 68          other data 
76A8FFB8-5D92-4E55-9910-71D773935753 70          other data 
2EB0B127-FF41-478D-A8EC-727FCD0420AB 4           other data 
846E931D-A3E8-4885-BF15-73DCDD8BF06E 49          other data 
5426A25C-B419-4BD0-A8AE-76DEF2BD22B8 91          other data 
3925CE47-DDD1-4689-A4D6-7A8EB3004D63 86          other data 
8176A903-4C10-4DDC-97B4-7C0889442F12 23          other data 
0F436108-401D-40A7-8136-7ED7D91A6A2E 39          other data 
FF52B83A-8FF2-4706-80C3-7F00DE29E0B3 54          other data 
3E29EB19-E709-45F1-9CDD-7FDBBB489DE1 36          other data 
379DEFC6-7757-4A85-B82F-839F88C30AE8 96          other data 
AC7C56BF-3C5E-4EFA-B7A2-83D5E6D18D9A 15          other data 
7543C2EA-EC03-486B-9AB4-84483430E610 74          other data 
83AAC12E-F4C3-48A8-9BF9-8869E6390A4B 8           other data 
4F502BD4-5C99-4DC3-8352-88DA9591B27A 18          other data 
20C8395B-2E91-43C7-8FE1-8B4298BCD4B9 16          other data 
45989F49-574A-4438-A20F-8B609DBF7586 88          other data 
4EB6040C-AC60-42A0-94C9-8BB9542EF541 100         other data 
6476E0AB-7121-4DA2-8888-8CCD5C40CA87 12          other data 
3AA1154A-F650-44DC-B88E-91837A65E60D 19          other data 
228578BB-ABAF-4706-8CE7-93DE05FC3DF2 45          other data 
5A1689CC-7BDA-40A5-82FC-9650D58739AE 30          other data 
058F97B1-7AF7-4F32-801F-9AE3B284A9BB 80          other data 
07E106C4-0307-4ABE-AF02-9C734506BAC8 92          other data 
636CD13F-212B-4EAF-86C2-9EC3A8733DF6 40          other data 
23C8B3AE-77F2-45DC-BCE3-A0442EC0F8B3 52          other data 
E35160E1-FAD0-4CB3-9FCF-A2B2278EC4AA 61          other data 
758B3131-4329-46B2-A6D8-A2DC2A56ED8B 29          other data 
DA36FFC6-ADBD-4A38-B236-A3DFA3B7828B 94          other data 
98E8BC0F-4ABF-4CB5-BF9A-A4616CB51C7A 34          other data 
1A95A814-4D04-4C76-B378-A7E56CE4C685 82          other data 
D78D5EB7-9516-44E2-A196-A94205B35A8A 3           other data 
2E8B0887-CEB2-4487-B6F0-AE614E587488 59          other data 
67CA7AF8-18D4-45A3-9D53-AEB9A0EF97C8 99          other data 
A35AB10B-3F47-4184-A6FA-B8E38495A8C0 5           other data 
FFBCDA30-3134-49AB-8CD3-B9C512E50B0B 56          other data 
567EAD09-BF58-4027-9ABC-BCB62767DFE4 93          other data 
F0BAA52F-E5CA-42C0-A6D3-BFB81531CAFA 62          other data 
972F5A38-4F74-43E4-BCE6-C357E7D953D5 65          other data 
3258AB31-3A35-46BA-A053-C7686F3281BD 37          other data 
D3C00476-8582-4D61-B198-C7B5711BEF00 81          other data 
F521BBF6-770A-41D0-8FA5-C8E0684FD7D5 26          other data 
0BAE24EF-E7FE-42DD-BEA1-CA02A4024D5B 69          other data 
AA6BD0D8-EC8C-4B21-B21B-D429331C56B8 11          other data 
998FDC1B-7CAE-40DF-9AFA-DA3FD8CDCADB 89          other data 
4352A25D-A50B-42C3-A241-DC19BD7207D3 60          other data 
3F393EF3-3A26-4D36-BD00-DE9B9C63097E 38          other data 
B8A37EFF-5121-499E-AA22-E0ABE9C6293D 9           other data 
20B7C188-751F-4D90-8B9E-E1D4889A3795 1           other data 
CB2765CC-0FDA-423F-A5FE-E420A37BF2D5 72          other data 
2CE206A3-5481-4DC8-A725-E497611DD8BF 14          other data 
B1F04446-A9FB-4A64-8462-E5D02E4B5C71 17          other data 
89E50E9D-D1F9-488F-ADF0-EB13BD8B9D3F 83          other data 
3189B3B3-3892-4307-916F-EBC3E77573EE 44          other data 
3427F572-F535-4BF4-ADCC-EDC7E4C98E39 46          other data 
C93EDF08-35B4-430F-80B3-EE2605439DEE 2           other data 
15E0FBF2-18EF-41E4-938F-EFE7F0CA76F5 53          other data 
F665CAF8-C9BC-45D3-AD2B-F3E630FD8C5F 10          other data 
17C1CB7F-6C98-4A3D-9CD5-F883312B47C8 50          other data 
0191B624-C765-4C41-8FE3-FC0C07B82609 35          other data 
006D1851-23AC-4325-AD48-FE76F73F31BC 32          other data 

Αν προσεκτικά παρατηρήσουμε το αποτέλεσμα θα δούμε ότι τα rows έχουν ταξινομηθεί με βάση το id αλλά δεν έχουν μπει όμως το ένα κάτω από το άλλο καθώς αυτό φαίνεται από το πεδίο aa το οποίο μας δείχνει την σειρά εισαγωγής του row στο πίνακα.

Αν μείνουμε μέχρι εδώ βγαίνει το συμπέρασμα ότι η χρήση του sql server data type σαν primary key σε ένα πίνακα είναι κακή, κάκιστη θα έλεγα επιλογή. Όμως δεν είναι έτσι τα πράγματα. Για αυτό ας κάνουμε ακόμα ένα πείραμα.

Ας φτιάξουμε ένα ακόμα πίνακα όπως παρακάτω

USE test
GO 

CREATE TABLE t2 
(
    id UNIQUEIDENTIFIER NOT NULL PRIMARY KEY DEFAULT(NEWSEQUENTIALID()),
    aa INT IDENTITY NOT NULL,
    otherdata NCHAR(2000) DEFAULT (N'other data')
)

Αυτός είναι ακριβώς ίδιος με το προηγούμενο αλλά υπάρχει μια σημαντική διαφορά αντί να χρησιμοποιώ την NEWID() χρησιμοποιώ την  NEWSEQUENTIALID() (είναι διαθέσιμη από την έκδοση του SQL Server 2005!!!).

Aς επιβεβαιώσουμε ότι έχουμε τον index μας

sp_helpindex t2
GO

index_name               index_description                                 index_keys
------------------------ ------------------------------------------------- ----------
PK__t2__3213E83F0519C6AF clustered, unique, primary key located on PRIMARY id

Και ας δούμε την δομή του index μας

SELECT index_id, avg_fragmentation_in_percent, page_count
FROM sys.dm_db_index_physical_stats(DB_ID('test'),OBJECT_ID('t2'),1,NULL,'LIMITED') 
GO 
index_id    avg_fragmentation_in_percent page_count
----------- ---------------------------- -------------------- 
1           0                            0

Ας βάλουμε τις δύο πρώτες γραμμές στο πίνακα μας

INSERT INTO t2 DEFAULT VALUES
INSERT INTO t2 DEFAULT VALUES
GO

Και ας δούμε την δομή του index μας

SELECT index_id, avg_fragmentation_in_percent, page_count
FROM sys.dm_db_index_physical_stats(DB_ID('test'),OBJECT_ID('t2'),1,NULL,'LIMITED') 
GO 
index_id    avg_fragmentation_in_percent page_count
----------- ---------------------------- -------------------- 
1           0                            1

Όλα όπως βλέπουμε είναι φυσιολογικά. Ας βάλουμε τις επόμενες δύο γραμμές στον πίνακα μας

INSERT INTO t2 DEFAULT VALUES
INSERT INTO t2 DEFAULT VALUES
GO

Και να δούμε τη δομή του index

SELECT index_id, avg_fragmentation_in_percent, page_count
FROM sys.dm_db_index_physical_stats(DB_ID('test'),OBJECT_ID('t2'),1,NULL,'LIMITED') 
GO 

index_id    avg_fragmentation_in_percent page_count
----------- ---------------------------- -------------------- 
1           50                           2

Όλα πάλι είναι φυσιλογικά έχω page_count ίσο με 2 που είναι και το φυσιλογικό μιας και έχω τέσσερεις γραμμές. Το avg_fragmentation_in_percent είναι υψηλό (50%) αλλά για να δούμε τι θα γίνει με αυτό αν βάλουμε στο πίνακα μας ακόμα 96 εγγραφές ώστε στο σύνολο να γίνουν 100?

INSERT INTO t2 DEFAULT VALUES
GO 96
SELECT index_id, avg_fragmentation_in_percent, page_count
FROM sys.dm_db_index_physical_stats(DB_ID('test'),OBJECT_ID('t2'),1,NULL,'LIMITED') 
GO 

index_id    avg_fragmentation_in_percent page_count
----------- ---------------------------- -------------------- 
1           4                            50

Όπως βλέπουμε αυτό έχει μειωθεί σημαντικά αλλά το περισσότερο σημαντικό είναι ότι ο αριθμός των σελίδων (page_count) έχει παραμείνει σωστός (50 σελίδες) δηλαδή 2 rows/page.

Για να δούμε και τα δεδομένα μας στο πίνακα

SELECT * FROM t2
GO

id                                   aa          otherdata
------------------------------------ ----------- ----------
A6D5C824-7922-E011-A143-00155D020606 1           other data                                             
A7D5C824-7922-E011-A143-00155D020606 2           other data                                             
D439AA51-7922-E011-A143-00155D020606 3           other data                                             
D539AA51-7922-E011-A143-00155D020606 4           other data                                             
2C2FEF8C-7922-E011-A143-00155D020606 5           other data                                             
2D2FEF8C-7922-E011-A143-00155D020606 6           other data                                             
2E2FEF8C-7922-E011-A143-00155D020606 7           other data                                             
2F2FEF8C-7922-E011-A143-00155D020606 8           other data                                             
302FEF8C-7922-E011-A143-00155D020606 9           other data                                             
312FEF8C-7922-E011-A143-00155D020606 10          other data                                             
322FEF8C-7922-E011-A143-00155D020606 11          other data                                             
332FEF8C-7922-E011-A143-00155D020606 12          other data                                             
342FEF8C-7922-E011-A143-00155D020606 13          other data                                             
352FEF8C-7922-E011-A143-00155D020606 14          other data                                             
362FEF8C-7922-E011-A143-00155D020606 15          other data                                             
372FEF8C-7922-E011-A143-00155D020606 16          other data                                             
382FEF8C-7922-E011-A143-00155D020606 17          other data                                             
392FEF8C-7922-E011-A143-00155D020606 18          other data                                             
3A2FEF8C-7922-E011-A143-00155D020606 19          other data                                             
3B2FEF8C-7922-E011-A143-00155D020606 20          other data                                             
3C2FEF8C-7922-E011-A143-00155D020606 21          other data                                             
3D2FEF8C-7922-E011-A143-00155D020606 22          other data                                             
3E2FEF8C-7922-E011-A143-00155D020606 23          other data                                             
3F2FEF8C-7922-E011-A143-00155D020606 24          other data                                             
402FEF8C-7922-E011-A143-00155D020606 25          other data                                             
412FEF8C-7922-E011-A143-00155D020606 26          other data                                             
422FEF8C-7922-E011-A143-00155D020606 27          other data                                             
432FEF8C-7922-E011-A143-00155D020606 28          other data                                             
442FEF8C-7922-E011-A143-00155D020606 29          other data                                             
452FEF8C-7922-E011-A143-00155D020606 30          other data                                             
462FEF8C-7922-E011-A143-00155D020606 31          other data                                             
472FEF8C-7922-E011-A143-00155D020606 32          other data                                             
482FEF8C-7922-E011-A143-00155D020606 33          other data                                             
492FEF8C-7922-E011-A143-00155D020606 34          other data                                             
4A2FEF8C-7922-E011-A143-00155D020606 35          other data                                             
4B2FEF8C-7922-E011-A143-00155D020606 36          other data                                             
4C2FEF8C-7922-E011-A143-00155D020606 37          other data                                             
4D2FEF8C-7922-E011-A143-00155D020606 38          other data                                             
4E2FEF8C-7922-E011-A143-00155D020606 39          other data                                             
4F2FEF8C-7922-E011-A143-00155D020606 40          other data                                             
502FEF8C-7922-E011-A143-00155D020606 41          other data                                             
512FEF8C-7922-E011-A143-00155D020606 42          other data                                             
522FEF8C-7922-E011-A143-00155D020606 43          other data                                             
532FEF8C-7922-E011-A143-00155D020606 44          other data                                             
542FEF8C-7922-E011-A143-00155D020606 45          other data                                             
552FEF8C-7922-E011-A143-00155D020606 46          other data                                             
562FEF8C-7922-E011-A143-00155D020606 47          other data                                             
572FEF8C-7922-E011-A143-00155D020606 48          other data                                             
582FEF8C-7922-E011-A143-00155D020606 49          other data                                             
592FEF8C-7922-E011-A143-00155D020606 50          other data                                             
5A2FEF8C-7922-E011-A143-00155D020606 51          other data                                             
5B2FEF8C-7922-E011-A143-00155D020606 52          other data                                             
5C2FEF8C-7922-E011-A143-00155D020606 53          other data                                             
5D2FEF8C-7922-E011-A143-00155D020606 54          other data                                             
5E2FEF8C-7922-E011-A143-00155D020606 55          other data                                             
5F2FEF8C-7922-E011-A143-00155D020606 56          other data                                             
602FEF8C-7922-E011-A143-00155D020606 57          other data                                             
612FEF8C-7922-E011-A143-00155D020606 58          other data                                             
622FEF8C-7922-E011-A143-00155D020606 59          other data                                             
632FEF8C-7922-E011-A143-00155D020606 60          other data                                             
642FEF8C-7922-E011-A143-00155D020606 61          other data                                             
652FEF8C-7922-E011-A143-00155D020606 62          other data                                             
662FEF8C-7922-E011-A143-00155D020606 63          other data                                             
672FEF8C-7922-E011-A143-00155D020606 64          other data                                             
682FEF8C-7922-E011-A143-00155D020606 65          other data                                             
692FEF8C-7922-E011-A143-00155D020606 66          other data                                             
6A2FEF8C-7922-E011-A143-00155D020606 67          other data                                             
6B2FEF8C-7922-E011-A143-00155D020606 68          other data                                             
6C2FEF8C-7922-E011-A143-00155D020606 69          other data                                             
6D2FEF8C-7922-E011-A143-00155D020606 70          other data                                             
6E2FEF8C-7922-E011-A143-00155D020606 71          other data                                             
6F2FEF8C-7922-E011-A143-00155D020606 72          other data                                             
702FEF8C-7922-E011-A143-00155D020606 73          other data                                             
712FEF8C-7922-E011-A143-00155D020606 74          other data                                             
722FEF8C-7922-E011-A143-00155D020606 75          other data                                             
732FEF8C-7922-E011-A143-00155D020606 76          other data                                             
742FEF8C-7922-E011-A143-00155D020606 77          other data                                             
752FEF8C-7922-E011-A143-00155D020606 78          other data                                             
762FEF8C-7922-E011-A143-00155D020606 79          other data                                             
772FEF8C-7922-E011-A143-00155D020606 80          other data                                             
782FEF8C-7922-E011-A143-00155D020606 81          other data                                             
792FEF8C-7922-E011-A143-00155D020606 82          other data                                             
7A2FEF8C-7922-E011-A143-00155D020606 83          other data                                             
7B2FEF8C-7922-E011-A143-00155D020606 84          other data                                             
7C2FEF8C-7922-E011-A143-00155D020606 85          other data                                             
7D2FEF8C-7922-E011-A143-00155D020606 86          other data                                             
7E2FEF8C-7922-E011-A143-00155D020606 87          other data                                             
7F2FEF8C-7922-E011-A143-00155D020606 88          other data                                             
802FEF8C-7922-E011-A143-00155D020606 89          other data                                             
812FEF8C-7922-E011-A143-00155D020606 90          other data                                             
822FEF8C-7922-E011-A143-00155D020606 91          other data                                             
832FEF8C-7922-E011-A143-00155D020606 92          other data                                             
842FEF8C-7922-E011-A143-00155D020606 93          other data                                             
852FEF8C-7922-E011-A143-00155D020606 94          other data                                             
862FEF8C-7922-E011-A143-00155D020606 95          other data                                             
872FEF8C-7922-E011-A143-00155D020606 96          other data                                             
882FEF8C-7922-E011-A143-00155D020606 97          other data                                             
892FEF8C-7922-E011-A143-00155D020606 98          other data                                             
8A2FEF8C-7922-E011-A143-00155D020606 99          other data                                             
8B2FEF8C-7922-E011-A143-00155D020606 100         other data

Αν παρατηρήσουμε τα δεδομένα θα δούμε ότι αυτά είναι ταξινομημένα με το id αλλά έχουμε σωστή και την σειρά καταχωρήσης, δηλαδή το πρώτο record μπήκε πρώτο και το id στην ταξινόμηση είναι πρώτο το δεύτερο το τρίτο, …, το εκατοστό.

Όμως αυτό δεν είναι ο λόγος που τώρα είναι όλα καλά.

Όπως γνωρίζουμε στο leaf level του index είναι ο index ταξινομημένος. Επίσης επειδή ο index μας είναι clustered στην ουσία το leaf level και τα data pages είναι το ίδιο και το αυτό.

Στην πρώτη περίπτωση με την χρήση της NEWID(), η οποία κάθε φορά επιστρέφει ένα τυχαίο GUID, σαν default value έχω το εξής φαινόμενο

Με το που βάζω το πρώτο record αυτό μπαίνει στη σελίδα πχ 1 το δεύτερο μπαίνει και αυτό σε αυτή τη σελίδα, έτσι η σελίδα μας είναι ως εξής

id                                   aa          otherdata
------------------------------------ ----------- ----------------------
20B7C188-751F-4D90-8B9E-E1D4889A3795 1           other data 
C93EDF08-35B4-430F-80B3-EE2605439DEE 2           other data

Όταν πάμε να βάλουμε το τρίτο record το οποίο είναι το παρακάτω

D78D5EB7-9516-44E2-A196-A94205B35A8A 3 other data

Το οποίο πρέπει να μπει πριν από το πρώτο έτσι πρέπει να γίνει page split στην πρώτη σελίδα και επειδή δεν έχουμε ορίζει κάποιο fillfactor στον index (default ίσο 0 που σημαίνει ότι αφήνει χώρο ώστε να μπορεί να μπει ακόμα μία έγγραφή) δημιουργούνται τρεις σελίδες όπου η κάθε μια έχει από ένα record

Page 1
id                                   aa          otherdata
------------------------------------ ----------- ------------
D78D5EB7-9516-44E2-A196-A94205B35A8A 3           other data
Page 2
id aa otherdata
------------------------------------ ----------- ------------
20B7C188-751F-4D90-8B9E-E1D4889A3795 1           other data 
Page 3
id aa otherdata
------------------------------------ ----------- ------------
C93EDF08-35B4-430F-80B3-EE2605439DEE 2           other data

Βάζοντας και την τέταρτη εγγραφή η δομή του index είναι η παρακάτω

Page 1
id                                   aa          otherdata
------------------------------------ ----------- ---------------
D539AA51-7922-E011-A143-00155D020606 4           other data
D78D5EB7-9516-44E2-A196-A94205B35A8A 3           other data
Page 2
id                                   aa          otherdata
------------------------------------ ----------- ---------------
20B7C188-751F-4D90-8B9E-E1D4889A3795 1           other data 
Page 3
id                                   aa          otherdata
------------------------------------ ----------- --------------
C93EDF08-35B4-430F-80B3-EE2605439DEE 2           other data

Εξου και το αποτέλεσμα που πήραμε και είδαμε ότι είχαμε 3 σελίδες. Αυτό συμβαίνει σε όλες τις άλλες εγγραφές με την ίδια λογική και έτσι έχουμε το τελικό αποτέλεσμα με το μεγάλο fragmentation και τις 65 σελίδες.

Στο δεύτερο πίνακα όμως δεν συμβαίνει κάτι τέτοιο καθώς η   NEWSEQUENTIALID() δίνει σειριακά GUIDs. Έτσι δεν έχουμε ούτε ουσιαστικά μεγάλο fragmentation ούτε παραπάνω αριθμό σελίδων.

Συμπέρασμα

Το πεδίο uniqueidentifier δεν έχει απολύτως κανένα πρόβλημα να είναι primary key σε ένα πίνακα (κατ’ επέκταση θα έλεγα ότι δεν έχει κανένα πρόβλημα να είναι clustered key) ΑΡΚΕΙ να γεμίζει με την NEWSEQUENTIALID() function και όχι με την NEWID() function.

Antonios Chatzipavlis

Antonios Chatzipavlis

Antonios is a Data Solutions Consultant and Trainer. He has been working in IT since 1988. In his career, he has worked as senior developer, IT Manager, Solutions Architect and IT Consultant. Since 1995 he has been devoted on new technologies and software development tools, mainly by Microsoft, either by training company staff and colleagues or assisting them in design, development and implementation as a consultant or chief developer. He has focused in Databases and Data Science since 1995. He specialized in Microsoft SQL Server since version 6.0 in areas like SQL Server Internals, Database Design and Development, Business Intelligence and in 2010 he has started working with Azure Data Platform, NoSQL databases, Big Data Technologies and Machine Learning. He is an active member of many IT communities in Greece, answering colleagues' questions and writing articles in his web site. He is the owner of SQLschool.gr which is a community portal with a lot of information about Microsoft SQL Server. He has been a Microsoft Certified Trainer (MCT) since 2000. Microsoft honored him as MVP on Data Platform due to his activities in SQL Server since 2010. He holds a large number of Microsoft Certifications and Microsoft SQL Server Certifications since version 6.5.

Tip

What's New in SQL Server 2022 - Episodes

More Tips...

Become a member

If you want to receive updates from us become a member to our community.

Connect

Explore

Learn


sqlschool.gr © 2010-2024 All rights reserved

This site uses cookies for operational and analytics purposes only. By continuing to browse this site, you agree to their use.