ลำดับของคอลัมน์ในดัชนีรวมใน PostgreSQL (และลำดับการสืบค้น)


10

ฉันมีตารางที่มี 50K แถว จริงๆแล้วมันเป็นตาราง PostGIS

แบบสอบถามมี 4 ส่วน (บังคับ 1 ข้อ) (3 ตัวเลือก)

  1. กล่องแยก (สี่เหลี่ยมทางภูมิศาสตร์) ที่มีละติจูด 4 เส้น, ยาว (ฉันใช้ st_intersects) [จำเป็น]
  2. ช่วงวันที่ (นาทีสูงสุด) ในฟิลด์วันที่
  3. ประเภทไฟล์ (ชุดของค่าข้อความสูงสุด 8 ค่า) กำลังใช้ IN (..... ) แต่ฉันสามารถสร้างตารางชั่วคราวได้ถ้าต้องการ ฉันเห็นคนจำนวนมากไม่ชอบอิน
  4. ประเทศ (ค่าข้อความ)

ฉันคาดหวังประมาณ 100 - 4,000 แถวที่ส่งคืน

ถ้าฉันสร้างดัชนีผสมบนตารางฉันควรใช้คอลัมน์ใดก่อน เม็ดเล็กละเอียดน่าจะเป็นที่ตั้ง (มีการกระจายข้อมูลไปทั่วโลก) ปัจจุบันฉันมีมันเป็นดัชนีส่วนสำคัญ

ดัชนีอื่น ๆ จะเป็น BTREE

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

ผู้เชี่ยวชาญด้าน PostgreSQL และ PostGIS ทำอะไร (ใครรู้เรื่องภายในของระบบ) พูด?


UPDATE:

ให้ฉันเพิ่มพูนคำถามนี้

  1. ฉันไม่ต้องการให้ใครทำงานที่ฉันควรทำ ฉันเคารพเวลาของคุณมากเกินไป ดังนั้นฉันจะอธิบายการวิเคราะห์ในภายหลัง
  2. ทั้งหมดที่ฉันกำลังมองหาคือตัวชี้และเคล็ดลับและแนวทาง
  3. ฉันอ่านโพสต์เล็ก ๆ น้อย ๆ ที่ยอดเยี่ยมนี้: https://devcenter.heroku.com/articles/postgresql-indexes#managing-and-maintaining-indexesเกี่ยวกับดัชนี
  4. สิ่งที่ฉันทำตามปกติคือสร้างดัชนีแยกต่างหาก 4 ตัว (ภูมิศาสตร์กล่องชื่อประเทศ file_type และวันที่) แต่สิ่งที่ต้องการดูว่าแบบสอบถามแบบผสมจะทำอะไร

