VACUUM ส่งคืนพื้นที่ดิสก์ไปยังระบบปฏิบัติการ


21

VACUUMมักจะไม่คืนพื้นที่ว่างในดิสก์ไปยังระบบปฏิบัติการยกเว้นในบางกรณีพิเศษ
จากเอกสาร:

รูปแบบมาตรฐานของการVACUUMลบเวอร์ชันของแถวที่ตายแล้วในตารางและดัชนีและทำเครื่องหมายพื้นที่ที่มีอยู่สำหรับการใช้ซ้ำในอนาคต อย่างไรก็ตามมันจะไม่คืนพื้นที่ไปยังระบบปฏิบัติการยกเว้นในกรณีพิเศษที่หนึ่งหรือหลายหน้าท้ายตารางกลายเป็นอิสระทั้งหมดและสามารถล็อคตารางแบบเอกสิทธิ์ได้อย่างง่ายดาย ในทางตรงกันข้ามVACUUM FULLบีบอัดตารางอย่างแข็งขันด้วยการเขียนไฟล์ตารางเวอร์ชันใหม่ที่สมบูรณ์โดยไม่มีพื้นที่ว่าง สิ่งนี้จะลดขนาดของตาราง แต่จะใช้เวลานาน นอกจากนี้ยังต้องการพื้นที่ดิสก์เพิ่มเติมสำหรับสำเนาใหม่ของตารางจนกว่าการดำเนินการจะเสร็จสมบูรณ์

คำถามคือจะทำอย่างไรเมื่อฐานข้อมูลนี้one or more pages at the end of a table become entirely freeสำเร็จ? สิ่งนี้สามารถทำได้ผ่านVACUUM FULLแต่ฉันมีพื้นที่ไม่เพียงพอที่จะใช้มัน มีความเป็นไปได้อื่นอีกไหม?

คำตอบ:


29

VACUUM FULLที่จะกลับพื้นที่ในการปฏิบัติการการใช้ VACUUM FULL ANALYZEในขณะที่ถูกที่มันฉันคิดว่าคุณเรียก ฉันพูดคู่มือ :

FULL

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

ฉันเน้นตัวหนา

CLUSTER ประสบความสำเร็จเช่นกันในฐานะที่เป็นหลักประกัน

ธรรมดาVACUUMไม่บรรลุเป้าหมายของคุณ ( "หนึ่งหน้าขึ้นไปที่ท้ายตารางโดยสิ้นเชิง" ) มันไม่ได้เรียงลำดับของแถวใหม่และจะตัดเฉพาะหน้าที่ว่างเปล่าจากจุดสิ้นสุดทางกายภาพของไฟล์เมื่อมีโอกาสเกิดขึ้น - เช่นคำพูดของคุณจากคู่มือแนะนำ

คุณสามารถรับหน้าว่างในตอนท้ายของฟิสิคัลไฟล์เมื่อคุณINSERTแบทช์ของแถวและDELETEพวกมันก่อนที่จะมีการเพิ่ม tuples อื่น ๆ หรืออาจเกิดขึ้นโดยบังเอิญหากมีการลบแถวออกมากพอ

นอกจากนี้ยังมีการตั้งค่าพิเศษที่อาจป้องกันไม่ให้VACUUM FULLเรียกคืนพื้นที่ ดู:

เตรียมหน้าว่างที่ท้ายตารางเพื่อทำการทดสอบ

คอลัมน์ระบบctidแสดงถึงตำแหน่งทางกายภาพของแถว คุณต้องเข้าใจคอลัมน์นั้น:

เราสามารถทำงานกับมันและเตรียมตารางโดยการลบแถวทั้งหมดออกจากหน้าสุดท้าย:

DELETE FROM tbl t
USING (
   SELECT (split_part(ctid::text, ',', 1) || ',0)')::tid     AS min_tid
        , (split_part(ctid::text, ',', 1) || ',65535)')::tid AS max_tid
   FROM   tbl
   ORDER  BY ctid DESC
   LIMIT  1
   ) d
WHERE t.ctid BETWEEN d.min_tid AND d.max_tid;

ตอนนี้หน้าสุดท้ายว่างเปล่า สิ่งนี้จะละเว้นการเขียนพร้อมกัน ไม่ว่าคุณจะเป็นคนเดียวที่เขียนลงในตารางนั้นหรือคุณจำเป็นต้องล็อคการเขียนเพื่อหลีกเลี่ยงสัญญาณรบกวน

แบบสอบถามได้รับการปรับให้เหมาะสมเพื่อระบุแถวที่มีคุณสมบัติได้อย่างรวดเร็ว จำนวนที่สองของ a tidคือดัชนี tuple ที่เก็บไว้เป็น unsigned int2และ65535เป็นค่าสูงสุดสำหรับประเภทนั้น ( 2^16 - 1) ดังนั้นนั่นจึงเป็นขอบเขตที่ปลอดภัย

