เหตุใด DELETE จึงมีผลกระทบต่อประสิทธิภาพอย่างมาก


20

ในตอนท้ายคือสคริปต์ทดสอบสำหรับเปรียบเทียบประสิทธิภาพระหว่างตัวแปร @table และตาราง #temp ฉันคิดว่าฉันตั้งค่าไว้อย่างถูกต้อง - การกำหนดเวลาการทำงานนั้นเกิดขึ้นนอกคำสั่ง DELETE / TRUNCATE ผลลัพธ์ที่ฉันได้รับมีดังนี้ (คูณเป็นมิลลิวินาที)

@Table Variable  #Temp (delete)  #Temp (truncate)
---------------  --------------  ----------------
5723             5180            5506
15636            14746           7800
14506            14300           5583
14030            15460           5386
16706            16186           5360

เพียงเพื่อให้แน่ใจว่าฉันมีสติสิ่งนี้แสดงให้เห็นว่า CURRENT_TIMESTAMP (aka GetDate()) ถูกนำมาใช้ในเวลาของคำสั่งไม่ใช่ของแบตช์ดังนั้นจึงไม่มีการโต้ตอบระหว่าง TRUNCATE / DELETE กับSET @StartTime = CURRENT_TIMESTAMPคำสั่ง

select current_timestamp
waitfor delay '00:00:04'
select current_timestamp

-----------------------
2012-10-21 11:29:20.290

-----------------------
2012-10-21 11:29:24.290

มันค่อนข้างสอดคล้องในการข้ามระหว่างการวิ่งครั้งแรกและการวิ่งครั้งต่อไปเมื่อใช้ DELETE เพื่อล้างตาราง สิ่งที่ฉันขาดหายไปในความเข้าใจของฉันลบ ? ฉันได้ทำซ้ำหลายครั้งเปลี่ยนคำสั่งขนาด tempdb เพื่อไม่ให้เติบโต ฯลฯ

CREATE TABLE #values (
  id int identity primary key, -- will be clustered
  name varchar(100) null,
  number int null,
  type char(3) not null,
  low int null,
  high int null,
  status smallint not null
);
GO
SET NOCOUNT ON;

DECLARE @values TABLE (
  id int identity primary key clustered,
  name varchar(100) null,
  number int null,
  type char(3) not null,
  low int null,
  high int null,
  status smallint not null
);
DECLARE  @ExecutionTime  TABLE(      Duration bigINT    ) 
DECLARE  @StartTime DATETIME,  @i INT = 1; 
WHILE (@i <= 5) 
  BEGIN 
    DELETE @values;
    DBCC freeproccache With NO_InfoMSGS;
    DBCC DROPCLEANBUFFERS With NO_InfoMSGS;
    SET @StartTime = CURRENT_TIMESTAMP -- alternate getdate() 
    /****************** measured process ***********************/ 

    INSERT @values SELECT a.* FROM master..spt_values a join master..spt_values b on b.type='P' and b.number < 1000;

    /**************** end measured process *********************/ 
    INSERT @ExecutionTime 
    SELECT DurationInMilliseconds = datediff(ms,@StartTime,CURRENT_TIMESTAMP) 
    SET @i +=  1 
  END -- WHILE 

SELECT DurationInMilliseconds = Duration FROM   @ExecutionTime 
GO 

-- Temporary table
DECLARE  @ExecutionTime  TABLE(      Duration bigINT    ) 
DECLARE  @StartTime DATETIME,  @i INT = 1; 
WHILE (@i <= 5) 
  BEGIN 
    delete #values;
    -- TRUNCATE TABLE #values;
    DBCC freeproccache With NO_InfoMSGS;
    DBCC DROPCLEANBUFFERS With NO_InfoMSGS;
    SET @StartTime = CURRENT_TIMESTAMP -- alternate getdate() 
    /****************** measured process ***********************/ 

    INSERT #values SELECT a.* FROM master..spt_values a join master..spt_values b on b.type='P' and b.number < 1000;

    /**************** end measured process *********************/ 
    INSERT @ExecutionTime 
    SELECT DurationInMilliseconds = datediff(ms,@StartTime,CURRENT_TIMESTAMP) 
    SET @i +=  1 
  END -- WHILE 

