it-swarm.asia

إدراج فعال في جدول مع فهرس متفاوت المسافات

لديّ عبارة SQL التي تُدرج الصفوف في جدول بفهرس مجمع في العمود TRACKING_NUMBER.

على سبيل المثال:

INSERT INTO TABL_NAME (TRACKING_NUMBER, COLB, COLC) 
SELECT TRACKING_NUMBER, COL_B, COL_C 
FROM STAGING_TABLE

سؤالي هو - هل يساعد على استخدام جملة ORDER BY في عبارة SELECT لعمود الفهرس العنقودي ، أم سيتم رفض أي مكسب تم تحقيقه من خلال الفرز الإضافي المطلوب لشرط ORDER BY؟

29
GWR

كما تشير الإجابات الأخرى بالفعل إلى أن SQL Server قد يضمن أو لا يضمن صراحة أن الصفوف مرتبة في ترتيب فهرس مجمع قبل insert.

يعتمد ذلك على ما إذا كان لدى عامل تشغيل الفهرس العنقودي في الخطة مجموعة خصائص DMLRequestSort (والتي بدورها تعتمد على العدد التقديري للصفوف التي يتم إدراجها).

إذا وجدت أن SQL Server يقلل من قيمة هذا لأي سبب من الأسباب قد تستفيد من إضافة ORDER BY صريح إلى استعلام SELECT لتقليل انقسام الصفحة والتجزئة الناتجة عن عملية INSERT

مثال:

use tempdb;

GO

CREATE TABLE T(N INT PRIMARY KEY,Filler char(2000))

CREATE TABLE T2(N INT PRIMARY KEY,Filler char(2000))

GO

DECLARE @T TABLE (U UNIQUEIDENTIFIER PRIMARY KEY DEFAULT NEWID(),N int)

INSERT INTO @T(N)
SELECT number 
FROM master..spt_values
WHERE type = 'P' AND number BETWEEN 0 AND 499

/*Estimated row count wrong as inserting from table variable*/
INSERT INTO T(N)
SELECT T1.N*1000 + T2.N
FROM @T T1, @T T2

/*Same operation using explicit sort*/    
INSERT INTO T2(N)
SELECT T1.N*1000 + T2.N
FROM @T T1, @T T2
ORDER BY T1.N*1000 + T2.N


SELECT avg_fragmentation_in_percent,
       fragment_count,
       page_count,
       avg_page_space_used_in_percent,
       record_count
FROM   sys.dm_db_index_physical_stats(2, OBJECT_ID('T'), NULL, NULL, 'DETAILED')
;  


SELECT avg_fragmentation_in_percent,
       fragment_count,
       page_count,
       avg_page_space_used_in_percent,
       record_count
FROM   sys.dm_db_index_physical_stats(2, OBJECT_ID('T2'), NULL, NULL, 'DETAILED')
;  

يوضح أن T مجزأة بشكل كبير

avg_fragmentation_in_percent fragment_count       page_count           avg_page_space_used_in_percent record_count
---------------------------- -------------------- -------------------- ------------------------------ --------------------
99.3116118225536             92535                92535                67.1668272794663               250000
99.5                         200                  200                  74.2868173956017               92535
0                            1                    1                    32.0978502594514               200

لكن تجزئة T2 ضئيلة

avg_fragmentation_in_percent fragment_count       page_count           avg_page_space_used_in_percent record_count
---------------------------- -------------------- -------------------- ------------------------------ --------------------
0.376                        262                  62500                99.456387447492                250000
2.1551724137931              232                  232                  43.2438349394613               62500
0                            1                    1                    37.2374598468001               232

على العكس من ذلك ، قد ترغب في فرض SQL Server على التقليل من عدد الصفوف عندما تعلم أن البيانات تم فرزها مسبقًا بالفعل وترغب في تجنب الفرز غير الضروري. أحد الأمثلة البارزة هو عند إدراج عدد كبير من الصفوف في جدول بمفتاح فهرس مجمع newsequentialid. في إصدارات SQL Server السابقة لـ Denali SQL Server يضيف عملية فرز غير ضرورية ومكلفة . يمكن تجنب ذلك عن طريق

DECLARE @var INT =2147483647

INSERT INTO Foo
SELECT TOP (@var) *
FROM Bar

سيقدر SQL Server بعد ذلك أنه سيتم إدراج 100 صف بغض النظر عن حجم Bar الذي يقل عن الحد الذي تتم فيه إضافة فرز إلى الخطة. ومع ذلك ، كما هو موضح في التعليقات أدناه ، فإن هذا يعني أن الإدخال لن يتمكن للأسف من الاستفادة من الحد الأدنى من التسجيل.

18
Martin Smith

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

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

تعديل: 2011-10-28 17:00

إجابة @ Gonsal تظهر أن عملية الفرز تحدث دائمًا ، ليست هذه هي الحالة. مطلوب مخطوطات تجريبية!

