powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Длительные транзакции
11 сообщений из 11, страница 1 из 1
Длительные транзакции
    #38934720
big-trot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.

Есть таблица (planet_osm_line) - 87 млн записей. Из этой таблицы путем типового запроса SELECT ... INTO TABLE ..., выполняется формирование новой таблицы. Запрос выполняется больше суток. Вопрос - как понять, что запрос выполняется, а не завис? Куда и как смотреть, что бы понять что вставка данных идет и нужно просто набраться терпения и дождаться результата?
Спасибо.
...
Рейтинг: 0 / 0
Длительные транзакции
    #38934790
Alexius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
big-trot,

смотреть в pg_stat_activity поле waiting у строки с запросом, если оно false и status=active - значит запрос выполняется (но не значит что за разумное время завершится). понять, завершится ли можно по explain запроса.
по top/iotop/iostat можно понять во что запрос упирается: в cpu или диски.
...
Рейтинг: 0 / 0
Длительные транзакции
    #38934850
Gold_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
big-trot,

Если есть в новой таблице поле, заполняемое последовательностью (напрbмер - serial), то можно смотреть значение последовательности.
...
Рейтинг: 0 / 0
Длительные транзакции
    #38935030
Фотография grufos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
big-trot,

В книге "PostgreSQL 9 Administration Cookbook" Simon Riggs, Hannu Krosing
есть функция pg_relation_size_nolock которая показывает как узнать физический размер который занимает таблица на диске.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
CREATE OR REPLACE FUNCTION pg_relation_size_nolock(tablename regclass)
RETURNS BIGINT
LANGUAGE plpgsql
AS $$
DECLARE
    classoutput RECORD;
    tsid INTEGER;
    rid INTEGER;
    dbid INTEGER;
    filepath TEXT;
    filename TEXT;
    datadir TEXT;
    i INTEGER := 0;
    tablesize BIGINT;
BEGIN
    --
    -- получаем директорию с данными
    --
    EXECUTE 'SHOW data_directory' INTO datadir;
    -- получаем relfilenode и reltablespace
    SELECT reltablespace as tsid,relfilenode as rid INTO classoutput
    FROM pg_class
    WHERE oid = tablename
    AND relkind = 'r';
    --
    -- генерируем ошибку если не можем найти указанную таблицу
    --
    IF NOT FOUND THEN
        RAISE EXCEPTION 'tablename % not found', tablename;
    END IF;
    tsid := classoutput.tsid;
    rid := classoutput.rid;
    --
    -- получаем внутренний идентификатор объекта самй БД - oid
    --
    SELECT oid INTO dbid
    FROM pg_database
    WHERE datname = current_database();
    -- 
    -- используем внутренее представление о формировании полного имени файла
    --
    IF tsid = 0 THEN
        filepath := datadir || '/base/' || dbid || '/' || rid;
    ELSE
        filepath := datadir || '/pg_tblspc/' || tsid || '/' || dbid || '/' || rid;
    END IF;
    --
    -- получаем размер полученного файла
    --
    SELECT (pg_stat_file(filepath)).size INTO tablesize;
    --
    -- суммируем размеры всех возможных дополнительных файлов, если они есть
    --
    WHILE FOUND LOOP
        i := i + 1;
        filename := filepath || '.' || i;
        --
        -- pg_stat_file возвращает ERROR если не может найти файл
        -- таким образом мы знаем, что больше нечего искать
        --
        BEGIN
            SELECT tablesize + (pg_stat_file(filename)).size INTO tablesize;
        EXCEPTION
            WHEN OTHERS THEN EXIT;
        END;
    END LOOP;
    RETURN tablesize;
END;
$$;


далее используете следующее
Код: sql
1.
2.
3.
4.
-- создаем таблицу нужной структуры и обеспечиваем существование таблицы вне транзакции копирования данных
select * into table_dest from table_source where 1=2; 
-- начинаем копирование
insert into table_dest select * from table_source;



в другом соединении выполняем команду
Код: sql
1.
select round(pg_relation_size_nolock('table_dest'::regclass)*100.0/pg_relation_size_nolock('table_source'::regclass),2);


теперь мы можем видеть в % как много еще осталось скопировать.
Если же разделить полученный размер в байтах (pg_relation_size_nolock('table_dest'::regclass)) на среднюю ширину строки, то можно получить приблизительный объем вставленных строк.
...
Рейтинг: 0 / 0
Длительные транзакции
    #38935136
