วิธีสร้างดัชนีเพื่อเพิ่มความเร็วการสืบค้น LIKE รวมในนิพจน์


20

ฉันอาจจะถามคำถามผิดในชื่อเรื่อง นี่คือข้อเท็จจริง:

กลุ่มบริการลูกค้าของฉันร้องเรียนเกี่ยวกับเวลาตอบสนองที่ช้าเมื่อทำการค้นหาลูกค้าในอินเทอร์เฟซการจัดการของเว็บไซต์ Django ของเรา

เรากำลังใช้ Postgres 8.4.6 ฉันเริ่มบันทึกการสืบค้นที่ช้าและค้นพบผู้ร้ายนี้:

SELECT COUNT(*) FROM "auth_user" WHERE UPPER("auth_user"."email"::text) LIKE UPPER(E'%deyk%')

การค้นหานี้ใช้เวลานานกว่า 32 วินาทีในการเรียกใช้ นี่คือแผนแบบสอบถามที่จัดทำโดยอธิบาย:

QUERY PLAN
Aggregate  (cost=205171.71..205171.72 rows=1 width=0)
  ->  Seq Scan on auth_user  (cost=0.00..205166.46 rows=2096 width=0)
        Filter: (upper((email)::text) ~~ '%DEYK%'::text)

เนื่องจากนี่เป็นแบบสอบถามที่สร้างขึ้นโดย Django ORM จาก Django QuerySet ที่สร้างโดยแอปพลิเคชัน Django Admin ฉันจึงไม่สามารถควบคุมแบบสอบถามได้ ดัชนีดูเหมือนว่าโซลูชันเชิงตรรกะ ฉันพยายามสร้างดัชนีเพื่อเร่งความเร็ว แต่ก็ไม่ได้สร้างความแตกต่าง:

CREATE INDEX auth_user_email_upper ON auth_user USING btree (upper(email::text))

ผมทำอะไรผิดหรือเปล่า? ฉันจะเพิ่มความเร็วข้อความค้นหานี้ได้อย่างไร

คำตอบ:


21

ไม่มีการสนับสนุนดัชนีคือLIKE/ ILIKEในPostgreSQL 8.4 - ยกเว้นคำค้นหาทอดสมอซ้าย

ตั้งแต่PostgreSQL 9.1โมดูลเพิ่มเติมpg_trgmจัดเตรียมคลาสตัวดำเนินการสำหรับดัชนี Trigram ของ GIN และ GiST ที่สนับสนุนLIKE/ ILIKEหรือนิพจน์ทั่วไป (ตัวดำเนินการ~และเพื่อน) ติดตั้งหนึ่งครั้งต่อฐานข้อมูล:

CREATE EXTENSION pg_trgm;

ตัวอย่างดัชนี GIN:

CREATE INDEX tbl_col_gin_trgm_idx ON tbl USING gin (col gin_trgm_ops);

ที่เกี่ยวข้อง:


2
นี่เป็นคำตอบที่ถูกต้องจริงๆ
vonPetrushev

9

ดัชนีนั้นจะไม่ช่วยได้เนื่องจาก '%' ที่จุดเริ่มต้นของการจับคู่ของคุณดัชนี BTREE สามารถจับคู่คำนำหน้าเท่านั้นและสัญลักษณ์ตัวแทนที่จุดเริ่มต้นของการค้นหาของคุณหมายความว่าไม่มีคำนำหน้าคงที่ที่จะมองหา

นั่นเป็นสาเหตุที่ทำให้การสแกนตารางและจับคู่ทุกระเบียนในทางกลับกันกับสตริงข้อความค้นหา

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

http://www.postgresql.org/docs/8.4/static/textsearch-intro.html

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


นั่นคือสิ่งที่ฉันกลัว มีดัชนีอีกอย่างที่จะช่วยได้ไหม ดังที่ฉันพูดฉันมีข้อ จำกัด เล็กน้อยในความสามารถของฉันที่จะส่งผลกระทบต่อคิวรีเอง
David Eyk

สิ่งสำคัญที่สุด%คือคุณลักษณะที่จำเป็น: ฝ่ายบริการลูกค้าจำเป็นต้องใช้เพื่อค้นหาบัญชีลูกค้าโดยเฉพาะอย่างยิ่งเมื่อมีการพิมพ์ที่อยู่อีเมล
David Eyk

หลังจากการวิจัยเล็กน้อยเกี่ยวกับ LIKE และการจัดทำดัชนีข้อความแบบเต็มและฉันเริ่มเห็นประเด็นของคุณแล้ว
David Eyk

สำหรับตอนนี้ฉันได้พบวิธีที่จะปราบปรามสัญลักษณ์ตัวแทนชั้นนำ มันจะเปิดออกคุณสามารถใช้ดัชนีด้วยเช่นถ้าคุณสร้างดัชนีที่มีความเหมาะสมระดับผู้ประกอบการ เอกสารอยู่ที่นี่: postgresql.org/docs/8.4/static/indexes-opclass.html
David Eyk

ตรวจสอบ db ของคุณสำหรับ bloat ด้วย หากคุณมีจำนวนมากในตารางนั้นมันจะใช้เวลานานในการสแกน หากคุณมีเวลาหยุดทำงานเพียงจัดกลุ่มมันบนคีย์หลักและดูว่ามันทำงานได้เร็วขึ้นหรือไม่ หากคุณต้องการที่จะตรวจสอบการบวมคุณสามารถเรียกใช้การวิเคราะห์แล้วเรียกใช้แบบสอบถามที่นี่: wiki.postgresql.org/wiki/Show_database_bloat สำหรับค่าที่แม่นยำยิ่งขึ้นให้ดูที่ด้านล่างของหน้านั้น
Scott Marlowe
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.