Apakah ada batas atas untuk array
kolom?
Saya mendapatkan kesalahan ini saat memasukkan ke dalam bidang array -
PG::Error: ERROR: index row size 3480 exceeds maximum 2712 for index "ix_data"
Inilah definisi tabel saya -
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);
Saya perlu indeks pada bidang array, karena saya sedang melakukan beberapa pencarian di atasnya.
data
berisi daftar tag seperti ditunjukkan dalam posting blog terkait ini oleh Scott Snyder ? Jika itu masalahnya, saya mungkin punya solusi yang lebih baik untuk Anda.Jawaban:
Masalah
Berikut adalah kasus yang sangat mirip yang dibahas di pgsql.general . Ini tentang batasan dalam indeks b-tree, tapi itu semua sama karena indeks GIN menggunakan indeks b-tree untuk kunci secara internal dan oleh karena itu mengalami batasan yang sama untuk ukuran kunci (bukan ukuran item dalam b-tree polos indeks).
Saya mengutip manual tentang implementasi indeks GIN :
Either way, setidaknya satu elemen array di kolom Anda
data
terlalu besar untuk diindeks. Jika ini hanya nilai aneh tunggal atau semacam kecelakaan, Anda mungkin dapat memotong nilainya dan dilakukan dengan itu.Untuk keperluan demo berikut, saya akan menganggap sebaliknya: banyak nilai teks panjang dalam array.
Solusi sederhana
Anda bisa mengganti elemen dalam array Anda
data
dengan nilai hash yang sesuai . Dan mengirim nilai pencarian melalui fungsi hash yang sama. Tentu saja, Anda mungkin ingin menyimpan dokumen asli Anda di suatu tempat. Dengan itu, kami hampir tiba di varian kedua saya ...Solusi canggih
Anda bisa membuat tabel pencarian untuk elemen array dengan
serial
kolom sebagai pengganti kunci primer (secara efektif jenis nilai hash radikal) - yang lebih menarik jika nilai elemen yang terlibat tidak unik:Karena kita ingin mencari
elem
, kita menambahkan indeks - tapi sebuah indeks pada ekspresi saat ini, dengan hanya 10 karakter pertama dari teks yang panjang. Itu seharusnya cukup dalam kebanyakan kasus untuk mempersempit pencarian ke satu atau beberapa hits. Sesuaikan ukuran dengan distribusi data Anda. Atau gunakan fungsi hash yang lebih canggih.Kolom Anda
data
kemudian akan bertipeint[]
. Saya mengganti nama tabeldata
dan menyingkirkan yang tidak menyenangkan yangvarchar(50)
Anda miliki dalam contoh Anda:Setiap elemen array
data
mengacu pada aelem.elem_id
. Pada titik ini, Anda dapat mempertimbangkan untuk mengganti kolom array dengan tabel n: m, sehingga menormalkan skema Anda dan memungkinkan Postgres untuk menegakkan integritas referensial. Pengindeksan dan penanganan umum menjadi lebih mudah ...Namun, untuk alasan kinerja,
int[]
kolom dalam kombinasi dengan indeks GIN mungkin lebih unggul. Ukuran penyimpanan jauh lebih kecil. Dalam hal ini kita membutuhkan indeks GIN:Sekarang, setiap kunci indeks GIN (= elemen array) adalah
integer
bukan gondrongtext
. Indeks akan lebih kecil dengan beberapa urutan besarnya, pencarian akan lebih cepat.The downside: sebelum Anda benar-benar dapat melakukan pencarian, Anda harus melihat
elem_id
dari tabelelem
. Menggunakan indeks fungsional saya yang baru diperkenalkanelem_elem_left10_idx
, ini juga akan jauh lebih cepat.Anda dapat melakukan semuanya dalam satu permintaan sederhana :
Anda mungkin tertarik pada ekstensi
intarray
, yang memasok operator tambahan dan kelas operator.Demo langsung yang berfungsi penuh di sqlfiddle.
sumber
Kesalahannya adalah dengan indeks
ix_data
, bukantext[]
bidang. Ukuran maksimum untuk satu baris dalam tipe indeks tertentu terbatas pada2712
byte. Jika Anda menjatuhkan indeks dan mencoba memasukkan lagi, itu akan bekerja untuk Anda. Jika Anda perlu mengindeks bidang yang lebih besar, Anda mungkin ingin melihat fitur pengindeksan teks lengkap postgres.sumber
Saya mendapatkan ini di kolom geografi PostGIS. Itu karena saya tidak sengaja membuat indeks salah. Anda harus memasukkan parameter MENGGUNAKAN GIST saat membuat indeks tersebut.
sumber