เหตุใดลำดับ Denali จึงควรทำงานได้ดีกว่าคอลัมน์ข้อมูลประจำตัว


36

ในคำตอบของเขาที่จะดีกว่า: คอลัมน์ข้อมูลประจำตัวหรือสร้างค่ารหัสที่ไม่ซ้ำกัน? mrdenny พูดว่า:

เมื่อ SQL Denali ออกมามันจะสนับสนุนลำดับซึ่งจะมีประสิทธิภาพมากกว่าเอกลักษณ์ แต่คุณไม่สามารถสร้างสิ่งที่มีประสิทธิภาพมากขึ้นด้วยตัวคุณเอง

ผมไม่แน่ใจ. เมื่อทราบลำดับของ Oracle ฉันต้องสร้างทริกเกอร์สำหรับแทรกใส่แค็ปซูลแต่ละอันไว้ในการเรียกโพรซีเดอร์ที่เก็บไว้หรือภาวนาว่าฉันไม่ลืมที่จะใช้ลำดับเมื่อฉันแทรกโฆษณาแบบเฉพาะกิจ

ฉันสงสัยว่าข้อดีของลำดับนั้นชัดเจนมาก


2
ฉันรู้ว่ามันไม่ได้ตอบคำถามของคุณ แต่นอกเหนือจากความแตกต่างของประสิทธิภาพการเรียงลำดับมีข้อดีอื่น ๆ ตัวอย่างเช่นลำดับไม่ได้หยุดคุณอัปเดตคอลัมน์เป้าหมายซึ่งเป็นข้อ จำกัด ที่ไม่สะดวกของ IDENTITY
nvogel

คำตอบ:


37

ฉันจะตอบที่นี่เช่นกัน มันจะทำอย่างไรกับ internals ของวิธีการIDENTITYและSEQUENCEการทำงาน

ด้วยIDENTITYSQL Server จะแคชค่าล่วงหน้าลงในหน่วยความจำเพื่อให้พร้อมใช้งาน ดูคำตอบของ Martin Smithสำหรับรายละเอียด เมื่อใช้ค่ากระบวนการพื้นหลังจะสร้างค่าเพิ่มเติม ในขณะที่คุณสามารถจินตนาการสระว่ายน้ำนี้จะหมดเร็วอย่างรวดเร็วโดยปล่อยให้แอปพลิเคชั่นอยู่ในความเมตตาของกระบวนการพื้นหลังที่กำลังสร้างค่า

ด้วยSEQUENCESQL Server อนุญาตให้คุณกำหนดขนาดแคชที่ควรจะเป็น ในขณะที่ SQL Server ไม่ได้เก็บค่าไว้ในแคชจริง ๆ เพียงเก็บค่าปัจจุบันและค่าปลายด้านบนซึ่งจะลดจำนวน IO ที่จำเป็นในการสร้างค่า

อย่าตั้งค่าแคชสูงเกินไปเนื่องจากจะช่วยลดจำนวนตัวเลขที่สามารถใช้งานได้: หาก SQL Server เกิดข้อผิดพลาดค่าใด ๆ ที่ระบุในช่วงแคชปัจจุบันที่ไม่ได้ใช้จะหายไป

สำหรับการแทรกแถวเพียงระบุค่าเริ่มต้นสำหรับคอลัมน์ดังนี้:

DEFAULT (NEXT VALUE FOR Audit.EventCounter),

21

ตั้งแต่บทความ Itzik Ben Ganถูกเขียนขนาดแคช hardcoded ที่ 10 สำหรับIDENTITYดูเหมือนว่าจะมีการเปลี่ยนแปลง จากความคิดเห็นในรายการเชื่อมต่อนี้

ขนาดของการจัดสรรล่วงหน้าขึ้นอยู่กับขนาดของชนิดข้อมูลของคอลัมน์ที่คุณสมบัติการระบุไว้ สำหรับคอลัมน์จำนวนเต็ม SQL Server เซิร์ฟเวอร์จะจัดสรรข้อมูลประจำตัวในช่วงของค่า 1,000 ค่า สำหรับข้อมูล bigint ให้พิมพ์เซิร์ฟเวอร์จัดสรรล่วงหน้าในช่วง 10,000 ค่า

T-SQL สอบถามหนังสือมีตารางต่อไปนี้ แต่เน้นว่าค่าเหล่านี้จะไม่ได้รับเอกสารหรือรับประกันว่าจะไม่มีการเปลี่ยนแปลง

+-----------------+-----------+
|    DataType     | CacheSize |
+-----------------+-----------+
| TinyInt         | 10        |
| SmallInt        | 100       |
| Int             | 1,000     |
| BigInt, Numeric | 10,000    |
+-----------------+-----------+

บทความที่นี่ทดสอบขนาดแคชลำดับและการแทรกขนาดแบตช์ต่างๆและเกิดขึ้นกับผลลัพธ์ต่อไปนี้

ป้อนคำอธิบายรูปภาพที่นี่

