PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Perlu membuat pemicu yang menambah nilai dalam tabel setelah penyisipan

Mempertahankan nilai ringkasan itu rumit - mudah untuk menciptakan kemungkinan deadlock program Anda.

Jika Anda benar-benar harus melakukan ini, karena Anda tahu bahwa Anda akan mengalami masalah kinerja jika tidak (seperti nhunt dalam ratusan atau lebih), maka lebih baik untuk membuat tabel ringkasan terpisah untuk nhunts, seperti:

CREATE TABLE hunts_summary
(
    id_hs bigserial primary key,
    id_h integer NOT NULL,
    nhunts integer NOT NULL
);
CREATE INDEX hunts_summary_id_h_idx on hunts_summary(id_h);

Pemicu perburuan:

  • berjalan untuk setiap baris yang ditambahkan, dihapus, diperbarui;
  • menambahkan baris (id_h, nhunts) = (NEW.id_h, 1) pada setiap sisipan;
  • menambahkan baris (id_h, nhunts) = (OLD.id_h, -1) pada setiap penghapusan;
  • kedua hal di atas pada pembaruan yang mengubah id_h .

Karena pemicu hanya akan menambahkan baris baru, pemicu tidak mengunci baris yang ada dan karena itu tidak dapat menemui jalan buntu.

Tapi ini tidak cukup - seperti yang dijelaskan di atas tabel ringkasan akan menumbuhkan baris secepat atau lebih cepat dari tabel berburu, jadi itu tidak terlalu membantu. Jadi kita perlu menambahkan beberapa cara untuk menggabungkan baris yang ada secara berkala - beberapa cara untuk mengubah:

id_h nhunts
1    1
1    1
2    1
2    -1
1    1
1    -1
2    1
1    1
2    1

Kepada:

id_h nhunts
1    3
2    2

Ini tidak boleh berjalan pada setiap pemanggilan pemicu, karena kemudian akan menjadi sangat lambat, tetapi dapat berjalan secara acak - misalnya setiap pemanggilan 1/1024 secara acak. Fungsi ini akan menggunakan kata kunci "lewati terkunci" untuk menghindari menyentuh baris yang sudah terkunci, menghindari kemungkinan kebuntuan.

Pemicu tersebut akan terlihat seperti ini:

create or replace function hunts_maintain() returns trigger
as $hunts_maintain$
        begin
                if (tg_op = 'INSERT') then
                        insert into hunts_summary(id_h, nhunts)
                                values (NEW.id_h, 1);
                elsif (tg_op = 'DELETE') then
                        insert into hunts_summary(id_h, nhunts)
                                values (OLD.id_h, -1);
                elsif (tg_op = 'UPDATE' and NEW.id_h!=OLD.id_h) then
                        insert into hunts_summary(id_h, nhunts)
                                values (OLD.id_h, -1), (NEW.id_h, 1);
                end if;

                if (random()*1024 < 1) then
                        with deleted_ids as (
                                select id_hs from hunts_summary for update skip locked
                        ),
                        deleted_nhunts as (
                                delete from hunts_summary where id_hs in (select id_hs from deleted_ids) returning id_h, nhunts
                        )
                        insert into hunts_summary (id_h, nhunts) select id_h, sum(nhunts) from deleted_nhunts group by id_h;
                end if;

                return NEW;
        end;
$hunts_maintain$ language plpgsql;

create trigger hunts_maintain
        after insert or update or delete on hunts
        for each row execute procedure hunts_maintain();

Pemicunya berjalan cukup cepat di laptop saya untuk menyisipkan 1 juta baris untuk berburu tabel dalam 45 detik.

Tampilan di bawah ini akan memudahkan untuk mengekstrak nhunts saat ini dari ringkasan. Menanyakannya akan membutuhkan sedikit atau ms bahkan jika tabel perburuan akan berjumlah miliaran:

create or replace view hunts_summary_view as
        select id_h, sum(nhunts) as nhunts
        from hunts_summary
        group by id_h;



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Setara dengan PostgreSQL untuk TOP n WITH TIES:LIMIT with ties?

  2. Basis data default bernama postgres di server Postgresql

  3. Buat tabel dua jenis di PostgreSQL

  4. Db berbeda untuk pengujian di Django?

  5. Menyimpan dan membandingkan kombinasi unik