نظرًا لأن النصوص البرمجية كانت كبيرة جدًا ، فقد نقلتها إلى Gist . لسهولة التجربة ، تستخدم البرامج النصية وضع SQLCMD. تعمل الاختبارات على 2K5SP3 ، ثنائي النواة ، 8 جيجابايت.

تغطي اختبارات الإدراج ثلاثة سيناريوهات:

  1. مؤشر تجميع البيانات المرحلي في نفس ترتيب الهدف.
  2. مؤشر تجميع البيانات المرحلي بالترتيب العكسي.
  3. بيانات مرحلية مجمعة بواسطة col2 تحتوي على INT عشوائي.

التشغيل الأول ، بإدراج 25 صفًا.

1st run, 25 rows

جميع خطط التنفيذ الثلاثة متشابهة ، ولا يحدث أي فرز في أي مكان في الخطة ويتم مسح الفهرس العنقودي "أمر = خطأ".

الجولة الثانية ، بإدراج 26 صفًا.

2nd run, 26 rows

هذه المرة تختلف الخطط.

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

لذلك ، هناك نقطة حاسمة حيث يرى المحسن أن الفرز ضروري. كما يظهرMartinSmith ، يبدو أن هذا يعتمد على الصفوف المقدرة التي سيتم إدراجها. لا يتطلب جهاز الاختبار 25 الخاص بي نوعًا ، 26 لا يتطلب (2K5SP3 ، ثنائي النواة ، 8 جيجابايت)

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

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

تعديل: 2011-10-28 20:15

اختبارات متكررة على نفس المنصة ولكن مع 2K8R2. هذه المرة نقطة التحول هي 251 صف. مرة أخرى ، لا يؤثر تغيير كثافة الصفحة وعدد الأعداد الحالية.

12
Mark Storey-Smith

عبارة ORDER BY في عبارة SELECT زائدة عن الحاجة.

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

دعونا ننشئ حالة اختبار.

CREATE TABLE #Test (
    id INTEGER NOT NULL
);

CREATE UNIQUE CLUSTERED INDEX CL_Test_ID ON #Test (id);

CREATE TABLE #Sequence (
    number INTEGER NOT NULL
);

INSERT INTO #Sequence
SELECT number FROM master..spt_values WHERE name IS NULL;

لنقم بتمكين عرض النص لخطط الاستعلام الفعلية ، حتى نتمكن من رؤية المهام التي يتم تنفيذها بواسطة معالج الاستعلام.

SET STATISTICS PROFILE ON;
GO

الآن ، دعنا INSERT 2K صفوف في الجدول بدون شرط ORDER BY.

INSERT INTO #Test
SELECT number
  FROM #Sequence

خطة التنفيذ الفعلية لهذا الاستعلام هي التالية.

INSERT INTO #Test  SELECT number    FROM #Sequence
  |--Clustered Index Insert(OBJECT:([tempdb].[dbo].[#Test]), SET:([tempdb].[dbo].[#Test].[id] = [tempdb].[dbo].[#Sequence].[number]))
       |--Top(ROWCOUNT est 0)
            |--Sort(ORDER BY:([tempdb].[dbo].[#Sequence].[number] ASC))
                 |--Table Scan(OBJECT:([tempdb].[dbo].[#Sequence]))

كما ترى ، هناك عامل فرز قبل حدوث INSERT الفعلي.

الآن ، دعنا نمسح الجدول ، و INSERT 2k صف في الجدول مع بند ORDER BY.

TRUNCATE TABLE #Test;
GO

INSERT INTO #Test
SELECT number
  FROM #Sequence
 ORDER BY number

خطة التنفيذ الفعلية لهذا الاستعلام هي التالية.

INSERT INTO #Test  SELECT number    FROM #Sequence   ORDER BY number
  |--Clustered Index Insert(OBJECT:([tempdb].[dbo].[#Test]), SET:([tempdb].[dbo].[#Test].[id] = [tempdb].[dbo].[#Sequence].[number]))
       |--Top(ROWCOUNT est 0)
            |--Sort(ORDER BY:([tempdb].[dbo].[#Sequence].[number] ASC))
                 |--Table Scan(OBJECT:([tempdb].[dbo].[#Sequence]))

لاحظ أنها نفس خطة التنفيذ التي تم استخدامها لعبارة INSERT بدون البند ORDER BY.

الآن ، العملية Sort ليست مطلوبة دائمًا ، كما أظهر مارك سميث في إجابة أخرى (إذا كان عدد الصفوف المطلوب إدخالها منخفضًا) ، لكن ORDER BY لا يزال فقرة] فائضة في هذه الحالة ، لأنه حتى مع ORDER BY صريح ، لا يتم إنشاء عملية Sort بواسطة معالج الاستعلام.

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

تم تحديث 2011-11-02: كما أظهر مارك سميث ، INSERT s في جدول مع قد لا يتطلب الفهرس المجمع دومًا أن يتم فرزه - على الرغم من ذلك ، فإن عبارة ORDER BY زائدة عن الحاجة في هذه الحالة أيضًا.

8
gonsalu