Secara berkala, nilai-nilai baru ditambahkan graphatau nilai yang ada diperbarui. Saya ingin menyegarkan tampilan graph_avgsetiap beberapa jam hanya untuk nilai yang telah diperbarui. Namun dalam PostgreSQL 9.3, seluruh tabel di-refresh. Ini cukup memakan waktu. Versi berikutnya 9.4 memungkinkan CONCURRENTpembaruan tetapi masih menyegarkan seluruh tampilan. Dengan 100-an juta baris, ini membutuhkan waktu beberapa menit.
Apa cara yang baik untuk melacak nilai yang diperbarui & baru dan hanya menyegarkan tampilan sebagian?
Anda selalu dapat menerapkan tabel Anda sendiri yang berfungsi sebagai "tampilan terwujud". Itulah yang harus Anda lakukan sebelum MATERIALIZED VIEWditerapkan di Postgres 9.3.
(Atau gunakan SELECTpernyataan secara langsung, tanpa membuat a VIEW.)
Kemudian, tergantung pada detail yang tidak diketahui dari use case Anda, Anda bisa DELETE/ UPDATE/ INSERTberubah secara manual.
Pernyataan DML dasar dengan CTE pemodifikasi data untuk tabel Anda adalah :
Dengan asumsi tidak ada mencoba lagi untuk menulis untuk graph_avgsecara bersamaan (membaca adalah tidak ada masalah):
WITH del AS(DELETEFROM graph_avg tWHERENOTEXISTS(SELECT1FROM graph_avg_view v WHERE v.xaxis = v.xaxis);), upd AS(UPDATE graph_avg tFROM graph_avg_view vWHERE t.xaxis = v.xaxisAND t.avg_val <> v.avg_val)INSERTINTO graph_avg tSELECT*FROM graph_avg_view vLEFTJOIN graph_avg t USING(xaxis)WHERE t.xaxis ISNULL;
Tetapi ini kemungkinan besar harus dioptimalkan.
Resep dasar:
Tambahkan timestampkolom dengan default now()ke tabel basis Anda. Sebut saja ts.
Jika Anda memiliki pembaruan, tambahkan pemicu untuk mengatur cap waktu saat ini dengan setiap pembaruan yang berubah baik xaxisatau value.
Buat tabel kecil untuk mengingat stempel waktu dari foto terbaru Anda. Sebut saja mv:
CREATETABLE mv (
tbl text PRIMARYKEY, ts timestamp NOTNULLDEFAULT'-infinity');-- possibly more details
Buat parsial, indeks multikolom ini:
CREATEINDEX graph_mv_latest ON graph (xaxis, value)WHERE ts >='-infinity';
Gunakan cap waktu snapshot terakhir sebagai predikat dalam kueri Anda untuk menyegarkan snapshot dengan penggunaan indeks yang sempurna.
Di akhir transaksi, lepaskan indeks dan buat kembali dengan stempel waktu transaksi menggantikan stempel waktu dalam predikat indeks (awalnya '-infinity'), yang juga Anda simpan ke meja Anda. Semuanya dalam satu transaksi.
Perhatikan bahwa indeks parsial bagus untuk dibahas INSERTdan UPDATEdioperasikan, tetapi tidak DELETE. Untuk mengatasinya, Anda perlu mempertimbangkan seluruh tabel. Itu semua tergantung pada persyaratan yang tepat.
Terima kasih atas kejelasan pandangan terwujud dan menyarankan jawaban alternatif.
user4150760
13
Pembaruan Serentak (Postgres 9.4)
Meskipun bukan pembaruan tambahan seperti yang Anda minta, Postgres 9.4 memang menyediakan fitur pembaruan bersamaan yang baru .
Mengutip dokumen ...
Sebelum PostgreSQL 9.4, menyegarkan tampilan terwujud berarti mengunci seluruh tabel, dan karenanya mencegah permintaan apa pun, dan jika pembaruan membutuhkan waktu lama untuk mendapatkan kunci eksklusif (saat menunggu kueri menggunakannya untuk menyelesaikannya), pada gilirannya memegang pertanyaan selanjutnya. Ini sekarang dapat dikurangi dengan kata kunci CONCURRENTLY:
Namun, indeks yang unik perlu ada pada tampilan terwujud. Alih-alih mengunci tampilan terwujud, alih-alih membuat versi yang diperbarui sementara, membandingkan dua versi, lalu menerapkan INSERT dan HAPUS terhadap tampilan terwujud untuk menerapkan perbedaan. Ini berarti kueri masih dapat menggunakan tampilan terwujud saat sedang diperbarui. Tidak seperti bentuk non-konkuren, tupel tidak beku, dan perlu VACUUM karena DELETE yang disebutkan sebelumnya yang akan meninggalkan tupel mati.
Pembaruan bersamaan ini masih menjalankan kueri baru yang lengkap (bukan tambahan). Jadi CONCURRENTLY tidak menghemat waktu perhitungan keseluruhan, itu hanya meminimalkan jumlah waktu tampilan terwujud Anda tidak tersedia untuk digunakan selama pembaruan.
Sejenak aku bersemangat sampai aku membaca dengan cermat. it instead creates a temporary updated version of it...compares the two versions- Ini berarti versi sementara yang diperbarui masih merupakan perhitungan penuh, maka itu berlaku perbedaan untuk tampilan yang ada. Jadi intinya, saya masih melakukan kembali SEMUA perhitungan, tetapi hanya di tabel sementara.
user4150760
5
Ah, benar, CONCURRENTLYtidak menghemat waktu perhitungan keseluruhan, itu hanya meminimalkan jumlah waktu tampilan terwujud Anda tidak tersedia untuk digunakan selama pembaruan.
Pembaruan Serentak (Postgres 9.4)
Meskipun bukan pembaruan tambahan seperti yang Anda minta, Postgres 9.4 memang menyediakan fitur pembaruan bersamaan yang baru .
Mengutip dokumen ...
Pembaruan bersamaan ini masih menjalankan kueri baru yang lengkap (bukan tambahan). Jadi CONCURRENTLY tidak menghemat waktu perhitungan keseluruhan, itu hanya meminimalkan jumlah waktu tampilan terwujud Anda tidak tersedia untuk digunakan selama pembaruan.
sumber
it instead creates a temporary updated version of it...compares the two versions
- Ini berarti versi sementara yang diperbarui masih merupakan perhitungan penuh, maka itu berlaku perbedaan untuk tampilan yang ada. Jadi intinya, saya masih melakukan kembali SEMUA perhitungan, tetapi hanya di tabel sementara.CONCURRENTLY
tidak menghemat waktu perhitungan keseluruhan, itu hanya meminimalkan jumlah waktu tampilan terwujud Anda tidak tersedia untuk digunakan selama pembaruan.