it-swarm.asia

لماذا لا تزال قاعدة البيانات مجزأة بعد أن أعيد بناء كل شيء وأعيد فهرسته؟

لدي قاعدة بيانات حاولت إلغاء تجزئتها لجميع الجداول مرة واحدة عن طريق تشغيل T-SQL:

SELECT 
        'ALTER INDEX all ON ' + name + ' REORGANIZE;' + CHAR(10) +
        'ALTER INDEX all ON ' + name + ' REBUILD;'
    FROM sys.tables

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

قمت بتشغيل هذا لتحديد ما زلت تعاني من التجزئة:

SELECT * FROM 
sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, NULL) 
WHERE avg_fragmentation_in_percent > 0

وحصلت على:

database_id object_id   index_id    partition_number    index_type_desc alloc_unit_type_desc    index_depth index_level avg_fragmentation_in_percent    fragment_count  avg_fragment_size_in_pages  page_count  avg_page_space_used_in_percent  record_count    ghost_record_count  version_ghost_record_count  min_record_size_in_bytes    max_record_size_in_bytes    avg_record_size_in_bytes    forwarded_record_count  compressed_page_count
85  171147655   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   36.3636363636364    5   2.2 11  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  421576540   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   75  7   1.14285714285714    8   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  965578478   1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   14.7058823529412    6   5.66666666666667    34  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1061578820  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   40  4   1.25    5   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1109578991  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   30.7692307692308    5   2.6 13  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1205579333  2   1   NONCLUSTERED INDEX  IN_ROW_DATA 2   0   50  5   1.6 8   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
85  1493580359  1   1   CLUSTERED INDEX IN_ROW_DATA 2   0   50  6   1.66666666666667    10  NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL

أعلم أنني أفتقد شيئًا أساسيًا حقيقيًا ، لكنني لا أعرف ماذا.

41
Justin Dearing

الجداول صغيرة. عدد الصفحات في الجداول الخاصة بك هي:

11 ، 8 ، 6 ، 5 ، 13 ، 8 ، 10

يشغلون 480 كيلو بايت في المجموع. لا يوجد شيء لإلغاء التجزئة حرفيا.

تحرير: هذا يستدعي المزيد من الشرح.

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

تميل البرامج النصية defrag الأكثر استخدامًا (زوجان من الأمثلة المرتبطة أدناه) إلى استبعاد الجداول الصغيرة بسبب هذا. IIRC ،> 500 صفحة في واحدة أو كلتيهما. في هذه الأحجام ، هناك فائدة قليلة جدًا لإلغاء التجزئة ومن المحتمل أن تكون أرقام التجزئة مشوهة بسبب تخصيصات الحجم المختلط.

38
Mark Storey-Smith

اقتباس من " أفضل الممارسات لإلغاء التجزئة لفهرس Microsoft SQL Server 20 ":

"تؤثر التجزئة على القرص I/O. لذلك ، ركز على الفهارس الأكبر نظرًا لأن صفحاتهم أقل احتمالا في التخزين المؤقت بواسطة SQL Server. استخدم عدد الصفحات التي أبلغ عنها DBCC SHOWCONTIG للحصول على فكرة عن حجم الفهارس (كل صفحة 8 كيلوبايت في الحجم). بشكل عام ، يجب ألا تهتم بمستويات تجزئة الفهارس التي تحتوي على أقل من 1000 صفحة. في الاختبارات ، حققت الفهارس التي تحتوي على أكثر من 10000 صفحة مكاسب في الأداء ، مع أكبر مكاسب على الفهارس ذات صفحات أكثر بكثير (أكثر من 50000 صفحة) . "

لذا فإن هذا النوع من الإجابات يجيب على سؤالك ويدعم إجابات مارك وآرون.

يمكنك العثور على معلومات جيدة حول تجزئة الفهرس في المقالات التالية من Brent Ozar:

أيضًا .. يمكن العثور على محيط من المعلومات الرائعة حول الفهارس بشكل عام (أيضًا حول مشكلات التجزئة) على مدونة Kimberly Tripp .

20
Marian

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

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'ALTER INDEX all ON ' + name + ' REBUILD;
    ' FROM sys.tables;

PRINT @sql; -- to see the first 8,000 characters and make sure it checks out
-- EXEC sp_executesql @sql;
12
Aaron Bertrand