เป็นความจริงหรือไม่ที่ระบบ RDBMS นั้นได้รับการปรับให้เหมาะสมสำหรับCOMMIT
การทำงาน? การดำเนินการช้าลง / เร็วเท่าไหร่ROLLBACK
และทำไม
เป็นความจริงหรือไม่ที่ระบบ RDBMS นั้นได้รับการปรับให้เหมาะสมสำหรับCOMMIT
การทำงาน? การดำเนินการช้าลง / เร็วเท่าไหร่ROLLBACK
และทำไม
คำตอบ:
สำหรับ SQL Server คุณสามารถยืนยันว่าการดำเนินการกระทำไม่มีอะไรมากไปกว่าการเขียน LOP_COMMIT_XACT ไปยังล็อกไฟล์และปล่อยการล็อกซึ่งแน่นอนว่าจะเร็วกว่า ROLLBACK ของการดำเนินการทุกธุรกรรมของคุณตั้งแต่ BEGIN TRAN
หากคุณกำลังพิจารณาทุกการกระทำของธุรกรรมไม่ใช่เฉพาะการกระทำฉันยังคงยืนยันว่าคำสั่งของคุณไม่เป็นความจริง หากไม่รวมปัจจัยภายนอกความเร็วของดิสก์บันทึกเมื่อเปรียบเทียบกับความเร็วดิสก์ข้อมูลเป็นไปได้ว่าการย้อนกลับของงานใด ๆ ที่ทำโดยธุรกรรมจะเร็วกว่าการทำงานในครั้งแรก
การย้อนกลับกำลังอ่านไฟล์ตามลำดับของการเปลี่ยนแปลงและนำไปใช้กับหน้าข้อมูลในหน่วยความจำ ต้นฉบับ "งาน" ต้องสร้างแผนการดำเนินการรับหน้าเข้าร่วมแถวเป็นต้น
แก้ไข: มันขึ้นอยู่กับบิต ...
@JackDouglas ชี้ไปที่บทความนี้ซึ่งอธิบายถึงหนึ่งในสถานการณ์ที่การย้อนกลับอาจใช้เวลานานกว่าการดำเนินการดั้งเดิม ตัวอย่างการทำธุรกรรม 14 ชั่วโมงหลีกเลี่ยงการใช้คู่ขนานอย่างหลีกเลี่ยงไม่ได้ซึ่งใช้เวลานานกว่า 48 ชั่วโมงในการย้อนกลับเนื่องจากการย้อนกลับส่วนใหญ่เป็นเธรดเดี่ยว คุณมักจะปั่นป่วนบัฟเฟอร์พูลซ้ำ ๆ ดังนั้นคุณจะไม่ย้อนกลับการเปลี่ยนแปลงในหน้าหน่วยความจำ
ดังนั้นคำตอบก่อนหน้าของฉันจะได้รับการแก้ไข การย้อนกลับช้ากว่าเท่าใด สิ่งอื่น ๆ ทั้งหมดที่พิจารณาสำหรับธุรกรรม OLTP ทั่วไปไม่ใช่ นอกเหนือจากขอบเขตทั่วไปแล้วอาจใช้เวลานานกว่า "เลิกทำ" มากกว่า "ทำ" แต่ (นี่คือ twister ลิ้นที่เป็นไปได้หรือไม่) ทำไมจะขึ้นอยู่กับวิธีการทำ "ทำ"
แก้ไข 2: จากการอภิปรายในความคิดเห็นต่อไปนี้เป็นตัวอย่างที่วางแผนไว้มากเพื่อแสดงให้เห็นว่างานที่ทำเป็นปัจจัยสำคัญในการกำหนดค่าใช้จ่ายสัมพัทธ์ของการกระทำ vs ย้อนกลับเป็นการดำเนินการ
สร้างสองตารางและแพ็คอย่างไม่มีประสิทธิภาพ (พื้นที่ว่างเปล่าต่อหน้า):
SET STATISTICS IO OFF;
SET STATISTICS TIME OFF;
SET NOCOUNT ON;
GO
CREATE TABLE dbo.Foo
(
col1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
, col2 CHAR(4000) NOT NULL DEFAULT REPLICATE('A', 4000)
)
CREATE TABLE dbo.Bar
(
col1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
, col2 CHAR(4000) NOT NULL DEFAULT REPLICATE('A', 4000)
)
GO
INSERT dbo.Foo DEFAULT VALUES
GO 100000
INSERT dbo.Bar DEFAULT VALUES
GO 100000
เรียกใช้คิวรีการอัปเดต "ไม่ดี" การวัดเวลาที่ใช้ในการทำงานและเวลาที่ใช้ในการออกคำสั่ง
DECLARE
@StartTime DATETIME2
, @Rows INT
SET @Rows = 1
CHECKPOINT
DBCC DROPCLEANBUFFERS
BEGIN TRANSACTION
SET @StartTime = SYSDATETIME()
UPDATE
dbo.bar
SET
col2 = REPLICATE('B', 4000)
FROM
dbo.bar b
INNER JOIN
(
SELECT TOP(@Rows)
col1
FROM
dbo.foo
ORDER BY
NEWID()
) f
ON f.col1 = b.col1
OPTION (MAXDOP 1)
SELECT 'Find and update row', DATEDIFF(ms, @StartTime, SYSDATETIME())
SET @StartTime = SYSDATETIME()
COMMIT TRANSACTION
SELECT 'Commit', DATEDIFF(ms, @StartTime, SYSDATETIME())
GO
ทำเช่นเดียวกันอีกครั้ง แต่ออกและวัดการย้อนกลับ
DECLARE
@StartTime DATETIME2
, @Rows INT
SET @Rows = 1
CHECKPOINT
DBCC DROPCLEANBUFFERS
BEGIN TRANSACTION
SET @StartTime = SYSDATETIME()
UPDATE
dbo.bar
SET
col2 = REPLICATE('B', 4000)
FROM
dbo.bar b
INNER JOIN
(
SELECT TOP(@Rows)
col1
FROM
dbo.foo
ORDER BY
NEWID()
) f
ON f.col1 = b.col1
OPTION (MAXDOP 1)
SELECT 'Find and update row', DATEDIFF(ms, @StartTime, SYSDATETIME())
SET @StartTime = SYSDATETIME()
ROLLBACK TRANSACTION
SELECT 'Rollback', DATEDIFF(ms, @StartTime, SYSDATETIME())
GO
ด้วย @ Rows = 1 ฉันมีเหตุผลที่สอดคล้องกัน:
ด้วย @ Rows = 100:
ด้วย @ Rows = 1,000:
กลับไปที่คำถามเดิม หากคุณกำลังวัดเวลาที่ใช้ในการทำงานรวมถึงการกระทำการย้อนกลับนั้นเป็นสิ่งที่ไม่ควรพลาดเพราะงานส่วนใหญ่นั้นใช้เพื่อค้นหาแถวเพื่ออัปเดตไม่ใช่การแก้ไขข้อมูลจริง ๆ หากคุณกำลังมองหาการคอมมิชชันการแยกมันควรจะชัดเจนว่าการคอมมิชชันทำ "งาน" น้อยมาก กระทำคือ "ฉันเสร็จแล้ว"
begin tran
เพียงเพิ่มเคาน์เตอร์การทำธุรกรรม หากฉันเข้าใจคุณ rdbms กำลังทำงานทั้งหมด (รวมแถวสร้างแผนการดำเนินการ ... ) ที่ COMMIT ใช่หรือไม่
สำหรับ Oracle การย้อนกลับอาจใช้เวลานานกว่าเวลาที่ใช้ในการทำการเปลี่ยนแปลงที่จะย้อนกลับ สิ่งนี้มักไม่สำคัญเพราะ
สำหรับ SQL Server ฉันไม่แน่ใจว่าสถานการณ์เหมือนกัน แต่จะมีคนอื่นบอกว่าไม่ใช่ ...
สำหรับ "ทำไม" ฉันจะบอกว่าrollback
ควรจะหายากโดยปกติแล้วก็ต่อเมื่อมีอะไรผิดพลาดและแน่นอนว่าcommit
มีแนวโน้มที่จะเป็นเรื่องธรรมดามากขึ้น - ดังนั้นจึงเหมาะสมที่จะปรับcommit
การย้อนกลับไม่ใช่แค่ "โอ้ไม่เป็นไร" - ในหลาย ๆ กรณีมันต้องเลิกทำในสิ่งที่ทำไปแล้วจริงๆ ไม่มีกฎว่าการดำเนินการย้อนกลับจะช้ากว่าหรือเร็วกว่าการดำเนินการเดิมเสมอถึงแม้ว่าธุรกรรมเดิมจะดำเนินการแบบขนานการย้อนกลับนั้นจะเป็นเธรดเดี่ยว หากคุณกำลังรอฉันแนะนำว่าควรรอต่อไป
ทั้งหมดนี้เปลี่ยนแปลงด้วย SQL Server 2019 และแน่นอนและการกู้คืนฐานข้อมูลแบบเร่งด่วน (ซึ่งเป็นค่าปรับที่เปลี่ยนแปลงได้ด้วยเช่นกันทำให้สามารถย้อนกลับได้ทันทีโดยไม่คำนึงถึงขนาดของข้อมูล)
การทำธุรกรรมไม่ทั้งหมดจะทำให้กิจกรรมการกระทำของพวกเขาทำงานได้ดีกว่าการย้อนกลับ หนึ่งกรณีดังกล่าวคือการดำเนินการลบใน SQL เมื่อการทำธุรกรรมลบแถวแถวเหล่านี้จะถูกทำเครื่องหมายเป็นระเบียนผี เมื่อมีการส่งคอมมิชชันและงานล้างเรคคอร์ดเรคคอร์ดเริ่มต้นจากนั้นบันทึกเหล่านี้จะถูก 'ลบ' เท่านั้น
หากมีการใช้การย้อนกลับแทนจะเป็นการลบเครื่องหมายโกสต์ออกจากบันทึกเหล่านี้ไม่ใช่คำสั่งการแทรกที่เข้มข้น
ไม่ทั้งหมด PostgreSQL ไม่ต้องเสียเวลาในการย้อนกลับมากกว่าที่จะยอมรับเนื่องจากการดำเนินการทั้งสองนั้นเหมือนกันอย่างมีประสิทธิภาพในแง่ของดิสก์ I / O ฉันไม่คิดว่านี่เป็นคำถามของการปรับให้เหมาะสมสำหรับการคอมมิชชันมากเนื่องจากเป็นคำถามของสิ่งที่เคียวรีอื่น ๆ กำลังปรับให้เหมาะสม
คำถามพื้นฐานคือวิธีที่คุณพูดถึงเลย์เอาต์บนดิสก์และสิ่งนี้มีผลกระทบอย่างไรกับคอมมิท vs การย้อนกลับ db ที่สำคัญซึ่งย้อนกลับช้ากว่าการยอมรับมักจะย้ายข้อมูลโดยเฉพาะจากตารางคลัสเตอร์ออกจากโครงสร้างข้อมูลหลักและวางไว้ในเซ็กเมนต์ย้อนกลับเมื่ออัปเดตข้อมูล ซึ่งหมายความว่าการยอมรับคุณเพียงแค่ปล่อยเซ็กเมนต์ย้อนกลับ แต่เพื่อย้อนกลับคุณต้องคัดลอกข้อมูลทั้งหมดกลับ
สำหรับ PostgreSQL ตารางทั้งหมดเป็นตารางฮีพและดัชนีแยกกัน ซึ่งหมายความว่าเมื่อย้อนกลับหรือยืนยันจะไม่มีการจัดเรียงข้อมูลใหม่ สิ่งนี้ทำให้คอมมิชชันและย้อนกลับทั้งสองอย่างรวดเร็ว
อย่างไรก็ตามมันทำให้บางอย่างช้าลงเล็กน้อย ตัวอย่างเช่นการค้นหาคีย์หลักนั้นต้องสำรวจไฟล์ดัชนีและจากนั้นจะต้องกดปุ่มฮีปตาราง (สมมติว่าไม่มีการครอบคลุมดัชนีที่เกี่ยวข้อง) นี่ไม่ใช่เรื่องใหญ่โต แต่มันจะเพิ่มการค้นหาหน้าพิเศษหรืออาจเป็นการค้นหาหน้าแบบสุ่มเล็กน้อย (หากมีการปรับปรุงจำนวนมากเกิดขึ้นในแถวนั้น) เพื่อตรวจสอบข้อมูลและการมองเห็นอื่น ๆ
ความเร็วที่นี่ไม่ใช่คำถามของการปรับให้เหมาะสมใน PostgreSQL สำหรับการเขียนและการอ่าน มันเป็นความไม่เต็มใจที่จะมีสิทธิ์ดำเนินการอ่านบางอย่างเหนือคนอื่น ๆ ดังนั้น PostgreSQL จะทำงานโดยเฉลี่ยประมาณเช่นเดียวกับ db อื่น ๆ มันเป็นเพียงการดำเนินการบางอย่างที่อาจเร็วขึ้นหรือช้าลง
ดังนั้นฉันคิดว่าคำตอบที่แท้จริงคือ db ถูกปรับให้เหมาะสมสำหรับเวิร์กโหลดบางอย่างบนฝั่งอ่านและสิ่งนี้นำไปสู่ความท้าทายในด้านการเขียน โดยปกติแล้วจะมีคำถามอยู่บ่อยครั้งที่คอมมิชชันมักจะไม่ได้รับความนิยมมากกว่าการย้อนกลับ อย่างไรก็ตามสิ่งนี้ขึ้นอยู่กับความหมายของการทำสิ่งใดสิ่งหนึ่ง (การอัปเดตจะแตกต่างจากการลบ)