ข้อผิดพลาดขนาดดัชนีสูงสุดของแถว


12

มีขอบเขตบนสำหรับarrayคอลัมน์หรือไม่?

ฉันได้รับข้อผิดพลาดนี้เมื่อแทรกเข้าไปในฟิลด์อาร์เรย์ -

PG::Error: ERROR:  index row size 3480 exceeds maximum 2712 for index "ix_data"

นี่คือคำนิยามตารางของฉัน -

create table test_array(id varchar(50), data text[]);

ALTER TABLE test_array ADD PRIMARY KEY (id);

CREATE INDEX ix_data ON test_array USING GIN (data);

ฉันต้องการดัชนีในฟิลด์อาร์เรย์เนื่องจากฉันกำลังทำการค้นหาบางอย่างกับมัน


มันอาจจะเป็นไปได้ว่าdataมีรายชื่อของแท็กเช่นนี้แสดงให้เห็นในบล็อกโพสต์ที่เกี่ยวข้องโดยสกอตต์สไนเดอ ? หากเป็นกรณีนี้ฉันอาจมีทางออกที่ดีกว่าสำหรับคุณ
Erwin Brandstetter

user310525 ฉันต้องการที่จะแนะนำที่สองของ Erwin ว่าสิ่งนี้จะดีกว่าใน dba.se หากคุณยินดีที่จะสร้างบัญชีที่นั่นและตั้งค่าสถานะเพื่อให้ผู้ดูแลทำการโยกย้าย
แจ็คบอกว่าลอง topanswers.xyz

คำตอบ:


14

ปัญหา

นี่คือกรณีที่คล้ายกันมากกล่าวถึงใน 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แทน textlongish ดัชนีจะมีขนาดเล็กโดยคำสั่งหลายขนาดการค้นหาจึงจะมากได้เร็วขึ้น

ข้อเสีย: ก่อนที่จะสามารถดำเนินการค้นหาที่คุณต้องมองขึ้นจากตาราง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ที่ให้ตัวดำเนินการเพิ่มเติมและคลาสตัวดำเนินการ

สาธิตการใช้งานได้อย่างสมบูรณ์บน sqlfiddle


2

ข้อผิดพลาดเกิดขึ้นกับดัชนีix_dataไม่ใช่text[]ฟิลด์ ขนาดสูงสุดของแถวในประเภทดัชนีนั้น ๆ นั้นถูก จำกัด ไว้ที่2712ไบต์ หากคุณทำดัชนีของคุณลดลงและลองใส่ใหม่อีกครั้งมันก็น่าจะเหมาะกับคุณ หากคุณต้องการทำดัชนีฟิลด์ที่มีขนาดใหญ่ขึ้นคุณอาจต้องการดูคุณสมบัติการจัดทำดัชนีข้อความแบบเต็มของ postgres


2

ฉันได้รับสิ่งนี้ในคอลัมน์ภูมิศาสตร์ของ PostGIS เป็นเพราะฉันตั้งใจสร้างดัชนีไม่ถูกต้อง คุณควรรวมพารามิเตอร์ USING GIST เมื่อสร้างดัชนีดังกล่าว


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