บอกฉันหากข้อสันนิษฐานเหล่านี้ผิด (ฉันค่อนข้างใหม่กับความคิดของดัชนีผสม)

  1. คำสั่งซื้อเป็นสิ่งสำคัญ เลือกเป็นดัชนีแรกซึ่งจะตัดแถวลงมากที่สุด (ในกรณีของฉันตำแหน่ง (ภูมิศาสตร์) ซึ่งเป็นรูปหลายเหลี่ยมแบบง่ายหรือหลายรูปหลายเหลี่ยมจะทำได้ดีที่สุด)
  2. บางครั้งการสืบค้นจะข้ามดัชนี แต่ถ้าฉันสร้างแบบสอบถามแบบผสมพร้อมคีย์ (# 1, # 2, # 3, # 4) แม้ว่าผู้ใช้จะสร้างสิ่งที่ถาม # 1, # 3 ผู้วางแผนจะยังคงใช้แบบสอบถามแบบประกอบเดียวเนื่องจากพวกเขาสั่ง ถูกเก็บรักษาไว้
  3. โดยปกติฉันจะสร้างแบบสอบถาม BTREE สามรายการและรายการหนึ่งรายการ (สำหรับประเภทภูมิศาสตร์) PostGIS ไม่สนับสนุนการสร้างสารประกอบหลายประเภทดัชนี ดังนั้นฉันจะต้องใช้ GIST ดัชนีผสม แต่นั่นไม่ควรทำร้ายสิ่งต่าง ๆ
  4. ถ้าฉันจะสร้างสารประกอบเพิ่มเติมหรือดัชนีค่าเดียวนักวางแผนนั้นฉลาดพอที่จะเลือกอันที่ฉลาดที่สุด .....
  5. ชื่อประเทศสามารถมีค่าได้ประมาณ 250 ค่าและเห็นได้ชัดว่ามีการเชื่อมโยงอย่างแน่นหนากับตำแหน่ง (geobox) แต่ถ้าดัชนีที่ดีที่สุดถัดไปสำหรับการลดขนาดแถวคือ file_type ฉันควรใช้ต่อไป ฉันไม่คาดหวังให้ผู้ใช้มักใช้ประเทศหรือวันที่ในชุดแบบสอบถาม
  6. ฉันไม่ต้องกังวลเกี่ยวกับการสร้างดัชนีรวม 4 ปุ่มจะเพิ่มขนาดของข้อมูลดัชนีอย่างมาก คือถ้าดัชนีคีย์เดียวจะเป็น 90% ของการเพิ่มประสิทธิภาพจะไม่เจ็บที่จะเพิ่ม 3 รายการเพิ่มเติมเพื่อให้รวมกัน ในทางกลับกันฉันควรสร้างดัชนีทั้งคู่ ดัชนีภูมิศาสตร์เดียวและดัชนีผสมและให้นักวางแผนเข้าใจว่าสิ่งใดดีที่สุดและจะคำนึงถึงขนาดของตารางดัชนี

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

[เหตุผลที่ฉันยังไม่มีผลลัพธ์อธิบายให้แสดงก็คือฉันต้องสร้างตารางแถว 25K นี้จากตารางแถว 24M ใช้เวลามากกว่าที่ฉันคิด ฉันกำลังรวมกลุ่มสิ่งต่าง ๆ เป็น 1,000 กลุ่มรายการและให้ผู้ใช้คิวรีกับตารางแถว 25K แต่คำถามต่อไปของฉันจะเกี่ยวข้องกับการใช้ผลลัพธ์ของแบบสอบถามนั้นเพื่อไปที่ตารางแถว MASTER 25M แล้วดึงสิ่งต่าง ๆ ออกมาและนั่นเป็นจุดที่ประสิทธิภาพของดัชนีผสมจะเป็นจริง]


แบบสอบถามตัวอย่างด้านล่าง:


SELECT
    public.product_list_meta_mv.cntry_name       AS country,
    public.product_list_meta_mv.product_producer AS producer,
    public.product_list_meta_mv.product_name     AS prod_name,
    public.product_list_meta_mv.product_type     AS ptype,
    public.product_list_meta_mv.product_size     AS size,
    ST_AsGeoJSON(public.product_list_meta_mv.the_geom, 10, 2)          AS outline
FROM
    public.product_list_meta_mv 
WHERE
    public.product_list_meta_mv.cntry_name = 'Poland' 
AND
    ST_Intersects(public.product_list_meta_mv.the_geom,
    st_geogfromtext('SRID=4326;POLYGON((21.23107910156250 51.41601562500000,
                                        18.64379882812500 51.41601562500000,
                                        18.64379882812500 48.69415283203130,
                                        21.23107910156250 48.69415283203130,
                                        21.23107910156250 51.41601562500000))')) 
AND (date >= '1/2/1900 5:00:00 AM' 
 AND date <= '2/26/2014 10:26:44 PM')
AND (public.product_list_meta_mv.product_type in
    ('CIB10','DTED0','DTED1','DTED2','CIB01','CIB05')) ;

อธิบายผลการวิเคราะห์ (ฉันไม่ได้ใส่ดัชนีผสมใด ๆ และจากความเร็วที่ฉันเห็นฉันไม่รู้ว่าต้องการหรือไม่)

"Bitmap Heap Scan on catalog_full cat  (cost=4.33..37.49 rows=1 width=7428) (actual time=1.147..38.051 rows=35 loops=1)"
"  Recheck Cond: ('0103000020E61000000100000005000000000000005838354000000000AEB0494000000000A0A7324000000000AEB0494000000000A0A73240000000006C5D48400000000058383540000000006C5D4840000000005838354000000000AEB04940'::geography && outline)"
"  Filter: (((type)::text = ANY ('{CADRG,CIB10,DTED1,DTED2}'::text[])) AND (_st_distance('0103000020E61000000100000005000000000000005838354000000000AEB0494000000000A0A7324000000000AEB0494000000000A0A73240000000006C5D48400000000058383540000000006C5D4840000000005838354000000000AEB04940'::geography, outline, 0::double precision, false) < 1e-005::double precision))"
"  Rows Removed by Filter: 61"
"  ->  Bitmap Index Scan on catalog_full_outline_idx  (cost=0.00..4.33 rows=8 width=0) (actual time=0.401..0.401 rows=96 loops=1)"
"        Index Cond: ('0103000020E61000000100000005000000000000005838354000000000AEB0494000000000A0A7324000000000AEB0494000000000A0A73240000000006C5D48400000000058383540000000006C5D4840000000005838354000000000AEB04940'::geography && outline)"
"Total runtime: 38.109 ms"

EXPLAIN ANALYZE SELECT pid,product_name,type,country,date,size,cocom,description,egpl_date,ST_AsGeoJSON(outline, 10, 2) AS outline 
FROM portal.catalog_full AS cat 
WHERE ST_Intersects(st_geogfromtext('SRID=4326;POLYGON((21.2200927734375 51.38031005859375, 18.65478515625 51.38031005859375, 18.65478515625 48.7298583984375, 21.2200927734375 48.7298583984375, 21.2200927734375 51.38031005859375))'), cat.outline) 
AND (cat.type in ('CADRG','CIB10','DTED1','DTED2'))

2
โปรดระบุข้อความค้นหาที่แท้จริง
ypercubeᵀᴹ

"3 ตัวเลือก" หมายความว่าแบบสอบถามสามารถมี 8 รูปแบบที่แตกต่างกัน (ขึ้นอยู่กับว่ามีการเปิดใช้งานตัวเลือก 2,3,4 หรือไม่)
ypercubeᵀᴹ

มี 4 และส่วนประกอบที่ WHERE ใน st_intersects จำเป็นต้องมีคนอื่นอาจอยู่ที่นั่นหรือพวกเขาอาจไม่ แต่ฉันต้องการที่จะจัดการกับกรณีที่พวกเขาอยู่ทั้งหมด

2
ฉันโหวตให้โยกย้ายคำถามไปยัง dba.se นี่เป็นข้อความค้นหาที่ซับซ้อนที่มีเงื่อนไขหลายช่วง
ypercubeᵀᴹ

1
แสดงEXPLAIN ANALYZEสำหรับแบบสอบถาม
Craig Ringer

คำตอบ:


4

เป็นส่วนหนึ่งของงานของฉันฉันรักษาฐานข้อมูล PostgreSQL ค่อนข้างใหญ่ (ประมาณ 120GB บนดิสก์หลายตารางหลายล้านแถว) และได้รวบรวมเทคนิคเล็กน้อยเกี่ยวกับวิธีเพิ่มความเร็วการสืบค้น ก่อนแสดงความคิดเห็นเกี่ยวกับสมมติฐานของคุณ:

  1. ใช่ลำดับเป็นสิ่งสำคัญ แต่เป็นเพียงลำดับแรกที่แตกต่างกันจริงส่วนที่เหลือเป็นดัชนีระดับที่สอง
  2. ฉันไม่แน่ใจว่ามันจะใช้ทั้งคู่เสมอฉันเดาว่าผู้วางแผนคิวรีจะใช้อันดับ 1 จากนั้นทำสิ่งที่ฉลาดกับส่วนที่เหลือ
  3. ฉันไม่มีประสบการณ์กับเค้า
  4. ใช่เพิ่มดัชนีทั้งหมดก่อนดูสิ่งที่ใช้บ่อยที่สุดและอะไรให้ประสิทธิภาพดีที่สุด
  5. ฉันอยากจะลองทำทั้งสองอย่างและวัดว่าอะไรดีที่สุด ลองเขียน sql อีกครั้งด้วยแบบสอบถามย่อยที่แตกต่างกันอาจเป็นประเทศและเวลาในหนึ่งเดียวจากนั้นเข้าร่วมกับการสอบถามข้าม ฉันไม่ได้สังเกตเห็นปัญหาประสิทธิภาพการทำงานใด ๆ กับ IN-clauses ตราบใดที่รายการในรายการไม่ยาวพันองค์ประกอบ ฉันเดาว่าการค้นหาที่แตกต่างกันสองสามข้อที่ปรับขึ้นอยู่กับเกณฑ์การป้อนข้อมูลที่มีอยู่จะให้ผลลัพธ์ที่ดีที่สุด
  6. ฉันอยากจะแนะนำให้ทำดัชนี 4 ทิศทาง ลองสร้างมันขึ้นมาจากนั้นตรวจสอบขนาดพวกมันจะใหญ่มาก จากประสบการณ์ของฉันดัชนี 1 คีย์สี่ตัวเกือบเร็วพอ ๆ กับดัชนี 4 ทิศทางเดียว เคล็ดลับที่ใช้งานได้ดีกับข้อความค้นหาบางรายการเป็นดัชนีบางส่วนนั่นคือสิ่งนี้:

    สร้างดัชนีบน table_x (key1, key2, key3) WHERE some_x_column = 'XXXX';

ฉันสร้างนามแฝงในไฟล์. psqlrc ของฉันพร้อมข้อความค้นหาเพื่อช่วยค้นหาดัชนีที่จะเพิ่มหรือลบ อย่าลังเลที่จะดูพวกเขาที่ GitHub: .psql

ฉันใช้: seq_scans และ: bigtables มากแล้ว \ d table_name เพื่อรับรายละเอียดเกี่ยวกับตาราง อย่าลืมรีเซ็ตสถิติหลังจากคุณทำการเปลี่ยนแปลงเสร็จแล้วเลือก pg_stat_reset ();


1
นี่คือเคล็ดลับที่ยอดเยี่ยม ฉันเอาคำแนะนำของคุณแล้วใช้มันเพื่อทำการทดลองบนโต๊ะที่ใหญ่กว่าที่เราเก็บไว้ (43 ล้านแถว) ผลลัพธ์อยู่ที่: dba.stackexchange.com/questions/61084/…
Dr.YSG

1

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

เมื่อฉันเข้าใกล้สิ่งแรกที่ฉันทำคือเรียกใช้คิวรีในรูปแบบที่เรียบง่ายโดยที่ WHERE clause มีเพียงหนึ่งเงื่อนไขเท่านั้นแต่ละอันถูกใช้ภายใต้อธิบายถึงการวิเคราะห์ ดูทั้งแถวโดยประมาณและแถวจริงสำหรับแต่ละแถว


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