it-swarm.asia

متى يجب الإعلان عن المفتاح الأساسي بدون تجمّع؟

أثناء إنشاء قاعدة بيانات تجريبية لسؤال آخر طرحته سابقًا ، تذكرت إمكانية الإعلان عن مفتاح أساسي NONCLUSTERED

متى تستخدم المفتاح الأساسي NONCLUSTERED بدلاً من المفتاح الأساسي CLUSTERED؟

شكرا مقدما

177
Stuart Blackler

السؤال ليس "متى يجب أن يكون PK هو NC" ، ولكن بدلاً من ذلك يجب عليك أن تسأل "ما هو المفتاح المناسب للمؤشر العنقودي"؟

والجواب يعتمد حقاً على كيف تستعلم عن البيانات. يتميز الفهرس العنقودي بميزة على جميع الفهارس الأخرى: نظرًا لأنه يشمل دائمًا جميع الأعمدة ، فهو يغطي دائمًا. لذلك ، لا تحتاج الاستعلامات التي يمكنها الاستفادة من فهرس المجموعة إلى استخدام عمليات البحث لإرضاء بعض الأعمدة المتوقعة و/أو المسندات.

قطعة أخرى من اللغز كيف يمكن استخدام فهرس؟ هناك ثلاثة أنماط نموذجية:

  • تحقيقات ، عندما يتم البحث عن قيمة مفتاح واحد في الفهرس
  • مسح النطاق ، عندما يتم استرداد مجموعة من القيم الرئيسية
  • الترتيب حسب المتطلبات ، عندما يتمكن الفهرس من تلبية الطلب عن طريق عدم الحاجة إلى فرز متوقف

لذلك إذا قمت بتحليل الحمل المتوقع (الاستعلامات) واكتشفت أن عددًا كبيرًا من الاستعلامات سيستخدم فهرسًا معينًا لأنهم يستخدمون نمطًا معينًا من الوصول يستفيد من فهرس ، فمن المنطقي اقتراح هذا الفهرس على أنه فهرس مجمع.

عامل آخر هو أن مفتاح الفهرس العنقودي هو مفتاح البحث المستخدم من قبل all الفهارس غير العنقودية وبالتالي فإن مفتاح الفهرس واسع التكتل يخلق تأثيرًا مضاعفًا ويوسع جميع المؤشرات غير العنقودية والفهارس العريضة تعني المزيد من الصفحات ، المزيد من الإدخال/الإخراج ، المزيد من الذاكرة ، أقل جودة.

الفهرس العنقودي الجيد هو مستقر ، ولا يتغير خلال عمر الكيان ، لأن التغيير في قيم مفاتيح الفهرس المجمعة يعني أنه يجب حذف الصف وإدراجه مرة أخرى.

وينمو الفهرس المتجمع بشكل جيد بحيث لا يتم بشكل عشوائي (كل قيمة مفتاح مدرجة حديثًا أكبر من القيمة السابقة) لتجنب تجزئة الصفحة وتجزئتها (دون العبث بـ FILLFACTORs).

والآن بعد أن عرفنا ما هو مفتاح الفهرس الجيد ، هل يتطابق المفتاح الأساسي (الذي هو خاصية منطقية لنمذجة البيانات) مع المتطلبات؟ إذا كانت الإجابة بنعم ، فيجب تجميع PK. إذا كانت الإجابة لا ، فيجب ألا يكون PK متجمعًا.

لإعطاء مثال ، خذ بعين الاعتبار جدول حقائق المبيعات. كل إدخال له معرف هو المفتاح الأساسي. لكن الغالبية العظمى من الاستفسارات تطلب بيانات بين تاريخ وتاريخ آخر ، وبالتالي فإن أفضل مفتاح فهرس متفاوت هو المبيعات التاريخ ، وليس معرف . مثال آخر على وجود فهرس مجمع مختلف عن المفتاح الأساسي هو مفتاح انتقائية منخفض للغاية ، مثل "فئة" أو "حالة" ، مفتاح به عدد قليل جدًا من القيم المميزة. امتلاك مفتاح فهرس مجمع مع مفتاح الانتقاء المنخفض هذا كمفتاح أقصى اليسار ، على سبيل المثال (state, id) ، غالبًا ما يكون منطقيًا بسبب عمليات مسح النطاقات التي تبحث عن جميع الإدخالات في "حالة" معينة.

ملاحظة أخيرة حول إمكانية وجود مفتاح أساسي غير مجمع عبر كومة (أي أنه لا يوجد فهرس مجمع) على الإطلاق. قد يكون هذا سيناريو صالحًا ، والسبب النموذجي هو عندما يكون أداء الإدراج المجمَّع أمرًا بالغ الأهمية ، نظرًا لأن كومة الذاكرة المؤقتة لها إنتاجية إدراج إدراج أفضل بشكل كبير عند مقارنتها بالمؤشرات المجمعة.

194
Remus Rusanu

السبب الأساسي لاستخدام الفهارس العنقودية مذكور على ويكيبيديا :

يؤدي التجميع إلى تغيير كتلة البيانات إلى ترتيب مميز معين لمطابقة الفهرس ، مما يؤدي إلى تخزين بيانات الصف بالترتيب. لذلك ، يمكن إنشاء فهرس مجمع واحد فقط في جدول قاعدة بيانات معينة. يمكن للمؤشرات المجمعة أن تزيد بشكل كبير من سرعة الاسترداد الإجمالية ، ولكن عادة فقط حيث يتم الوصول إلى البيانات بالتسلسل في نفس أو ترتيب عكسي للفهرس العنقودي ، أو عند تحديد نطاق من العناصر.

لنفترض أن لدي جدولاً بالأشخاص ، وأن هؤلاء الأشخاص لديهم عمود الدولة ومفتاح أساسي فريد. إنه جدول ديموغرافي ، لذلك هذه هي الأشياء الوحيدة التي أهتم بها ؛ ما البلد وعدد الأشخاص الفريدين المرتبطين بهذا البلد.

وبالتالي ، من المحتمل أن أختار المكان أو الطلب حسب عمود الدولة فقط ؛ لا يساعدني فهرس متجمع على المفتاح الأساسي في تحقيق أي فائدة ، فأنا لا أستطيع الوصول إلى هذه البيانات عن طريق PK ، بل يمكنني الوصول إليها بواسطة هذا العمود الآخر. نظرًا لأنه لا يمكنني سوى وجود فهرس مجمع واحد على جدول ، فإن إعلان PK الخاص بي كـ Clustered سيمنعني من استخدام فهرس مجمع في البلد.

بالإضافة إلى ذلك ، إليك مقالة جيدة عن الفهارس العنقودية مقابل غير المجمعة ، تبين أن الفهارس العنقودية تسببت في إدراج مشكلات في الأداء في SQL Server 6.5 (على الأقل نأمل ألا تكون ذات صلة بمعظمنا هنا).

إذا وضعت فهرسًا مجمعًا في عمود IDENTITY ، فستحدث جميع إدخالاتك في الصفحة الأخيرة من الجدول - وستكون تلك الصفحة مقفلة طوال مدة كل هوية. لا مشكلة كبيرة ... إلا إذا كان لديك 5000 شخص يريدون جميعهم الصفحة الأخيرة. ثم لديك الكثير من التنافس على هذه الصفحة

لاحظ أن هذا ليس هو الحال في الإصدارات اللاحقة.

27
Ben Brocka

إذا كان مفتاحك الأساسي من UNIQUEIDENTIFIER ، فتأكد من تحديد أنه NONCLUSTERED. إذا قمت بتجميعها ، فيجب أن تقوم كل عملية إدخال بمجموعة من السجلات لإدراج الصف الجديد في الموضع الصحيح. سيؤدي ذلك إلى أداء الخزان.

17
Bryan Johns

مثال شائع جدًا:

  • جدول Customer مع CustomerID مثل CLUSTERED PRIMARY KEY
  • جدول ترتيب مع OrderID (PK), CustomerID, OrderDate وبعض الأعمدة الأخرى
  • OrderPositions مع OrderPositionID (PK), OrderId, ProductID, Amount, Price ...
  • عليك فهرسة جداول الطلبات

