คุณอาจไม่อยากได้ยินสิ่งนี้ แต่ทางเลือกที่ดีที่สุดในการเร่งความเร็วSELECT DISTINCTคือการหลีกเลี่ยง DISTINCTการเริ่มต้น ในหลายกรณี (ไม่ใช่ทั้งหมด!) สามารถหลีกเลี่ยงได้ด้วยการออกแบบฐานข้อมูลหรือแบบสอบถามที่ดีขึ้น
บางครั้งGROUP BYเร็วกว่าเพราะใช้เส้นทางรหัสที่แตกต่าง
ในกรณีเฉพาะของคุณดูเหมือนจะไม่สามารถกำจัดDISTINCTได้ แต่คุณสามารถรองรับการสืบค้นด้วยดัชนีเฉพาะถ้าคุณมีการสืบค้นหลายประเภท:
CREATE INDEX foo ON events (project_id, "time", user_id);
การเพิ่มuser_idจะมีประโยชน์ก็ต่อเมื่อคุณสแกนเฉพาะดัชนีนี้เท่านั้น ไปที่ลิงก์เพื่อดูรายละเอียด จะลบBitmap Heap Scanราคาแพงออกจากแผนคิวรีของคุณซึ่งใช้ 90% ของเวลาแบบสอบถาม
EXPLAINผลลัพธ์ของคุณบอกฉันว่าข้อความค้นหาต้องย่อผู้ใช้ 2,491 รายออกจากแถวที่ตรงกันครึ่งล้าน สิ่งนี้จะไม่เร็วอย่างมากไม่ว่าคุณจะทำอะไร แต่ก็สามารถเร็วขึ้นอย่างมาก
หากช่วงเวลาในแบบสอบถามของคุณเหมือนกันเสมอการMATERIALIIZED VIEWพับuser_idแต่ละครั้ง(project_id, <fixed time intervall>)จะไปไกล ไม่มีโอกาสที่จะมีช่วงเวลาที่แตกต่างกัน บางทีคุณอาจพับผู้ใช้อย่างน้อยต่อชั่วโมงหรือบางหน่วยเวลาขั้นต่ำอื่น ๆ และนั่นจะซื้อประสิทธิภาพเพียงพอที่จะรับประกันค่าใช้จ่ายจำนวนมาก
Nitpick:
ส่วนใหญ่เพรดิเคตที่"time"ควรจะเป็น:
AND "time" >= '2015-01-11 8:00:00'
AND "time" < '2015-02-10 8:00:00';
นอกเหนือ:
อย่าใช้timeเป็นตัวระบุ มันเป็นคำสงวนใน SQL มาตรฐานและเป็นประเภทพื้นฐานใน Postgres