Advertisement
skaurus

декларативно партиционированные креативы

Oct 18th, 2018
154
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
SQL 2.40 KB | None | 0 0
  1. CREATE TABLE creatives (
  2.     id          bigserial   NOT NULL,
  3.     dsp_id      INTEGER     NOT NULL,
  4.     bid_id      text        NOT NULL, -- тащемта явно не все креативы в мире имеют это поле... но пока что openrtb, а там посмотрим
  5.     click_url   text        NOT NULL,
  6.     title       text        NOT NULL,
  7.     thumbs      text[][]    NOT NULL,
  8.     dump        jsonb       NOT NULL,
  9.     ctime       TIMESTAMP   NOT NULL DEFAULT now(),
  10.     info        json
  11. ) PARTITION BY RANGE (ctime);
  12.  
  13. CREATE OR REPLACE FUNCTION week_table_suffix_from_ts(ts TIMESTAMP WITH TIME zone) RETURNS text
  14.     LANGUAGE plpgsql
  15.     AS $$
  16. DECLARE
  17.     table_suffix text := REPLACE(SUBSTRING((date_trunc('week', ts))::text FROM 1 FOR 10),'-','');
  18. BEGIN
  19.     RETURN table_suffix;
  20. END;
  21. $$;
  22.  
  23. CREATE OR REPLACE FUNCTION creatives_partitioning_trigger_f() RETURNS TRIGGER
  24.     LANGUAGE plpgsql
  25.     AS $$
  26. DECLARE
  27.     table_prefix    text    := 'creatives_';
  28.     CURRENT_TIME    TIMESTAMP WITH TIME zone := now();
  29.     table_suffix    text    := week_table_suffix_from_ts(CURRENT_TIME);
  30.     TABLE_NAME      text    := 'creatives_' || table_suffix;
  31.     table_exists    BOOLEAN;
  32. BEGIN
  33.     EXECUTE
  34.         'SELECT EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = $1 AND tablename = $2)'
  35.         INTO table_exists
  36.         USING 'public', TABLE_NAME;
  37.  
  38.     IF NOT table_exists THEN
  39.         EXECUTE format(
  40.             'CREATE TABLE IF NOT EXISTS %I PARTITION OF creatives FOR VALUES FROM (%L) TO (%L)'::text,
  41.             TABLE_NAME,
  42.             date_trunc('week', CURRENT_TIME),
  43.             date_trunc('week', CURRENT_TIME + INTERVAL '1 week')
  44.         );
  45.  
  46.         EXECUTE format( -- это ж всё равно serial, поэтому unique не делаю
  47.             'CREATE INDEX IF NOT EXISTS %I ON %I (id)'::text,
  48.             TABLE_NAME || '_id', TABLE_NAME
  49.         );
  50.  
  51.         EXECUTE format(
  52.             'CREATE INDEX IF NOT EXISTS %I ON %I (bid_id)'::text,
  53.             TABLE_NAME || '_bidid', TABLE_NAME
  54.         );
  55.  
  56.         EXECUTE format(
  57.             'CREATE INDEX IF NOT EXISTS %I ON %I (dsp_id, ctime)'::text,
  58.             TABLE_NAME || '_dspid_ctime', TABLE_NAME
  59.         );
  60.     END IF;
  61.  
  62.     RETURN NULL;
  63. END;
  64. $$;
  65.  
  66. CREATE TRIGGER creatives_partitioning_trigger BEFORE INSERT ON creatives FOR EACH STATEMENT EXECUTE PROCEDURE creatives_partitioning_trigger_f();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement