REINDEX อันตรายหรือไม่?


17

ฉันพยายามไปCOUNT(*)ที่โต๊ะที่มี 150,000 แถวที่มีคีย์หลัก มันเป็นเครื่องมือประมาณ 5 นาทีดังนั้นฉันจึงคิดว่านี่เป็นปัญหาการจัดทำดัชนี

อ้างถึงคู่มือ PostgreSQL :

REINDEX นั้นคล้ายกับการดร็อปและสร้างดัชนีใหม่ซึ่งเนื้อหาดัชนีจะถูกสร้างใหม่ตั้งแต่เริ่มต้น อย่างไรก็ตามข้อควรพิจารณาในการล็อคค่อนข้างแตกต่างกัน REINDEX ล็อคการเขียน แต่ไม่อ่านตารางหลักของดัชนี นอกจากนี้ยังใช้การล็อกแบบเอกสิทธิ์เฉพาะบุคคลในดัชนีเฉพาะที่กำลังประมวลผลซึ่งจะบล็อกการอ่านที่พยายามใช้ดัชนีนั้น (... ) CREATE INDEX ที่ตามมาล็อคการเขียน แต่ไม่อ่าน เนื่องจากดัชนีไม่อยู่ที่นั่นการอ่านจะไม่พยายามใช้ซึ่งหมายความว่าจะไม่มีการบล็อก แต่การอ่านอาจถูกบังคับให้สแกนตามลำดับราคาแพง

จากประสบการณ์ของคุณคุณสามารถบอกได้:

  • เป็นREINDEXINGอันตรายหรือไม่? มันจะเป็นอันตรายต่อความสอดคล้องของข้อมูลหรือไม่
  • ใช้เวลานานไหม?
  • มันเป็นทางออกที่เป็นไปได้สำหรับสถานการณ์ของฉันหรือไม่

ปรับปรุง:

วิธีแก้ปัญหาที่ใช้งานได้สำหรับเราคือสร้างดัชนีเดียวกันใหม่ด้วยชื่ออื่นแล้วลบดัชนีเก่า

การสร้างดัชนีนั้นรวดเร็วมากและเราได้ลดขนาดดัชนีจาก 650 MB เป็น 8 MB ใช้ a COUNT(*)กับbetweenใช้เวลาเพียง 3 วินาที

คำตอบ:


15

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

การสร้างดัชนีใหม่ไม่ควรใช้เวลามาก แต่โดยทั่วไปแล้วจะเกี่ยวข้องกับการอ่านทั้งตารางเรียงลำดับเขตข้อมูลดัชนีและเขียนดัชนีใหม่ ให้เวลากับCOUNT(*)มันอาจจะใช้เวลาห้านาทีขึ้นไป

ไม่น่าเป็นไปได้ว่านี่เป็นปัญหาการจัดทำดัชนี COUNT(*)ควรใช้การสแกนตารางในกรณีที่ไม่มีการอ่านดัชนี ฉันคาดหวังว่าคุณมีปัญหา IO ของการเรียงลำดับบางอย่าง

ลองใช้COUNT(1)หรือCOUNT(pk_field)อาจใช้ดัชนี

หากคุณกำลังทำงานบนแพลตฟอร์ม Unix หรือ Linux sarคุณอาจต้องการตรวจสอบการทำงานของดิสก์ที่มี คุณอาจมีดิสก์ที่ล้มเหลวซึ่งสามารถลดอัตรา IO ได้อย่างมาก

ตารางที่มีวัตถุขนาดใหญ่ยังสามารถเพิ่ม IO ได้อย่างมากเพื่อสร้างระเบียนสำหรับ COUNT (*)


2
ตาม wiki.postgresql.org COUNT(*)เป็นตัวเลือกที่ดีที่สุด:If you are using count(*), the database is free to use any column to count, which means it can pick the smallest covering index to scan (note that this is why count(*) is much better than count(some_field), as long as you don't care if null values of some_field are counted). Since indexes often fit entirely in memory, this means count(*) is often very fast.
ส้ม 80

1

ฉันไม่แน่ใจในคำตอบที่ดีที่สุดสำหรับคุณ อย่างไรก็ตามกระทู้นี้ดูเหมือนจะเสนอคำแนะนำที่ดี: n http://postgresql.1045698.n5.nabble.com/count-performance-issue-td2067873.html

สิ่งหนึ่งที่ทราบได้คือคุณสามารถติดตั้ง TRIGGER เพื่อรักษาจำนวนแถวในตารางแยกต่างหาก (ถ้า COUNT (*) จะถูกเรียกใช้บ่อยโดยแอปพลิเคชันของคุณ)

คำตอบบางส่วนชี้ให้เห็นว่านี่เป็นอาการของฐานข้อมูลที่ไม่ได้รับการดูดเมื่อไม่นานมานี้ (แนะนำว่า autovacuum ถูกปิดการใช้งานบนเซิร์ฟเวอร์ของคุณหรือสำหรับฐานข้อมูลนั้นโดยเฉพาะ)

ข้อเสนอแนะอื่น ๆ ดูเหมือนว่า:

ANALYZE tablename;
SELECT reltuple FROM pg_class WHERE relname = 'tablename';

และมีคนระบุว่าเป็น A. Kretschmer หมายเหตุ:

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

... สนับสนุนความคิดเห็นของฉันเกี่ยวกับสิทธิ์ระดับแถวเป็นปัญหาด้านประสิทธิภาพ

การค้นหาของฉันยังเปิดขึ้นWikiVS: MySQL กับ PostgreSQL: COUNT (*)

คุณสามารถอ่านผลการค้นหาอื่น ๆ ที่พบโดยใช้Google: ประสิทธิภาพการนับ postgresql (*)

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