Agregat dalam database - pemrosesan aliran "fakta" yang efisien

Misalkan Anda perlu memproses sejumlah besar (tidak, bukan ... BESAR) jumlah record di PostgreSQL untuk menghitung beberapa agregat. Dalam artikel sebelumnya , kami menganalisis berbagai opsi tentang bagaimana hal ini dapat diatur, dan dalam artikel ini kita akan melihat bagaimana tidak memblokir siapa pun secara khusus , termasuk "aliran masuk" data.





Misalnya, dapat menghitung ulang saldo dan mempertahankan penjualan terkonsolidasi untuk barang dengan pengiriman konstan, atau menggabungkan saldo dan perputaran untuk akun akuntansi, dengan perubahan besar dalam transaksi, atau hal lain ... Dalam sistem manajemen apa pun, akan ada slide , dan VLSI juga tidak terkecuali.





Tetapi semua situasi ini memiliki poin yang sama - jumlah perubahan  jauh  lebih besar daripada jumlah agregat target. Misalnya: ribuan barang, masing-masing dengan pengiriman puluhan ribu per hari.





Dalam pertimbangan lebih lanjut, kami akan mengandalkan model "Amazon dengan barang" ini.





Target - penjualan harian terkonsolidasi

Kami ingin memiliki agregat untuk penjualan dalam konteks  produk / hari / kuantitas .





Secara khusus, dalam hal ini, kami akan membuat agregat "langsung di database" agar dapat menerimanya dengan  cepat dan menyeluruh  untuk berbagai laporan.





, , , - ClickHouse, . , , , , , , , ...





- ( ), 2PC- , - .





, -   ,  , - , . ,  "" ,   .





?.. ...





    , ,  "" - - , - - ,   "" ,   ""  .





  - "", - "--".





"" , ,    ().





""

"". , - , .





  ""  .  INSERT, UPDATE DELETE



, "" -  INSERT



. , PostgreSQL  , - unique-.





, " " ,   - . , - , "" flow-.





"" ""

flow- ,   / ""  "- - ".





""? " , " -   58    .





,   , . , --, ,   .





, , , "" - …   fail, :





DELETE FROM flow WHERE (it, dt) = (1, '2018-07-29') RETURNING *;
      
      



, - " ". , 1K/, 10K/.





:





SET statement_timeout = 1000;
      
      



, ! , , - flow- ,   . …





, "" , . " ", .





, flow , ,   "" .





, , ! ,   :





DECLARE curs CURSOR FOR SELECT ctid, * FROM flow WHERE (it, dt) = (1, '2018-07-29') FOR UPDATE;
--  , ,    
    FETCH %d FROM curs;
    DELETE FROM flow WHERE ctid = ANY(...);
      
      



flow  ctid - ""   .





SAVEPOINT

, "". %d FETCH? - , - ... ?





PostgreSQL " "  SAVEPOINT/ROLLBACK TO, "" .





:





  1.  ( - , ).





  2. .





  3. -   COMMIT' .





  4.   , - COMMIT'.





  5.   ,  - , "" ( , ).





  6. !





BEGIN;
  DECLARE curs CURSOR FOR SELECT ctid, * FROM flow WHERE (it, dt) = (1, '2018-07-29') FOR UPDATE;

  FETCH 1 FROM curs;
  DELETE FROM flow WHERE ctid = ANY(...);
  -- processing
  INSERT INTO agg ...
  SAVEPOINT _1;
  
  FETCH 2 FROM curs;
  DELETE FROM flow WHERE ctid = ANY(...);
  -- processing
  INSERT INTO agg ...
  SAVEPOINT _2;
  
  FETCH 4 FROM curs;
  DELETE FROM flow WHERE ctid = ANY(...);
  -- processing...
  INSERT INTO agg ...
  -- oops! timeout exception!
  ROLLBACK TO _2;
  
  CLOSE curs;
COMMIT;
      
      



. , , !








All Articles