Jump to content
  • entries
    292
  • comments
    368
  • views
    59730

Uniqueidentifier data type as table primary key or clustered index


antonch

980 views

 Share

Περιμένοντας να έρθουν συγγενείς και φίλοι σπίτι να μου ευχηθούν για την γιορτή μου, σκεφτόμουν πώς να ευχαριστήσω όλους που σήμερα είτε με 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


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



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


Θα παρατηρήσουμε ότι το page_count είναι ίσο με το ένα. Άρα έχουμε δύο 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.

 Share

5 Comments


Recommended Comments

F***!

 

Τώρα ξέρεις σε πόσες βάσεις θα με βάλεις να αλλάξω default; και πρώτα από όλες πρέπει να διορθώσω όλες τις βάσεις του Community Server!!!

Link to comment

Να ρωτήσω όμως κάτι άλλο Αντώνη; Σε περίπτωση που θέλεις να κάνεις κάτι τετοιο, γιατί έτσι κι αλλοιώς το index του primary δεν το χρησιμοποιείς "βαριά" και γιατί θέλεις να είσαι σίγουρος ότι σε περιπτώσεις synchronization μεταξύ βάσεων, δεν θα έχεις conflict, ώστε να αναγκαστείς να γράφεις και conflict resolution code με ότι αυτό συνεπάγετε, το trade off δεν είναι τόσο "φοβερό" να το αλλάξεις σε seq id. Το σενάριο που περιγράφεις παραπάνω, το ήξερα πριν την υλοποίηση έχοντας διαβάσει online διάφορα πράγματα, παρ'όλαυτά για τους λόγους που περιγράφω παραπάνω επέλεξα non sequential id. Ιδέες/προτάσεις επάνω σ'αυτό;

Link to comment

@Panagiotis Kefalidis

Φίλε Παναγιώτη έτσι και αλλιώς του κάνεις μεγάλη χρήση καθώς το primary key είναι unique clustered index και θα είναι παντα fragmented καθώς όταν θα γίνεται insert ένα record θα πρέπει να παει στη σωστά ταξινομημένη θέση του, πράγμα που σημαίνει ότι θα έχεις συχνά page spliting ειδικότερα στο leaf level (=data pages)(το οποίο κοστίζει σε resources) και φυσικά όταν θα χρειαστείς να διαβάζεις τα δεδομένα θα διαβάζεις περισσότερες σελίδες. Ακόμα θα πρέπει να λάβεις σοβαρά υπόψην σου ότι όλοι οι nonclustered indexes πατάνε πάνω στον clustered index.

Link to comment

@Panagiotis Kefalidis

 

Όσο αφορά τα δεύτερο σκέλος της ερώτησης σου που όπως σωστά μου επισήμανες ότι δεν σου απάντησα στο msn, νόμιζα ότι την είχες δει στα BOL. Αλλά αντιγράφω από αυτά μια παράγραφο η οποία αποτελεί και απάντηση στο ερώτημα σου

"Each GUID generated by using NEWSEQUENTIALID() is unique on that computer. GUIDs generated by using NEWSEQUENTIALID() are unique across multiple computers only if the source computer has a network card."

Link to comment

Όχι, η αλήθεια είναι ότι δεν το είχα ψάξει, γι'αυτό με την ευκαιρία αυτού το έθεσα σαν ερώτημα εάν είναι οσο unique πρέπει εφόσον είναι sequential.. Ευχαριστώ για τις απαντήσεις Αντώνη.

Link to comment
Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...