Вставка случайно сгенерированных данных в PostgreSQL очень медленно; - PullRequest
1 голос
/ 29 января 2020

Мне нужно вставить очень большой набор данных в таблицу для целей тестирования. Именно для этой цели я создал скрипт, который генерирует чисто случайные данные. Это работает, но работает так медленно, что я буду здесь месяц воскресенья в ожидании завершения.

Несколько подробностей:

  • Таблица источников содержит 150 миллионов записей
  • Имеется три источника statistics_per_source
  • время ожидания 5
  • В настоящее время для 1000 вставок требуется около 4 минут
  • PostgreSQL -12

Вопрос : Какие шаги я могу предпринять, чтобы приведенный ниже скрипт работал намного быстрее, чем в настоящее время, или какой альтернативный подход я бы использовал, чтобы вставить эту величину случайных данных?


TRUNCATE TABLE public.statistic RESTART IDENTITY;



SELECT 'Creating View Statistics for Sources' as progress;
DO $$
DECLARE
    sleep       integer;
    sps         integer;
    start       integer     := 1;
    increment   integer;
    remaining   integer     := increment;
BEGIN
    SELECT sleep INTO sleep FROM Constants;
    SELECT statistics_per_source  INTO sps FROM Constants;
    SELECT commit_chunk_size INTO increment FROM Constants;
    INSERT INTO Progress(dt, operation, progress) VALUES (now(), 'statistics from source', 'BEGIN INSERT');

LOOP
    SELECT count(*) INTO remaining FROM source WHERE id > start LIMIT 1;
    EXIT WHEN remaining = 0;
    INSERT INTO Progress(dt, operation, progress) VALUES (now(), 'statistics from source', 'Beginning Source=' || start);

    INSERT INTO statistic(created, value, classtype, source_id, source_created, brand)
    SELECT
       date(src.created + trunc(random() * 20) * '1 day'::interval) created,
       (random() * 100000)::int,
       CASE WHEN (random() > 0.5) THEN 'Views' ELSE 'CTR' END,
        src.id,
        src.created,
        NULL
       FROM source src
    CROSS JOIN
        (SELECT generate_series(1, sps) as value ) s
    WHERE src.id between start + 1 and start + increment;

    INSERT INTO Progress(dt, operation, progress) VALUES (now(), 'statistics from source', 'Committing source=' || start);
    COMMIT;
    PERFORM pg_sleep(sleep);
    start := start + increment;
END LOOP ;
END $$;

Таблица выглядит так; Я намеренно пока избегаю создавать индексы для производительности вставки.

CREATE TABLE public.statistic
(
    id bigint NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 9223372036854775807 CACHE 1 ),
    created date NOT NULL,
    value double precision NOT NULL,
    classtype text COLLATE pg_catalog."default",
    data_source integer,
    production integer,
    source_id bigint,
    source_created date,
    brand integer,
    CONSTRAINT statistics_pk PRIMARY KEY (id)
)

1 Ответ

1 голос
/ 29 января 2020

Выполнение count (*) с условием where может несколько замедлить его, вы можете выйти из l oop, когда insert @@ rowcount был равен нулю

...