SELECT DurationInMilliseconds = Duration FROM   @ExecutionTime 
GO

DROP TABLE  #values 
SET NOCOUNT OFF;

คำตอบ:


20

ความแตกต่างนี้ดูเหมือนว่าจะนำไปใช้เมื่อวัตถุเป็นต้นไม้ B + เท่านั้น เมื่อลบprimary keyตัวแปรบนตารางดังนั้นมันจึงเป็นฮีพฉันได้ผลลัพธ์ดังต่อไปนี้

2560
2120
2080
2130
2140

แต่ด้วย PK ฉันพบรูปแบบที่คล้ายกันในการทดสอบของฉันเช่นกันกับผลลัพธ์ทั่วไปด้านล่าง

+--------+--------+---------+-------------------+
| @table | #table | ##table | [permanent_table] |
+--------+--------+---------+-------------------+
|   2670 |   2683 |    9603 |              9703 |
|   6823 |   6840 |    9723 |              9790 |
|   6813 |   6816 |    9626 |              9703 |
|   6883 |   6816 |    9600 |              9716 |
|   6840 |   6856 |    9610 |              9673 |
+--------+--------+---------+-------------------+

ทฤษฎีของฉันคือมีการเพิ่มประสิทธิภาพบางอย่างเมื่อทำการแทรกจำนวนมากกับต้นไม้ B + ท้องถิ่นที่ใช้เฉพาะเมื่อมันไม่ได้มีการจัดสรรหน้าใด ๆ

ฉันยึดสิ่งนี้จากข้อสังเกตต่อไปนี้

  1. เมื่อรันโค้ดทดสอบเวอร์ชันต่างๆฉันเห็นรูปแบบ@table_variablesและ#tempตารางนี้เท่านั้น ไม่ใช่ตารางถาวรในtempdbหรือ##ตาราง

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

  3. TRUNCATEยกเลิกการจัดสรรทุกหน้าจากตาราง DELETEจะไม่ทำให้หน้าสุดท้ายในตารางถูกจัดสรรคืน

  4. การใช้ตัวสร้างโปรไฟล์ VS 2012 แสดงให้เห็นว่าในกรณีที่เร็วกว่า SQL Server จะใช้พา ธ ของรหัสอื่น 36% ของเวลาที่ใช้ไปsqlmin.dll!RowsetBulk::InsertRowกับ 61% ของเวลาที่ใช้ในsqlmin.dll!RowsetNewSS::InsertRowกรณีที่ช้ากว่า

วิ่ง

SELECT * 
FROM sys.dm_db_index_physical_stats(2,OBJECT_ID('tempdb..#values'),1,NULL, 'DETAILED')

หลังจากการลบส่งกลับ

+-------------+------------+--------------+--------------------+
| index_level | page_count | record_count | ghost_record_count |
+-------------+------------+--------------+--------------------+
|           0 |          1 |            0 |                  1 |
|           1 |          1 |            1 |                  0 |
|           2 |          1 |            1 |                  0 |
+-------------+------------+--------------+--------------------+

ผมพบว่ามันเป็นไปได้ที่จะลดความแตกต่างเวลาบ้างโดยการเปิดใช้งานสถานะการติดตาม 610

นี่คือผลของการลดการปริมาณของการเข้าสู่ระบบอย่างมีนัยสำคัญสำหรับแทรกตามมา (ลดลงจาก 350 ล้านบาทเป็น 103 ล้านบาทในขณะที่มันไม่ล็อกแต่ละค่าแถวแทรก) แต่ตอนนี้มีเพียงการปรับปรุงเล็ก ๆ น้อย ๆ ในการกำหนดเวลาสำหรับ 2 และต่อมา@table, #tableกรณี และช่องว่างยังคงอยู่ ค่าสถานะการสืบค้นกลับปรับปรุงประสิทธิภาพโดยทั่วไปของการแทรกไปยังตารางสองชนิดอื่นอย่างมีนัยสำคัญ

