ปัญหา
นี่คือกรณีที่คล้ายกันมากกล่าวถึงใน pgsql.general มันเกี่ยวกับข้อ จำกัด ในดัชนี b-tree แต่ทั้งหมดเหมือนกันเพราะดัชนี GIN ใช้ดัชนี b-tree สำหรับคีย์ภายในและดังนั้นจึงทำงานเป็นข้อ จำกัด เดียวกันสำหรับขนาดคีย์ (แทนขนาดรายการใน b-tree ธรรมดา ดัชนี).
ฉันพูดคู่มือเกี่ยวกับการใช้ดัชนี GIN :
ภายในดัชนี GIN ประกอบด้วยดัชนี B-tree ที่สร้างขึ้นเหนือคีย์โดยที่แต่ละคีย์เป็นองค์ประกอบของรายการที่จัดทำดัชนีหนึ่งรายการหรือมากกว่า
ไม่ว่าจะด้วยวิธีใดองค์ประกอบอาร์เรย์อย่างน้อยหนึ่งองค์ประกอบในคอลัมน์ของคุณdata
ใหญ่เกินกว่าที่จะจัดทำดัชนีได้ หากนี่เป็นเพียงค่าประหลาดประหลาดหรืออุบัติเหตุบางประเภทคุณอาจตัดทอนค่าและทำมันได้
สำหรับวัตถุประสงค์ของการสาธิตต่อไปนี้ฉันจะถือว่าเป็นอย่างอื่น: มีค่าข้อความยาวมากมายในอาร์เรย์
ทางออกที่ง่าย
คุณสามารถเปลี่ยนองค์ประกอบในอาร์เรย์ของคุณdata
ด้วยตามค่าแฮ และส่งค่าการค้นหาผ่านฟังก์ชันแฮชเดียวกัน แน่นอนคุณอาจต้องการเก็บต้นฉบับของคุณไว้ที่อื่น ด้วยสิ่งนี้เราเกือบจะมาถึงตัวแปรที่สองของฉัน ...
โซลูชันขั้นสูง
คุณสามารถสร้างตารางการค้นหาสำหรับองค์ประกอบแถวลำดับที่มีserial
คอลัมน์เป็นคีย์หลักตัวแทน (มีผลบังคับใช้ค่าแฮชที่ต่างไปจากเดิมอย่างสิ้นเชิง) ซึ่งน่าสนใจยิ่งกว่าหากค่าองค์ประกอบที่เกี่ยวข้องนั้นไม่ซ้ำกัน:
CREATE TABLE elem (
elem_id serial NOT NULL PRIMARY KEY
, elem text UNIQUE NOT NULL
);
เนื่องจากเราต้องการที่จะมองขึ้นไปelem
เราเพิ่มดัชนี - แต่ดัชนีในการแสดงออกในครั้งนี้มีเพียง10 ตัวอักษรแรกของข้อความยาว ในกรณีส่วนใหญ่ควรจะเพียงพอที่จะ จำกัด การค้นหาให้เหลือเพียงหนึ่งหรือไม่กี่ครั้ง ปรับขนาดให้เหมาะกับการกระจายข้อมูลของคุณ หรือใช้ฟังก์ชันแฮชที่ซับซ้อนยิ่งขึ้น
CREATE INDEX elem_elem_left10_idx ON elem(left(elem,10));
คอลัมน์ของคุณก็จะเป็นประเภทdata
int[]
ฉันเปลี่ยนชื่อโต๊ะเป็นdata
และกำจัดลางร้ายที่varchar(50)
คุณมีในตัวอย่างของคุณ:
CREATE TEMP TABLE data(
data_id serial PRIMARY KEY
, data int[]
);
องค์ประกอบอาร์เรย์ในแต่ละหมายถึงdata
elem.elem_id
ณ จุดนี้คุณอาจพิจารณาที่จะแทนที่คอลัมน์อาเรย์ด้วยตาราง n: m ดังนั้นการทำให้สกีมาของคุณเป็นมาตรฐานและอนุญาตให้ Postgres บังคับใช้ความสมบูรณ์ของการอ้างอิง การจัดทำดัชนีและการจัดการทั่วไปกลายเป็นเรื่องง่าย ...
อย่างไรก็ตามสำหรับเหตุผลด้านประสิทธิภาพint[]
คอลัมน์ร่วมกับดัชนี GIN อาจเหนือกว่า ขนาดพื้นที่เก็บข้อมูลมีขนาดเล็กกว่ามาก ในกรณีนี้เราต้องการดัชนี GIN:
CREATE INDEX data_data_gin_idx ON data USING GIN (data);
ตอนนี้แต่ละที่สำคัญของดัชนี GIN (= องค์ประกอบอาร์เรย์) เป็นinteger
แทน text
longish ดัชนีจะมีขนาดเล็กโดยคำสั่งหลายขนาดการค้นหาจึงจะมากได้เร็วขึ้น
ข้อเสีย: ก่อนที่จะสามารถดำเนินการค้นหาที่คุณต้องมองขึ้นจากตารางelem_id
elem
การใช้ดัชนีการทำงานที่เพิ่งแนะนำของฉันelem_elem_left10_idx
สิ่งนี้ก็จะเร็วขึ้นมาก
คุณสามารถทำได้ทั้งหมดในแบบสอบถามง่ายๆเดียว :
SELECT d.*, e.*
FROM elem e
JOIN data d ON ARRAY[e.elem_id] <@ d.data
WHERE left(e.elem, 10) = left('word1234word', 10) -- match index condition
AND e.elem = 'word1234word'; -- need to recheck, functional index is lossy
คุณอาจสนใจส่วนขยายintarray
ที่ให้ตัวดำเนินการเพิ่มเติมและคลาสตัวดำเนินการ
data
มีรายชื่อของแท็กเช่นนี้แสดงให้เห็นในบล็อกโพสต์ที่เกี่ยวข้องโดยสกอตต์สไนเดอ ? หากเป็นกรณีนี้ฉันอาจมีทางออกที่ดีกว่าสำหรับคุณ