بالطبع "يعتمد الأمر" - كما هو الحال دائمًا - هو الجواب الصحيح ، ولكن معظم التطبيقات (وليس تقارير BI) ستعمل على أساس العملاء (على سبيل المثال ، تقوم بتسجيل الدخول كعميل 278 في موقع الويب والنقر على "طلباتي" أو يسرد الكاتب جميع الطلبات للعميل 4569 أو سوف يلخص روتين الفاتورة جميع الطلبات للعميل 137).

في هذه الحالة لن يكون من المنطقي تجميع الجدول بواسطة OrderID. نعم ، سيكون لديك استفسارات مثل SELECT ... WHERE OrderId = ? لإدراج تفاصيل الطلب ، ولكن هذا سيكون عادةً قصيرًا ورخيصًا (3 قراءات) يسعى الفهرس.

من ناحية أخرى ، إذا كنت ستقوم بتجميع جدول Order حسب CustomerID ، فلن تضطر إلى إجراء عمليات بحث رئيسية متعددة في كل مرة تقوم فيها بالاستعلام عن الجدول لـ CustomerId = ?.

يجب أن يكون CLUSTERED INDEX دائمًا UNIQUE ، وإلا سيضيف SQL Server عمود INT غير مرئي (= غير قابل للاستخدام) UNIQUIFIER لضمان التفرد - وسيكون من المنطقي إضافته بيانات حقيقية (قابلة للاستخدام) ثم بعض الأشياء العشوائية (حسب ترتيب الإدراج).

نظرًا لأن العميل (نأمل) في تقديم أكثر من طلب واحد ، فسنضطر إلى إضافة OrderID أو (إذا كنت تفرز عادةً لذلك) OrderDate (إذا كان وقتًا - وإلا يقتصر العميل على طلب واحد في اليوم) CLUSTERED INDEX وينتهي بـ:

CREATE UNIQUE CLUSTERED INDEX IX_Orders_UQ on Orders (CustomerID, OrderID)

تنطبق نفس القواعد على جدول OrderPositions. عادةً ما تسرد معظم الاستعلامات جميع المواقف الخاصة بترتيب معين ، لذلك يجب عليك إنشاء PK باستخدام OrderPositionID كـ NONCLUSTERED و UNIQUE CLUSTERED INDEX في OrderId, OrderPositionID.

راجع للشغل: من الصحيح أن جدول Customer تم تجميعه بواسطة PK الخاص به (CustomerID ، لأنه "جدول المستوى الأعلى" وسيتم - في تطبيق نموذجي - في الغالب الاستعلام عنه. بواسطة CustomerID الخاص به.

جداول البحث النقي على سبيل المثال Genders أو InvoiceTypes أو PaymentType هي مثال آخر على الجداول التي يجب تجميعها بواسطة PK الخاص بها (لأنك ستنضم إليها عادةً في GenderId ، InvoiceTypeId أو PaymentTypeId).

8
Thomas Franz

عندما يعتبر المؤشر المجمع أكثر فائدة للنظام العام من PK المجمعة باستخدام بعض قياس الأداء. يمكن أن يكون هناك فهرس مجمع واحد فقط على جدول.

أمثلة على مقاييس الأداء هي وقت الاستعلام الفردي (السرعة) ، ودمج إجمالي أوقات الاستعلام مقابل الجدول (الكفاءة) واضطرار إلى إضافة العديد من الأعمدة إلى فهرس كبير جدًا غير متكتل من أجل تحقيق أداء مماثل للكتلة (الحجم ).

يمكن أن يحدث هذا عندما يتم استرداد البيانات بشكل عام باستخدام فهرس غير فريد ، أو يحتوي على قيم خالية (غير مسموح بها في PK) ، أو تمت إضافة PK لسبب ثانوي (مثل النسخ المتماثل أو تحديد سجل سجل المراجعة).

2
crokusek