วิธีการจัดทำดัชนีของแบบสอบถามด้วยฟิลด์ WHERE IS NULL คืออะไร


14

ฉันมีตารางที่มีจำนวนมากแทรกการตั้งค่าหนึ่งของฟิลด์ ( uploaded_at) NULLเพื่อ จากนั้นภารกิจตามระยะเวลาจะเลือกสิ่งอันดับทั้งหมดWHERE uploaded_at IS NULLประมวลผลและอัปเดตตั้งค่าuploaded_atเป็นวันที่ปัจจุบัน

ฉันควรจัดทำดัชนีตารางอย่างไร

ฉันเข้าใจว่าฉันควรใช้ดัชนีบางส่วนเช่น:

CREATE INDEX foo ON table (uploaded_at) WHERE uploaded_at IS NULL

หรือว่าอย่างนั้น ฉันบิตสับสน NULLแต่ถ้ามันเป็นสิ่งที่ถูกต้องเพื่อดัชนีในเขตข้อมูลที่อยู่เสมอ หรือถ้ามันถูกต้องที่จะใช้ดัชนี b-tree Hash ดูเหมือนเป็นความคิดที่ดีกว่า แต่ล้าสมัยและไม่ได้รับการจำลองแบบผ่านการสตรีมการจำลองแบบ hot-standby คำแนะนำใด ๆ ที่จะได้รับการชื่นชมอย่างมาก

ฉันได้ทดลองเล็กน้อยด้วยดัชนีต่อไปนี้:

"foo_part" btree (uploaded_at) WHERE uploaded_at IS NULL
"foo_part_id" btree (id) WHERE uploaded_at IS NULL

และตัววางแผนแบบสอบถามดูเหมือนว่าจะเลือกfoo_partดัชนีเสมอ explain analyseยังให้ผลลัพธ์ที่ดีขึ้นเล็กน้อยสำหรับfoo_partดัชนี:

Index Scan using foo_part on t1  (cost=0.28..297.25 rows=4433 width=16) (actual time=0.025..3.649 rows=4351 loops=1)
   Index Cond: (uploaded_at IS NULL)
 Total runtime: 4.060 ms

VS

Bitmap Heap Scan on t1  (cost=79.15..6722.83 rows=4433 width=16) (actual time=1.032..4.717 rows=4351 loops=1)
   Recheck Cond: (uploaded_at IS NULL)
   ->  Bitmap Index Scan on foo_part_id  (cost=0.00..78.04 rows=4433 width=0) (actual time=0.649..0.649 rows=4351 loops=1)
 Total runtime: 5.131 ms

คำตอบ:


10

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

CREATE INDEX foo ON table bar (some_col) WHERE uploaded_at IS NULL;

หากคุณไม่มีกรณีการใช้งานสำหรับคอลัมน์อื่น ๆ ก็ยังคงดีที่สุดที่จะยึดติดกับไร้ประโยชน์uploaded_atดังนั้นจึงไม่แนะนำค่าบำรุงรักษาเพิ่มเติมสำหรับดัชนีและข้อ จำกัด สำหรับการปรับปรุง HOT มากกว่า:

หรือใช้ค่าคงที่เป็นนิพจน์ดัชนีถ้าคุณไม่มีประโยชน์สำหรับคอลัมน์ดัชนีอื่น ๆ ชอบ:

CREATE INDEX baz ON table bar ((TRUE)) WHERE uploaded_at IS NULL;

จำเป็นต้องใส่วงเล็บ นอกจากนี้ยังช่วยให้ดัชนีมีขนาดต่ำสุด แต่ในขณะที่คอลัมน์ดัชนีจะไม่ใหญ่กว่า 8 ไบต์ (ซึ่งเป็นกรณีtimestamp) แต่ก็ยังมีขนาดต่ำสุดอยู่ดี ที่เกี่ยวข้อง:


อาจเป็นidฟิลด์อนุกรมได้หรือไม่
Kirill Zaitsev

1
@teferi: a serialดีเท่า ๆ จุดคือไม่ว่าจะมีจริงแบบสอบถามเพื่อใช้ประโยชน์จากมัน
Erwin Brandstetter
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.