+--------+--------+---------+-------------------+
| @table | #table | ##table | [permanent_table] |
+--------+--------+---------+-------------------+
|   2663 |   2670 |    5403 |              5426 |
|   5390 |   5396 |    5410 |              5403 |
|   5373 |   5390 |    5410 |              5403 |
|   5393 |   5410 |    5406 |              5433 |
|   5386 |   5396 |    5390 |              5420 |
+--------+--------+---------+-------------------+

จากการดูในบันทึกการทำธุรกรรมฉันสังเกตเห็นว่าการแทรกครั้งแรกกับตารางชั่วคราวในท้องถิ่นที่ว่างเปล่าดูเหมือนจะถูกบันทึกน้อยที่สุด (ที่ 96 MB)

เม็ดมีดที่เร็วขึ้นเหล่านี้มีเพียง657ธุรกรรม ( LOP_BEGIN_XACT/ LOP_COMMIT_XACTคู่) ที่เปรียบเทียบได้มากกว่า10,000ในกรณีที่ช้ากว่า โดยเฉพาะอย่างยิ่งLOP_FORMAT_PAGEการดำเนินงานดูเหมือนจะลดลงมาก กรณีที่ช้ากว่ามีรายการบันทึกธุรกรรมสำหรับสิ่งนี้สำหรับแต่ละหน้าในตาราง (ประมาณ10,270) เปรียบเทียบกับเฉพาะ4รายการดังกล่าวในกรณีที่รวดเร็ว

บันทึกที่ใช้ในทั้งสามกรณีมีดังต่อไปนี้ (ฉันได้ลบบันทึกการใช้งานสำหรับการอัปเดตไปยังตารางฐานของระบบเพื่อลดจำนวนข้อความ แต่ยังรวมอยู่ในผลรวมทั้งหมด)

การบันทึกการแทรกครั้งแรกกับ@table_var(96.5 MB)

+-----------------------+----------+----------------------------------------------+---------------+---------+
|       Operation       | Context  |                AllocUnitName                 | Size in Bytes |   Cnt   |
+-----------------------+----------+----------------------------------------------+---------------+---------+
| LOP_BEGIN_XACT        | LCX_NULL | NULL                                         |         83876 |     658 |
| LOP_COMMIT_XACT       | LCX_NULL | NULL                                         |         34164 |     657 |
| LOP_CREATE_ALLOCCHAIN | LCX_NULL | NULL                                         |           120 |       3 |
| LOP_FORMAT_PAGE       | LCX_HEAP | dbo.#531856C7                                |            84 |       1 |
| LOP_FORMAT_PAGE       | LCX_IAM  | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |            84 |       1 |
| LOP_FORMAT_PAGE       | LCX_IAM  | dbo.#531856C7                                |            84 |       1 |
| LOP_FORMAT_PAGE       | LCX_IAM  | Unknown Alloc Unit                           |            84 |       1 |
| LOP_HOBT_DDL          | LCX_NULL | NULL                                         |           216 |       6 |
| LOP_HOBT_DELTA        | LCX_NULL | NULL                                         |           320 |       5 |
| LOP_IDENT_NEWVAL      | LCX_NULL | NULL                                         |     100240000 | 2506000 |
| LOP_INSERT_ROWS       | LCX_HEAP | dbo.#531856C7                                |            72 |       1 |
| LOP_MODIFY_ROW        | LCX_IAM  | dbo.#531856C7                                |            88 |       1 |
| LOP_MODIFY_ROW        | LCX_PFS  | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |        158592 |    1848 |
| LOP_MODIFY_ROW        | LCX_PFS  | dbo.#531856C7                                |            80 |       1 |
| LOP_MODIFY_ROW        | LCX_PFS  | Unknown Alloc Unit                           |        216016 |    2455 |
| LOP_SET_BITS          | LCX_GAM  | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |         84360 |    1406 |
| LOP_SET_BITS          | LCX_GAM  | Unknown Alloc Unit                           |        147120 |    2452 |
| LOP_SET_BITS          | LCX_IAM  | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |         84360 |    1406 |
| LOP_SET_BITS          | LCX_IAM  | Unknown Alloc Unit                           |        147120 |    2452 |
| Total                 | NULL     | NULL                                         |     101209792 | 2519475 |
+-----------------------+----------+----------------------------------------------+---------------+---------+

