ฉันมีตารางประมาณ 100 ล้านแถวที่ฉันจะคัดลอกเพื่อแก้ไขเพิ่มดัชนี ฉันไม่ได้กังวลกับเวลาที่ต้องใช้ในการสร้างตารางใหม่ แต่ดัชนีที่สร้างขึ้นจะมีประสิทธิภาพมากขึ้นหรือไม่หากฉันแก้ไขตารางก่อนที่จะแทรกข้อมูลใด ๆ หรือแทรกข้อมูลก่อนแล้วจึงเพิ่มดัชนี
ฉันมีตารางประมาณ 100 ล้านแถวที่ฉันจะคัดลอกเพื่อแก้ไขเพิ่มดัชนี ฉันไม่ได้กังวลกับเวลาที่ต้องใช้ในการสร้างตารางใหม่ แต่ดัชนีที่สร้างขึ้นจะมีประสิทธิภาพมากขึ้นหรือไม่หากฉันแก้ไขตารางก่อนที่จะแทรกข้อมูลใด ๆ หรือแทรกข้อมูลก่อนแล้วจึงเพิ่มดัชนี
คำตอบ:
การสร้างดัชนีหลังจากการแทรกข้อมูลเป็นวิธีที่มีประสิทธิภาพมากขึ้น (มักจะแนะนำให้ดร็อปดัชนีก่อนนำเข้าแบทช์และหลังจากนำเข้าแล้วสร้างใหม่)
ตัวอย่าง Syntetic (PostgreSQL 9.1 เครื่องพัฒนาช้าหนึ่งล้านแถว):
CREATE TABLE test1(id serial, x integer);
INSERT INTO test1(id, x) SELECT x.id, x.id*100 FROM generate_series(1,1000000) AS x(id);
-- Time: 7816.561 ms
CREATE INDEX test1_x ON test1 (x);
-- Time: 4183.614 ms
แทรกแล้วสร้างดัชนี - ประมาณ 12 วินาที
CREATE TABLE test2(id serial, x integer);
CREATE INDEX test2_x ON test2 (x);
-- Time: 2.315 ms
INSERT INTO test2(id, x) SELECT x.id, x.id*100 FROM generate_series(1,1000000) AS x(id);
-- Time: 25399.460 ms
สร้างดัชนีแล้วแทรก - ประมาณ 25.5 วินาที (ช้ากว่าสองเท่า)
ควรสร้างดัชนีหลังจากเพิ่มแถวแล้ว ไม่เพียง แต่จะเร็วขึ้นเท่านั้น แต่การปรับสมดุลของต้นไม้ก็น่าจะดีขึ้นด้วย
การแก้ไข "การปรับสมดุล" อาจไม่ใช่ตัวเลือกที่ดีที่สุดสำหรับคำศัพท์ที่นี่ ในกรณีของ b-tree มีความสมดุลตามนิยาม แต่ไม่ได้หมายความว่า b-tree มีเค้าโครงที่เหมาะสมที่สุด การกระจายโหนดลูกภายในพาเรนต์อาจไม่สม่ำเสมอ (ทำให้เสียค่าใช้จ่ายมากขึ้นในการอัปเดตในอนาคต) และความลึกของต้นไม้อาจลึกเกินความจำเป็นหากการปรับสมดุลไม่ได้ดำเนินการอย่างรอบคอบในระหว่างการอัปเดต หากดัชนีถูกสร้างขึ้นหลังจากเพิ่มแถวก็จะมีการกระจายที่ดีกว่า นอกจากนี้หน้าดัชนีบนดิสก์อาจมีการกระจายตัวน้อยลงหลังจากสร้างดัชนีแล้ว ข้อมูลเพิ่มเติมเล็กน้อยที่นี่
สิ่งนี้ไม่สำคัญกับปัญหานี้เนื่องจาก:
O(n*log(N))
นานขึ้น ( n
แถวที่เพิ่มเข้ามา) เนื่องจากเวลา gerating ของต้นไม้คือO(N*log(N))
ถ้าคุณแยกสิ่งนี้ออกเป็นข้อมูลเก่าและข้อมูลใหม่คุณจะได้รับO((X+n)*log(N))
สิ่งนี้สามารถแปลงเป็นได้ง่าย ๆO(X*log(N) + n*log(N))
และในรูปแบบนี้คุณจะเห็นสิ่งที่คุณจะรอเพิ่มเติมn
แถวใหม่) คุณจะได้รับเวลาเพิ่มเติมที่O(log(N))
จำเป็นในการแทรกโครงสร้างของต้นไม้อีกต่อไปหลังจากเพิ่มองค์ประกอบใหม่เข้าไป (คอลัมน์ดัชนีจากแถวใหม่เนื่องจากมีดัชนีอยู่แล้วและมีการเพิ่มแถวใหม่ดังนั้นดัชนีจะต้องสร้างใหม่ให้สมดุล โครงสร้างค่าใช้จ่ายนี้O(log(P))
ซึ่งP
เป็นพลังงานดัชนี[องค์ประกอบในดัชนี] ) คุณมีn
แถวใหม่แล้วในที่สุดคุณn * O(log(N))
ก็O(n*log(N))
สรุปเวลาเพิ่มเติมแล้วดัชนีที่สร้างขึ้นหลังจากนั้นเร็วกว่ามากในกรณีส่วนใหญ่ ตรงประเด็น: 20 ล้านแถวที่มีข้อความเต็มใน varchar (255) - (ชื่อธุรกิจ) ดัชนีในขณะที่นำเข้าแถว - จับคู่กับการใช้เวลาสูงสุด 20 วินาทีในกรณีที่เลวร้ายที่สุด วางดัชนีและสร้างใหม่ - จับคู่กับการใช้เวลาน้อยกว่า 1 วินาทีทุกครั้ง
ฉันไม่แน่ใจว่ามันจะมีความสำคัญต่อประสิทธิภาพของดัชนีจริงๆเนื่องจากในทั้งสองกรณีคุณกำลังแทรกข้อมูลใหม่ลงในดัชนี เซิร์ฟเวอร์จะไม่รู้ว่าดัชนีที่ไม่สมดุลจะเป็นอย่างไรจนกว่าจะสร้างโดยพื้นฐานแล้ว เห็นได้ชัดว่าความเร็วอย่างชาญฉลาดทำการแทรกโดยไม่มีดัชนี