ซึ่งดูเหมือนจะแสดงให้เห็นว่าการแทรกขนาดใหญ่ออกมาดำเนินการIDENTITY SEQUENCEมันไม่ได้ทดสอบขนาดแคช 1,000 และผลลัพธ์เหล่านั้นเป็นเพียงการทดสอบเดียว มองที่ขนาดแคช 1,000 โดยเฉพาะด้วยขนาดของแบตช์ต่าง ๆ ฉันได้ผลลัพธ์ดังต่อไปนี้ (ลองแต่ละชุดขนาด 50 ครั้งและรวมผลลัพธ์เป็นด้านล่าง - ทุกครั้งในหน่วยμs)

+------------+-----------+-----------+-----------+-----------+-----------+-----------+
|            |             Sequence              |             Identity              |
| Batch Size |    Min    |    Max    |    Avg    |    Min    |    Max    |    Avg    |
+------------+-----------+-----------+-----------+-----------+-----------+-----------+
| 10         | 2,994     | 7,004     | 4,002     | 3,001     | 7,005     | 4,022     |
| 100        | 3,997     | 5,005     | 4,218     | 4,001     | 5,010     | 4,238     |
| 1,000      | 6,001     | 19,013    | 7,221     | 5,982     | 8,006     | 6,709     |
| 10,000     | 26,999    | 33,022    | 28,645    | 24,015    | 34,022    | 26,114    |
| 100,000    | 189,126   | 293,340   | 205,968   | 165,109   | 234,156   | 173,391   |
| 1,000,000  | 2,208,952 | 2,344,689 | 2,269,297 | 2,058,377 | 2,191,465 | 2,098,552 |
+------------+-----------+-----------+-----------+-----------+-----------+-----------+

สำหรับขนาดแบทช์ที่ใหญ่กว่าIDENTITYรุ่นดูเหมือนเร็วกว่าปกติ

หนังสือการสืบค้น TSQL ยังอธิบายว่าทำไมIDENTITYสามารถมีข้อได้เปรียบด้านประสิทธิภาพมากกว่าลำดับ

IDENTITYเป็นเฉพาะของตารางและSEQUENCEไม่ได้เป็น หากภัยพิบัติเกิดขึ้นกับการแทรกกลางก่อนที่บัฟเฟอร์การบันทึกจะถูกลบทิ้งไม่สำคัญว่าข้อมูลประจำตัวที่กู้คืนนั้นเป็นรหัสก่อนหน้านี้เนื่องจากกระบวนการกู้คืนจะยกเลิกการแทรกดังนั้น SQL Server จึงไม่บังคับให้ล้างบัฟเฟอร์บันทึกในทุก ๆ การเขียนดิสก์ที่เกี่ยวข้องกับแคช อย่างไรก็ตามสำหรับ Sequence สิ่งนี้ถูกบังคับใช้เนื่องจากค่าอาจถูกใช้เพื่อวัตถุประสงค์ใด ๆ - รวมถึงภายนอกฐานข้อมูล ดังนั้นในตัวอย่างข้างต้นที่มีตัวแทรกนับล้านและขนาดแคชเท่ากับ 1,000 นี่คือการบันทึกการลบอีกหนึ่งพัน

สคริปต์ที่จะทำซ้ำ

DECLARE @Results TABLE(
  BatchCounter INT,
  NumRows      INT,
  SequenceTime BIGINT,
  IdTime       BIGINT);

DECLARE @NumRows      INT = 10,
        @BatchCounter INT;

WHILE @NumRows <= 1000000
  BEGIN
      SET @BatchCounter = 0;

      WHILE @BatchCounter <= 50
        BEGIN
            --Do inserts using Sequence
            DECLARE @SequenceTimeStart DATETIME2(7) = SYSUTCDATETIME();

            INSERT INTO dbo.t1_Seq1_cache_1000
                        (c1)
            SELECT N
            FROM   [dbo].[TallyTable] (@NumRows)
            OPTION (RECOMPILE);

            DECLARE @SequenceTimeEnd DATETIME2(7) = SYSUTCDATETIME();
            --Do inserts using IDENTITY
            DECLARE @IdTimeStart DATETIME2(7) = SYSUTCDATETIME();

            INSERT INTO dbo.t1_identity
                        (c1)
            SELECT N
            FROM   [dbo].[TallyTable] (@NumRows)
            OPTION (RECOMPILE);

            DECLARE @IdTimeEnd DATETIME2(7) = SYSUTCDATETIME();

            INSERT INTO @Results
            SELECT @BatchCounter,
                   @NumRows,
                   DATEDIFF(MICROSECOND, @SequenceTimeStart, @SequenceTimeEnd) AS SequenceTime,
                   DATEDIFF(MICROSECOND, @IdTimeStart, @IdTimeEnd)             AS IdTime;

            TRUNCATE TABLE dbo.t1_identity;

            TRUNCATE TABLE dbo.t1_Seq1_cache_1000;

            SET @BatchCounter +=1;
        END

      SET @NumRows *= 10;
  END

SELECT NumRows,
       MIN(SequenceTime) AS MinSequenceTime,
       MAX(SequenceTime) AS MaxSequenceTime,
       AVG(SequenceTime) AS AvgSequenceTime,
       MIN(IdTime)       AS MinIdentityTime,
       MAX(IdTime)       AS MaxIdentityTime,
       AVG(IdTime)       AS AvgIdentityTime
FROM   @Results
GROUP  BY NumRows;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.