الإرشاد المتسلسل والتفتت
-
27-09-2019 - |
سؤال
أحاول أن أفهم كيف يعمل GUID المتسلسل بشكل أفضل من GUID العادي.
هل لأنه مع GUID العادية ، يستخدم الفهرس البايت الأخير من GUID لفرز؟ نظرًا لأنه عشوائي ، فإنه سيؤدي إلى انشقاقات صفحات وتقسيم الصفحة لأنه غالبًا ما ينقل البيانات إلى صفحة أخرى لإدراج بيانات جديدة؟
Sequential Guid Sine هو متسلسل سيؤدي إلى انشقاقات أقل بكثير من الصفحة والتفتت؟
هل فهمي صحيح؟
إذا كان بإمكان أي شخص إلقاء المزيد من الأضواء على هذا الموضوع ، فسأقدر كثيرًا.
شكرًا لك
تعديل:
GUID التتابع = newSequentialId () ،
Guid = NewID ()
المحلول
لقد قلت كل شيء في سؤالك.
من خلال إضافة صفوف جديدة للمفتاح الرئيسي / المفتاح الأساسي معًا في نهاية الجدول ، مما يجعل الأمور لطيفة لخادم SQL. في المقارنة ، تعني المفتاح الأساسي العشوائي أنه يمكن إدراج سجلات جديدة في أي مكان في الجدول - من المرجح أن تكون فرصة الصفحة الأخيرة للجدول في ذاكرة التخزين المؤقت (إذا كانت كل القراءات تسير) ، ومع ذلك فرصة إن صفحة عشوائية في منتصف الجدول الموجودة في ذاكرة التخزين المؤقت منخفضة إلى حد ما ، مما يعني أن IO إضافية مطلوبة.
علاوة على ذلك ، عند إدخال الصفوف في منتصف الطاولة ، هناك فرصة لعدم وجود مساحة كافية لإدراج الصف الإضافي. إذا كان هذا هو الحال ، فإن SQL Server يحتاج إلى إجراء عمليات IO إضافية باهظة الثمن من أجل إنشاء مساحة للسجل - الطريقة الوحيدة لتجنب ذلك هي وجود فجوات منتشرة بين البيانات للسماح بإدراج سجلات إضافية (تُعرف باسم أ عامل التعبئة) ، والذي يسبب في حد ذاته مشكلات في الأداء لأن البيانات تنتشر على المزيد من الصفحات ، وبالتالي مطلوب المزيد من IO للوصول إلى الجدول بأكمله.
نصائح أخرى
أؤجل حكمة كيمبرلي ل. تريب حول هذا الموضوع:
ولكن ، GUID غير متسلسلة - مثل تلك التي يتم إنشاؤها في العميل (باستخدام .NET) أو التي تم إنشاؤها بواسطة وظيفة NewID () (في خادم SQL) يمكن أن تكون اختيارًا سيئًا بشكل فظيع - بسبب تجزئة ذلك في المقام الأول يخلق في الجدول الأساسي ولكن أيضًا بسبب حجمه. إنها واسعة بشكل لا لزوم لها (إنها أوسع 4 أضعاف من الهوية القائمة على INT - والتي يمكن أن تمنحك 2 مليار صف (4 مليارات) صفوف فريدة). وإذا كنت بحاجة إلى أكثر من ملياري ، فيمكنك دائمًا الذهاب مع Bigint (8 بايت INT) والحصول على 263-1 صفًا.
لتصور الصورة كاملة letil اسمه ostress قد تستخدم. على سبيل المثال ، يمكنك إنشاء جدولين: واحد مع عادي GUID مثل PK ، والآخر مع GUID التسلسل:
-- normal one
CREATE TABLE dbo.YourTable(
[id] [uniqueidentifier] NOT NULL,
CONSTRAINT [PK_YourTable] PRIMARY KEY NONCLUSTERED (id)
);
-- sequential one
CREATE TABLE dbo.YourTableSeq(
[id] [uniqueidentifier] NOT NULL CONSTRAINT [df_yourtable_id] DEFAULT (newsequentialid()),
CONSTRAINT [PK_YourTableSeq] PRIMARY KEY NONCLUSTERED (id)
);
ثم مع استخدام معين ، تقوم بتشغيل عدد من الإدراج مع اختيار الإحصاءات حول تفتيت الفهرس:
ostress -Slocalhost -E -dYourDB -Q"INSERT INTO dbo.YourTable VALUES (NEWID()); SELECT count(*) AS Cnt FROM dbo.YourTable; SELECT AVG_FRAGMENTATION_IN_PERCENT AS AvgPageFragmentation, PAGE_COUNT AS PageCounts FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, N'LIMITED') DPS INNER JOIN sysindexes SI ON DPS.OBJECT_ID = SI.ID AND DPS.INDEX_ID = SI.INDID WHERE SI.NAME = 'PK_YourTable';" -oE:\incoming\TMP\ -n1 -r10000
ostress -Slocalhost -E -dYourDB -Q"INSERT INTO dbo.YourTableSeq DEFAULT VALUES; SELECT count(*) AS Cnt FROM dbo.YourTableSeq; SELECT AVG_FRAGMENTATION_IN_PERCENT AS AvgPageFragmentation, PAGE_COUNT AS PageCounts FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, N'LIMITED') DPS INNER JOIN sysindexes SI ON DPS.OBJECT_ID = SI.ID AND DPS.INDEX_ID = SI.INDID WHERE SI.NAME = 'PK_YourTableSeq';" -oE:\incoming\TMP\ -n1 -r10000
ثم في الملف e: الوارد tmp query.out ستجد إحصائياتك. نتائجي هي:
"Normal" GUID:
Records AvgPageFragmentation PageCounts
----------------------------------------------
1000 87.5 8
2000 93.75 16
3000 96.15384615384616 26
4000 96.875 32
5000 96.969696969696969 33
10000 98.571428571428584 70
Sequential GUID:
Records AvgPageFragmentation PageCounts
----------------------------------------------
1000 83.333333333333343 6
2000 63.636363636363633 11
3000 41.17647058823529 17
4000 31.818181818181817 22
5000 25.0 28
10000 12.727272727272727 55
كما ترون مع إدراج GUID الذي تم إنشاؤه بالتسلسل ، يكون الفهرس أقل تجزئة لأن عملية إدراج تؤدي إلى ندرة تخصيص الصفحة الجديدة.