ฉันมีแบบสอบถามที่ค่อนข้างง่ายในตารางที่มีแถว 1.5M:
SELECT mtid FROM publication
WHERE mtid IN (9762715) OR last_modifier=21321
LIMIT 5000;
EXPLAIN ANALYZE
เอาท์พุท:
Limit (cost=8.84..12.86 rows=1 width=8) (actual time=0.985..0.986 rows=1 loops=1) -> Bitmap Heap Scan on publication (cost=8.84..12.86 rows=1 width=8) (actual time=0.984..0.985 rows=1 loops=1) Recheck Cond: ((mtid = 9762715) OR (last_modifier = 21321)) -> BitmapOr (cost=8.84..8.84 rows=1 width=0) (actual time=0.971..0.971 rows=0 loops=1) -> Bitmap Index Scan on publication_pkey (cost=0.00..4.42 rows=1 width=0) (actual time=0.295..0.295 rows=1 loops=1) Index Cond: (mtid = 9762715) -> Bitmap Index Scan on publication_last_modifier_btree (cost=0.00..4.42 rows=1 width=0) (actual time=0.674..0.674 rows=0 loops=1) Index Cond: (last_modifier = 21321) Total runtime: 1.027 ms
จนถึงตอนนี้ดีเร็วและใช้ดัชนีที่มีอยู่
ตอนนี้ถ้าฉันปรับเปลี่ยนแบบสอบถามเพียงเล็กน้อยผลลัพธ์จะเป็น:
SELECT mtid FROM publication
WHERE mtid IN (SELECT 9762715) OR last_modifier=21321
LIMIT 5000;
EXPLAIN ANALYZE
การส่งออกเป็น:
Limit (cost=0.01..2347.74 rows=5000 width=8) (actual time=2735.891..2841.398 rows=1 loops=1) -> Seq Scan on publication (cost=0.01..349652.84 rows=744661 width=8) (actual time=2735.888..2841.393 rows=1 loops=1) Filter: ((hashed SubPlan 1) OR (last_modifier = 21321)) SubPlan 1 -> Result (cost=0.00..0.01 rows=1 width=0) (actual time=0.001..0.001 rows=1 loops=1) Total runtime: 2841.442 ms
ไม่เร็วนักและใช้การสแกน seq ...
แน่นอนแบบสอบถามเดิมที่ดำเนินการโดยการประยุกต์ใช้เป็นบิตที่ซับซ้อนมากขึ้นและได้ช้าและแน่นอนเดิมจำศีลสร้างไม่ได้(SELECT 9762715)
แต่ช้าจะมีแม้กระทั่งการที่(SELECT 9762715)
! แบบสอบถามถูกสร้างขึ้นโดยไฮเบอร์เนตดังนั้นจึงค่อนข้างท้าทายที่จะเปลี่ยนแปลงและบางคุณสมบัติไม่พร้อมใช้งาน (เช่นUNION
ไม่พร้อมใช้งานซึ่งจะเร็ว)
คำถาม
- เหตุใดจึงไม่สามารถใช้ดัชนีในกรณีที่สองได้ พวกเขาจะใช้อย่างไร?
- ฉันสามารถปรับปรุงประสิทธิภาพการสืบค้นด้วยวิธีอื่นได้หรือไม่
ความคิดเพิ่มเติม
ดูเหมือนว่าเราสามารถใช้เคสแรกด้วยการเลือก SELECT จากนั้นใส่รายการผลลัพธ์ลงในคิวรี แม้จะมีหมายเลข 5000 ในรายการ IN () มันเร็วกว่าโซลูชันที่สองถึงสี่เท่า อย่างไรก็ตามดูเหมือนว่าผิด (เช่นอาจเร็วขึ้น 100 เท่า :)) มันไม่สามารถเข้าใจได้อย่างสมบูรณ์ว่าเหตุใดตัววางแผนคิวรีจึงใช้วิธีการที่แตกต่างไปจากเดิมอย่างสิ้นเชิงสำหรับเคียวรีสองรายการนี้ดังนั้นฉันจึงต้องการหาวิธีแก้ปัญหาที่ดีกว่าสำหรับปัญหานี้
(SELECT 9762715)
จริงๆมันขึ้นอยู่กับการค้นหาที่ซ่อนอยู่หลังที่เกิดขึ้นจริง
(SELECT 9762715)
สำหรับคำถามไฮเบอร์เนต: สามารถทำได้ แต่ต้องมีการเขียนโค้ดอย่างจริงจังเนื่องจากเรามีเกณฑ์การจำศีลไฮเบอร์เนตที่ผู้ใช้กำหนดซึ่งได้รับการแปลแบบทันที ดังนั้นโดยพื้นฐานแล้วเราจะปรับเปลี่ยนโหมดไฮเบอร์เนตซึ่งเป็นงานที่ใหญ่และมีผลข้างเคียงมากมาย
JOIN
แทนที่จะIN ()
? นอกจากนี้ยังได้publication
รับการวิเคราะห์เมื่อเร็ว ๆ นี้?