big-trot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ситуация несколько иная. Выражение SELECT ... INTO TABLE ... похоже не создает сразу таблицу в явном виде, потому что её не видно ни в одном из инструментов. Можно предположить, что таблица появится после выполнения всей операции в целом. В настоящий момент нет возможности обратиться к этой таблице и отследить как идет вставка. В pg_stat_activity процесс находится в активном состоянии. С помощью запроса select pg_database_size(current_database()) видно, что размер базы данных увеличивается. Не ясно, как понять когда процесс завершится.
...
Рейтинг: 0 / 0
Длительные транзакции
    #38935148
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
big-trot,

Такие вещи сначала тестируют на тестовой базе (или если таковой нет на каком то разумном обьеме данных на боевой базе) чтобы иметь представление о времени выполнения. Сейчас вы это никак не узнаете.

--
Maxim Boguk
www.postgresql-consulting.ru
...
Рейтинг: 0 / 0
Длительные транзакции
    #38935154
big-trot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
На разумном объеме это все работает, потому что проверялось на меньшей геометрии (данные вставлялись для одного города).
...
Рейтинг: 0 / 0
Длительные транзакции
    #38935207
Фотография grufos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
big-trotВыражение SELECT ... INTO TABLE ... похоже не создает сразу таблицу в явном виде,
именно поэтому я написал вам, что таблицу источник нужно создать заранее, отдельной командой в отдельном запросе.
...
Рейтинг: 0 / 0
Длительные транзакции
    #38935209
Фотография grufos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
big-trotНе ясно, как понять когда процесс завершится.
далее вы можете смотреть на время потраченное на запись определенного объема данных и зная каков общий объем примерно понять как долго еще будет идти процесс.
...
Рейтинг: 0 / 0
Длительные транзакции
    #38936373
big-trot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Опытным путем пришел к следующей схеме работы с данными больших таблиц.
1. Если необходимо выполнить выборку данных из большой таблицы и результат направить в другую таблицу, то целесообразно результат запросы выгружать сначала в файл с помощью команды COPY, и далее той же командой COPY загрузить данные в предварительно созданную под эти данные таблицу.
2.Не рекомендуется использовать команду типа SELECT ... INTO TABLE. Данной выражение работает на несколько порядков медленнее.
3.Правда не пробовал вариант INSERT INTO ... SELECT... Осмелюсь предположить, что этот вариант равносилен SELECT ... INTO TABLE.

На основании чего были сделаны выводы:
Исходная таблица - 86 млн. записей.
В результате выполнения запроса получено - 4 млн. записей.
Время выборки и копирование результата в файл заняло чуть больше 4-х часов. Время вставки данных из файла в таблицу - секунды.
Время выполнения команды SELECT ... INTO TABLE - запрос еще выполняется. Но уже время выполнения запроса в настоящий меряется сутками.
...
Рейтинг: 0 / 0
Длительные транзакции
    #38937116
Alexius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
big-trot,

в общем случае так рекомендовать нельзя. провел тест ради интереса на 9.3 на тестовых данных (таблица узкая, 48 байт. на широких может быть иначе):

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
postgres=# select count(*) from posts2;
  count
---------
 1513912
(1 row)

Time: 293.055 ms

postgres=# select * into temp1 from posts2 where id % 2 = 1;
SELECT 756956
Time: 1217.439 ms

postgres=# copy (select * from posts2 where id % 2 = 1) to '/path/temp1.data';
COPY 756956
Time: 2522.389 ms

postgres=# copy (select * from posts2 where id % 2 = 1) to '/path/temp2.data' with (format 'binary');
COPY 756956
Time: 1423.973 ms



copy в text формате стабильно 2 раза медленнее, в binary примерно так же. на аналогичной 10М таблице результаты примерно такие же.

insert into кстати медленней select * into (т.к. ему нужно данные еще через wal прогнать, в отсутствии репликации остальные варианты в wal'ы писать не будут скорее всего).

в unlogged таблицу примерно с такой же скоростью работает:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
postgres=# create table temp24 (like posts2);

postgres=# insert into temp24 select * from posts2 where id % 2 = 1;
INSERT 0 756956
Time: 2920.123 ms

postgres=# create unlogged table temp25 (like posts2);

postgres=# insert into temp25 select * from posts2 where id % 2 = 1;
INSERT 0 756956
Time: 1364.296 ms
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Длительные транзакции
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]