SQL Fiddle (การใช้ตารางอย่างง่ายจากกรณีอื่น)

เครื่องมือในการวัดขนาดแถว / ตาราง:

ดิสก์เต็ม

คุณต้องมีพื้นที่เลื้อยบนดิสก์สำหรับการดำเนินการใด ๆ เหล่านี้ นอกจากนี้ยังมีเครื่องมือที่ชุมชนpg_repackแทน/VACUUM FULL CLUSTERมันหลีกเลี่ยงการล็อคพิเศษ แต่ต้องการพื้นที่ว่างในการทำงานด้วยเช่นกัน คู่มือ:

ต้องการพื้นที่ว่างในดิสก์ใหญ่เป็นสองเท่าของตารางเป้าหมายและดัชนี

เป็นทางเลือกสุดท้ายคุณสามารถเรียกใช้รอบการถ่ายโอนข้อมูล / เรียกคืน ซึ่งจะลบ Bloat ทั้งหมดออกจากตารางและดัชนีด้วย คำถามที่เกี่ยวข้องอย่างใกล้ชิด:

คำตอบตรงนั้นค่อนข้างรุนแรง หากสถานการณ์ของคุณอนุญาต (ไม่มีคีย์ต่างประเทศหรือการอ้างอิงอื่นป้องกันการลบแถว) และไม่มีการเข้าถึงตารางพร้อมกัน) คุณสามารถ:

ดัมพ์ตารางไปยังดิสก์ที่เชื่อมต่อจากคอมพิวเตอร์ระยะไกลที่มีพื้นที่ดิสก์มากมาย ( -aสำหรับ--data-only):

จากรีโมตเชลล์ข้อมูลดัมพ์ตาราง:

pg_dump -h <host_name> -p <port> -t mytbl -a mydb > db_mytbl.sql

ในเซสชัน pg TRUNCATEตาราง:

-- drop all indexes and constraints here for best performance
TRUNCATE mytbl;

จากเปลือกระยะไกลเรียกคืนไปยังตารางเดียวกัน:

psql -h <host_name> -p <port> mydb -f db_mytbl.sql
-- recreate all indexes and constraints here

ตอนนี้ไม่มีแถวหรือ bloat ที่ตายแล้ว

แต่บางทีคุณอาจมีที่ง่ายกว่า?

  • คุณสามารถเพิ่มเนื้อที่ว่างในดิสก์ได้โดยการลบ (ย้าย) ไฟล์ที่ไม่เกี่ยวข้องหรือไม่?

  • คุณสามารถVACUUM FULLเล็กลงตารางแรกทีละคนดังนั้นเนื้อที่ว่างบนดิสก์เพียงพอหรือไม่

  • คุณสามารถเรียกใช้REINDEX TABLEหรือREINDEX INDEXเพิ่มพื้นที่ดิสก์จากดัชนีป่องได้หรือไม่

สิ่งที่คุณทำไม่เป็นผื่น หากมีข้อสงสัยให้สำรองข้อมูลทุกอย่างไปยังสถานที่ปลอดภัยก่อน


เออร์วินขอโทษฉันลืมที่จะพูดถึงว่าฉันมีพื้นที่ไม่พอสำหรับการดูดสุญญากาศ อัปเดตคำถาม
ผิดทุกอย่าง

@Zapadlo: ฉันเพิ่มบทสำหรับคำถามที่อัปเดตแล้ว
Erwin Brandstetter

ขอบคุณสำหรับคำตอบที่ครอบคลุม อันที่จริงฉันคิดว่าฉันสามารถวางแถวที่ตายแล้วในตอนท้ายของหน้า db โดยการปรับปรุงปลอมเช่นupdate table set field_1 = field_1แต่การดูดตารางนั้นหลังจากการดำเนินการนั้นล้มเหลวในการคืนพื้นที่ว่างความคิดใด ๆ
ผิดทุกอย่าง

@Zapadlo: ความคิดที่ฉันมีอยู่ในคำตอบแล้ว :) ฉันไม่รู้เครื่องมือที่สามารถเรียงลำดับ tuples ที่ตายแล้วได้โดยไม่ต้องมีพื้นที่กระดิกมากบนดิสก์ (ไม่ได้หมายความว่าไม่มีใครออก)
Erwin Brandstetter

พวกเขาบอกว่าเครื่องมือนี้ทำเคล็ดลับ แต่ยังไม่ได้ลองเลย: code.google.com/p/pgtoolkit/source/browse/trunk/bin/…
ผิดเกี่ยวกับทุกอย่าง
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.