การบันทึกแทรกที่ตามมา TF 610 ปิด (350 MB)

+-----------------------+--------------------+----------------------------------------------+---------------+---------+
|       Operation       |      Context       |                AllocUnitName                 | Size in Bytes |   Cnt   |
+-----------------------+--------------------+----------------------------------------------+---------------+---------+
| LOP_BEGIN_CKPT        | LCX_NULL           | NULL                                         |            96 |       1 |
| LOP_BEGIN_XACT        | LCX_NULL           | NULL                                         |       1520696 |   12521 |
| LOP_COMMIT_XACT       | LCX_NULL           | NULL                                         |        651040 |   12520 |
| LOP_CREATE_ALLOCCHAIN | LCX_NULL           | NULL                                         |            40 |       1 |
| LOP_DELETE_SPLIT      | LCX_INDEX_INTERIOR | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |          2160 |      36 |
| LOP_END_CKPT          | LCX_NULL           | NULL                                         |           136 |       1 |
| LOP_FORMAT_PAGE       | LCX_HEAP           | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |        859236 |   10229 |
| LOP_FORMAT_PAGE       | LCX_IAM            | Unknown Alloc Unit                           |            84 |       1 |
| LOP_FORMAT_PAGE       | LCX_INDEX_INTERIOR | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |          3108 |      37 |
| LOP_HOBT_DDL          | LCX_NULL           | NULL                                         |           648 |      18 |
| LOP_HOBT_DELTA        | LCX_NULL           | NULL                                         |        657088 |   10267 |
| LOP_IDENT_NEWVAL      | LCX_NULL           | NULL                                         |     100239960 | 2505999 |
| LOP_INSERT_ROWS       | LCX_CLUSTERED      | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |     258628000 | 2506000 |
| LOP_INSERT_ROWS       | LCX_HEAP           | dbo.#531856C7                                |            72 |       1 |
| LOP_INSERT_ROWS       | LCX_INDEX_INTERIOR | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |       1042776 |   10302 |
| LOP_MODIFY_HEADER     | LCX_HEAP           | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |        859236 |   10229 |
| LOP_MODIFY_HEADER     | LCX_INDEX_INTERIOR | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |          3192 |      38 |
| LOP_MODIFY_ROW        | LCX_IAM            | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |           704 |       8 |
| LOP_MODIFY_ROW        | LCX_PFS            | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |        934264 |   11550 |
| LOP_MODIFY_ROW        | LCX_PFS            | Unknown Alloc Unit                           |        783984 |    8909 |
| LOP_SET_BITS          | LCX_GAM            | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |         76980 |    1283 |
| LOP_SET_BITS          | LCX_GAM            | Unknown Alloc Unit                           |        534480 |    8908 |
| LOP_SET_BITS          | LCX_IAM            | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |         76980 |    1283 |
| LOP_SET_BITS          | LCX_IAM            | Unknown Alloc Unit                           |        534480 |    8908 |
| LOP_SHRINK_NOOP       | LCX_NULL           | NULL                                         |            32 |       1 |
| LOP_XACT_CKPT         | LCX_NULL           | NULL                                         |            92 |       1 |
| Total                 | NULL               | NULL                                         |     367438748 | 5119297 |
+-----------------------+--------------------+----------------------------------------------+---------------+---------+

การบันทึกแทรกที่ตามมา TF 610 บน (103 MB)

+-------------------------+-------------------------+----------------------------------------------+---------------+---------+
|        Operation        |         Context         |                AllocUnitName                 | Size in Bytes |   Cnt   |
+-------------------------+-------------------------+----------------------------------------------+---------------+---------+
| LOP_BEGIN_CKPT          | LCX_NULL                | NULL                                         |           192 |       2 |
| LOP_BEGIN_XACT          | LCX_NULL                | NULL                                         |       1339796 |   11099 |
| LOP_BULK_EXT_ALLOCATION | LCX_NULL                | NULL                                         |         20616 |     162 |
| LOP_COMMIT_XACT         | LCX_NULL                | NULL                                         |        577096 |   11098 |
| LOP_CREATE_ALLOCCHAIN   | LCX_NULL                | NULL                                         |            40 |       1 |
| LOP_DELETE_SPLIT        | LCX_INDEX_INTERIOR      | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |          2160 |      36 |
| LOP_END_CKPT            | LCX_NULL                | NULL                                         |           272 |       2 |
| LOP_FORMAT_PAGE         | LCX_BULK_OPERATION_PAGE | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |        863520 |   10280 |
| LOP_FORMAT_PAGE         | LCX_IAM                 | Unknown Alloc Unit                           |            84 |       1 |
| LOP_FORMAT_PAGE         | LCX_INDEX_INTERIOR      | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |          3108 |      37 |
| LOP_HOBT_DELTA          | LCX_NULL                | NULL                                         |        666496 |   10414 |
| LOP_IDENT_NEWVAL        | LCX_NULL                | NULL                                         |     100239960 | 2505999 |
| LOP_INSERT_ROWS         | LCX_CLUSTERED           | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |         23544 |     218 |
| LOP_INSERT_ROWS         | LCX_HEAP                | dbo.#719CDDE7                                |            72 |       1 |
| LOP_INSERT_ROWS         | LCX_INDEX_INTERIOR      | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |       1042776 |   10302 |
| LOP_MODIFY_HEADER       | LCX_BULK_OPERATION_PAGE | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |        780216 |   10266 |
| LOP_MODIFY_HEADER       | LCX_HEAP                | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |       1718472 |   20458 |
| LOP_MODIFY_HEADER       | LCX_INDEX_INTERIOR      | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |          3192 |      38 |
| LOP_MODIFY_ROW          | LCX_IAM                 | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |           704 |       8 |
| LOP_MODIFY_ROW          | LCX_PFS                 | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |        114832 |    1307 |
| LOP_MODIFY_ROW          | LCX_PFS                 | Unknown Alloc Unit                           |        231696 |    2633 |
| LOP_RANGE_INSERT        | LCX_NULL                | NULL                                         |            48 |       1 |
| LOP_SET_BITS            | LCX_GAM                 | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |         77100 |    1285 |
| LOP_SET_BITS            | LCX_GAM                 | Unknown Alloc Unit                           |        157920 |    2632 |
| LOP_SET_BITS            | LCX_IAM                 | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |         77100 |    1285 |
| LOP_SET_BITS            | LCX_IAM                 | Unknown Alloc Unit                           |        157920 |    2632 |
| LOP_XACT_CKPT           | LCX_NULL                | NULL                                         |            92 |       1 |
| Total                   | NULL                    | NULL                                         |     108102960 | 2602218 |
+-------------------------+-------------------------+----------------------------------------------+---------------+---------+

ขอบคุณสำหรับการยืนยันรายละเอียด ดังนั้นคำถามยังคงถูกถามทำไม DELETE ถึงไม่กลับตารางให้ว่างเปล่าอย่างแท้จริงโดยใช้คำของคุณ นอกจากนี้สิ่งนี้จะโต้แย้งสำหรับการใช้ตาราง #temp หากมีการใช้ clear / populate ในการประมวลผลแบบแบตช์
孔夫子

1
@RichardTheKiwi - ผลประโยชน์ที่TRUNCATEมากกว่าDELETEโดยตัวของมันเองก็เป็นสิ่งที่ถกเถียงกันอยู่ ฉันมักจะพิจารณาตัวแปรตารางสำหรับแถวจำนวนมากด้วย
Martin Smith

