Saya tidak terlalu baik dengan DB, jadi mohon bersabar.
Saya mencoba untuk menempatkan data JSON yang sangat panjang ke tabel, tabel ini dibuat oleh Django framework.
Saya menggunakan Postgres di Heroku. Jadi, ketika saya mencoba memasukkan data, saya mendapatkan kesalahan berikut:
File "/app/.heroku/python/lib/python3.6/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
psycopg2.OperationalError: index row size 3496 exceeds maximum 2712 for index "editor_contentmodel_content_2192f49c_uniq"
HINT: Values larger than 1/3 of a buffer page cannot be indexed.
Consider a function index of an MD5 hash of the value, or use full text indexing.
DB dan tabel saya terlihat seperti ini:
gollahalli-me-django-test::DATABASE=> \dt
List of relations
Schema | Name | Type | Owner
--------+----------------------------+-------+----------------
public | auth_group | table | ffnyjettujyfck
public | auth_group_permissions | table | ffnyjettujyfck
public | auth_permission | table | ffnyjettujyfck
public | auth_user | table | ffnyjettujyfck
public | auth_user_groups | table | ffnyjettujyfck
public | auth_user_user_permissions | table | ffnyjettujyfck
public | django_admin_log | table | ffnyjettujyfck
public | django_content_type | table | ffnyjettujyfck
public | django_migrations | table | ffnyjettujyfck
public | django_session | table | ffnyjettujyfck
public | editor_contentmodel | table | ffnyjettujyfck
(11 rows)
gollahalli-me-django-test::DATABASE=> \d+ editor_contentmodel
Table "public.editor_contentmodel"
Column | Type | Modifiers | Storage | Stats target | Description
-----------+--------------------------+-----------+----------+--------------+-------------
ref_id | character varying(120) | not null | extended | |
content | text | not null | extended | |
timestamp | timestamp with time zone | not null | plain | |
Indexes:
"editor_contentmodel_pkey" PRIMARY KEY, btree (ref_id)
"editor_contentmodel_content_2192f49c_uniq" UNIQUE CONSTRAINT, btree (content, ref_id)
"editor_contentmodel_ref_id_8f74b4f3_like" btree (ref_id varchar_pattern_ops)
Sepertinya saya harus berubah "editor_contentmodel_content_2192f49c_uniq" UNIQUE CONSTRAINT, btree (content, ref_id)
untuk mengambilmd5(content)
Adakah yang bisa membantu saya dengan ini? Saya tidak tahu bagaimana melakukannya.
Memperbarui:
JSON
konten - https://gist.github.com/akshaybabloo/0b3dc1fb4d964b10d09ccd6884fe3a40
Pembaruan 2:
Saya telah membuat UNIQUE
indeks berikut , apa yang harus saya hapus di ini?
gollahalli_me_django=> create unique index on editor_contentmodel (ref_id, md5(content::text));
CREATE INDEX
gollahalli_me_django=> \d editor_contentmodel;
Table "public.editor_contentmodel"
Column | Type | Modifiers
-----------+--------------------------+-----------
ref_id | character varying(120) | not null
content | jsonb | not null
timestamp | timestamp with time zone | not null
Indexes:
"editor_contentmodel_pkey" PRIMARY KEY, btree (ref_id)
"editor_contentmodel_content_2192f49c_uniq" UNIQUE CONSTRAINT, btree (content, ref_id) <---- 1
"editor_contentmodel_ref_id_md5_idx" UNIQUE, btree (ref_id, md5(content::text))
"editor_contentmodel_ref_id_8f74b4f3_like" btree (ref_id varchar_pattern_ops) <----2
Haruskah saya menghapus 1
atau 2
(Lihat panah)?
sumber
Jawaban:
Anda memiliki indeks UNIK pada
(content, ref_id)
, dipanggileditor_contentmodel_content_2192f49c_uniq
Saya tidak yakin mengapa ini ada untuk memulai. Jadi mari kita mundur dan membahas apa yang dilakukannya. Ini memastikan itu
content
, danref_id
unik. Namun, dalam PostgreSQLUNIQUE
kendala diimplementasikan dengan btree yang menjadikan ini solusi yang buruk. Dengan menggunakan metode ini, Anda membuat btree dengan konten yang pada dasarnya menduplikasi ukuran tabel kecil ini, dan membuat indeks raksasa. Indeks raksasa yang masih dibatasi oleh ukuran konten - seperti yang Anda temukan. Itu menimbulkan beberapa pertanyaanApakah Anda peduli bahwa konten itu unik? Jika Anda benar-benar peduli bahwa konten itu unik untuk ref_id, maka yang mungkin Anda inginkan adalah menyimpan hash dari konten tersebut. Sesuatu seperti..
Ini sebagai gantinya akan menyimpan konten md5sum di btree. Selama ref_id memiliki konten dengan md5 unik di atas ref_id itu, Anda baik.
Jika Anda tidak peduli itu
content
unik, pertimbangkan untuk menghapusnya sepenuhnya.Mungkin tidak ada artinya sama sekali ketika Anda menerapkan
UNIQUE
batasan dengan btree (seperti yang dilakukan PostgreSQL), Anda mendapatkan indeks tambahan secara gratis. Dalam keadaan normal ini memiliki manfaat pinggiran.Akan mempercepat kueri
Namun, ketika Anda berkesempatan untuk menggunakan
md5()
varian fungsional tidak ada lagi indeks pada konten, jadi sekarang untuk menggunakan indeks itu Anda harusmd5(content) = md5('This content')
Keseluruhan
text = text
dinilai lebih. Itu hampir tidak pernah seperti yang Anda inginkan. Jika Anda ingin mempercepat permintaan-waktu atas teks, btree tidak berguna. Anda mungkin ingin melihatnyaPEMBARUAN 1
Berdasarkan JSON Anda, saya sarankan menyimpannya sebagai
jsonb
, dan kemudian membuat indeksmd5(content)
; jadi mungkin alih-alih di atas, jalankan ini.PEMBARUAN 2
Anda bertanya indeks mana yang harus Anda hapus
Inilah jawaban yang mengejutkan: Anda harus menghapus semuanya kecuali :
editor_contentmodel_pkey
yang mengatakan bahwa semuaref_id
harus unik.editor_contentmodel_content_2192f49c_uniq
indeks ini memastikan bahwa Anda beradaUNIQUE
diref_id
ANDcontent
, tetapi jika Anda tidak dapat memiliki duplikatref_id
Anda tidak akan pernah memiliki konten duplikat untuk ituref_id
. Jadi Anda tidak akan pernah bisa melanggar indeks ini tanpa juga melanggareditor_contentmodel_pkey
. Itu membuatnya sia-sia.editor_contentmodel_ref_id_md5_idx
indeks ini juga tidak ada gunanya karena alasan yang sama. Anda tidak pernah memiliki duplikatmd5(content::text)
lebihref_id
karena terlepas dari apa nilaimd5(content::text)
adalah Anda tidak pernah memiliki duplikatref_id
.editor_contentmodel_ref_id_8f74b4f3_like
juga merupakan ide yang buruk karena Anda menduplikasi indeksref_id
. Ini tidak berguna, hanya saja tidak optimal. Sebaliknya, jika Anda perluvarchar_pattern_ops
menggunakannya, alih-alih hanyacontent
bidang.Sebagai catatan terakhir, kami tidak banyak menggunakan
varchar
PostgreSQL karena ini diimplementasikan sebagai varlena dengan batasan cek. Tidak ada untungnya, dan tidak ada yang hilang saat Anda menggunakannyatext
. Jadi kecuali ada alasan konkret mengaparef_id
bisa menjadi 120 karakter tetapi bisa 119 karakter, maka saya hanya akan menggunakantext
tipenya.PEMBARUAN 3
Mari kita kembali ke masalah Anda sebelumnya ..
Ini memberitahu Anda masalahnya secara khusus dengan indeks
"editor_contentmodel_content_2192f49c_uniq"
. Anda telah mendefinisikannya sebagaiJadi masalahnya di sini adalah Anda mencoba membuat indeks selesai
content
. Tapi, sekali lagi, indeks itu sendiri menyimpan konten json yang sebenarnyacontent
, dan itulah yang melebihi batas. Ini sebenarnya bukan masalah, karena meskipun batas itu tidak ada di tempateditor_contentmodel_content_2192f49c_uniq
akan sama sekali tidak berguna. Mengapa? lagi Anda tidak dapat menambahkan lebih banyak keunikan ke baris yang sudah dijamin 100% unik. Anda sepertinya tidak mendapatkan ini. Mari kita tetap sederhana.Di atas satu-satunya indeks unik / kendala (tanpa indeks lain) lebih
(ref_id, content)
masuk akal karena akan menghentikan duplikasi(1,1)
. Indeks atas(ref_id, md5(content))
juga masuk akal karena akan menghentikan duplikasi(1,1)
dengan proxy menghentikan duplikasi(1, md5(1))
. Namun semua karya ini karena dalam contoh saya berikanref_id
adalah TIDAK dijamin akanUNIQUE
. Andaref_id
bukan iniref_id
. Andaref_id
adalah seorangPRIMARY KEY
. Itu artinya dijamin UNIK.Itu berarti duplikat
(1,1)
dan deretan(1,2)
TIDAK PERNAH bisa dimasukkan. Itu juga berarti bahwa indeks lebih dari apa pun selain ref_id tidak dapat menjamin lebih banyak keunikan. Mereka harus kurang ketat dari indeks yang Anda miliki saat ini. Jadi meja Anda hanya bisa terlihat seperti inisumber
editor_contentmodel
tabelcolumn
dan menambahkan keunikan md5? atau tidak bisakah kita mengubah sajaCONSTRAINT editor_contentmodel_content_2192f49c_uniq UNIQUE (content, ref_id)
? Mengapa saya harus membuat tabel baru untuk itu?CREATE TABLE
perintahnya dan keluarkanCREATE UNIQUE INDEX
hak di bawahnya. LaluDROP
indeks lama Anda.Update 2
Karena ref_id adalah kunci utama, Anda tidak dapat memiliki nilai duplikatnya. Itu berarti batasan unik pada kombinasi (konten, ref_id) tidak berguna, karena apa pun yang melanggar itu juga akan melanggar batasan kunci utama. Singkirkan saja itu.
sumber
create unique index on editor_contentmodel (ref_id, md5(content::text))
? atau saya bisa membuat ulang tabel dan menghapus kunci utama.