นี้จะฟังดูขี้เกียจ แต่จะไม่ทำซ้ำ 1 ถึง 10-record (ตัวแปร) แทรก 1,000 ครั้งในชุดแสดงอาการเดียวกัน? การใช้แถวจำนวนมากเป็นเพียงการทำให้รุนแรงขึ้นเท่านั้นและให้มาตราส่วนเพื่อดูความแตกต่างได้ดียิ่งขึ้น ส่วนสำคัญของคำถามคือการพิสูจน์วิธีใดวิธีหนึ่งที่ #temp ตารางจะดีขึ้นเมื่อเรารู้ว่าความแตกต่างคืออะไร
孔夫子

ทฤษฏีของฉันคือว่ามันคือการจัดสรร10,000+หน้าเว็บที่เกิดขึ้นในวิธีการที่เหมาะสมที่สุดและดูเหมือนว่าจะหลีกเลี่ยงบางค่าใช้จ่ายต่อหน้า สำหรับเม็ดมีดขนาดเล็กฉันคาดหวังว่าความแตกต่างดังกล่าวจะมีนัยสำคัญน้อยกว่า
Martin Smith

@RichardTheKiwi - ขอบคุณ! อาจมีมากกว่าที่จะพูดเกี่ยวกับเรื่องนี้ ฉันจะลองอัปเกรดเป็นเวอร์ชั่นเดียวกันกับ SQL Kiwi และดูว่าฉันยังเห็นเส้นทางรหัสที่แตกต่างกันหรือไม่ ถ้าเป็นเช่นนั้นบางทีมันอาจจะขึ้นอยู่กับฮาร์ดแวร์ว่ามันทำให้ความแตกต่าง (การทดสอบของฉันได้รับในพีซีของฉันกับข้อมูลทั้งหมดและเข้าสู่ระบบไฟล์บน SSD เดียวกัน)
มาร์ตินสมิ ธ

0

การสังเกตและการเก็งกำไร . .

ในบางระบบ CURRENT_TIMESTAMP ถูกกำหนดให้เป็นเวลาที่เริ่มต้นธุรกรรมปัจจุบัน การค้นหาอย่างรวดเร็วไม่ปรากฏเอกสารที่ชัดเจนว่า CURRENT_TIMESTAMP ทำงานอย่างไรบน SQL Server แต่โหมดเริ่มต้นของ SQL Server คือการทำธุรกรรมอัตโนมัติและไม่มีการทำธุรกรรมเริ่มต้นที่นี่ดังนั้นมันควรจะเป็นเวลาทันทีก่อนที่คำสั่ง INSERT (คำสั่ง DELETE ควรกระทำโดยอัตโนมัติและวิธีการทำงานของ CURRENT_TIMESTAMP บน SQL Server ไม่ควรมีอะไรเกี่ยวข้องกับคำสั่ง DELETE เมื่อคุณใช้ธุรกรรมที่ได้รับมอบหมายโดยอัตโนมัติ)

ในการวนซ้ำครั้งแรกคำสั่ง DELETE จะไม่มีการทำงานจริงและไม่มีแถวใด ๆ ที่จะเข้าสู่ระบบ บางทีเครื่องมือเพิ่มประสิทธิภาพอาจรู้เช่นนั้นและนั่นเป็นการลดเวลาสำหรับการทำซ้ำครั้งแรก (การรวมกันของแถวที่จะลบและไม่มีแถวที่จะเข้าสู่ระบบ)

คุณสามารถทดสอบ (ฉันคิดว่า) โดยการแทรกก่อนที่จะลบ


วันนี้ฉันจะหยุดตอบคำถาม หรืออะไรก็ตามที่ฉันกำลังทำอยู่เมื่อฉันพิมพ์สิ่งต่าง ๆ ลงในกล่องนั้น
Mike Sherrill 'Cat Recall'

คำตอบนี้ควรจะถูกลบออกเป็นล้าสมัยสัมผัสและรบกวน?
孔夫子
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.