powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Максимально быстрая вставка в таблицу 1млн+ записей
13 сообщений из 13, страница 1 из 1
Максимально быстрая вставка в таблицу 1млн+ записей
    #38533087
Yurgens
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Привет

Как .NET максимально быстро вставить в таблицу 1 млн+ записей?
Из всего что перепробовал быстрее всего получается пачками по 1000 в виде
INSERT INTO tbl (id, rel) values (1, 2), (2,3),...

Пробовал через адаптер, получается существенно медленнее.
...
Рейтинг: 0 / 0
Максимально быстрая вставка в таблицу 1млн+ записей
    #38533139
Yurgens,

Вопрос, а что является источником этих миллионов записей?
Дальше возможны варианты.

Вариант 1: (По идее самый быстрый) Вызвать утилиту IMPORT или LOAD с помощью хранимой процедуры ADMIN_CMD procedure - Run administrative commands
Файл должен физически находится на файловой системе сервера или узла координатора. Т.е. этот способ применим не всегда.
В принципе можно из .Net вызвать командную строку db2 на клиенте (где установлен .Net) и выполнить команду IMPORT или LOAD с клиента.

Вариант 2: Использовать класс DB2BulkCopy Class

Вариант 3: Оптимизировать работу провайдера.

По этому варианту описание здесь: Dramatically improve performance on DB2 Inserts
Суть: Выполнять SQL-операторы между вызовами методов BeginChain() и EndChain().
В таком случае провайдер объединяет операторы в блоки и передает их в СУБД тоже блоками, что значительно увеличивает производительность.

DB2Connection.BeginChain Method
DB2Connection.EndChain Method

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
DB2Connection conn;

conn.BeginChain();

#<SQL-операторы>

conn.EndChain();
...
Рейтинг: 0 / 0
Максимально быстрая вставка в таблицу 1млн+ записей
    #38533159
CawaSPb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Евгений Хабаров,

Даже ссылки идентичные подобрались :)

Добавил бы ещё:
а) не забыть поиграться с параметризацией (всё-таки 1000000 компиляций - это значимо + напрочь вымоет кэши)
б) можно подумать об отмене логирования на таблице, хотя в целом это порочная практика (LOAD лучше, там можно COPY YES выставить)
в) посмотреть на прочие практики, описанные тут - " Tips for improving INSERT performance in DB2 Universal Database ".
...
Рейтинг: 0 / 0
Максимально быстрая вставка в таблицу 1млн+ записей
    #38533335
Yurgens
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В .NET из какой-то системы получаем 1 млн+ ID-шек, которые по факту нужно пересечь с ID-шками в базе. Сейчас это делается путем вставки новой таблицы в базу (с параметрами NOT LOGGED IN INITIALLY и APPEND ON) и записыванием их туда через
INSERT INTO " + tableName + " (ID, REL) values (1,2), (2,2), (3,2),...
где в одно выполнение INSERT INTO помещается лишь тысяча айдишек, т.е. кол-во транзакций 1 млн/1000
при такой схеме перформанс получается 60 сек на 1 млн айдишек... как-то медленно.
...
Рейтинг: 0 / 0
Максимально быстрая вставка в таблицу 1млн+ записей
    #38533372
Yurgens,

Сразу возникает вопрос что за система, а то может можно туда напрямую через СУБД обратиться?
Если исходную систему можно прицепить через Federation, то можно и сквозные запросы делать.
Ну и например MERGE-оператор единый провести.
Как вариант, можно настроить репликацию между системами, если это нужно.
В каком формате и виде поступают данные из исходной системы?
...
Рейтинг: 0 / 0
Максимально быстрая вставка в таблицу 1млн+ записей
    #38533428
Yurgens
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Подключить базу в исходную систему нет возможности, есть выход из системы в виде массива в .NET-е
...
Рейтинг: 0 / 0
Максимально быстрая вставка в таблицу 1млн+ записей
    #38533449
CawaSPb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Yurgens,

1. Коммит делать только в самом конце. Пусть это будет 1 транзакция из 1000 запросов.
2. Параметризовать запрос - пусть он не 1000 раз компилируется для каждого набора из 1000 ID'шек. Параметризация также сведёт запрос к одной entry в кэше, что позволит полнее посмотреть его метрики и разобраться, во что упираемся.
3. Если ID строго упорядочены, то можно в два раза уменьшить объём данных, передаваемых с клиента.
4. Ну и скажите, поигрались ли с BeginChain()/EndChain()?

Обратите также внимание, что NOT LOGGED INITIALLY действует до первого коммита.
APPEND ON - правильно.

Интересный вариант (в качестве эксперимента "на попробовать") - упаковать всё в один XML, впихнуть его в базу одним запросом, а дальше просто по нему (его индексам) запросы гонять.


PS Ещё раз присоединюсь к Евгению - опишите задачу полностью. Правильное архитектурное решение может дать гораздо лучший и наиболее просто поддерживаемый результат.
...
Рейтинг: 0 / 0
Максимально быстрая вставка в таблицу 1млн+ записей
    #38533509
Yurgens
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
То, что уже попробовал:
1) var adp = new DB2DataAdapter() и adp.InsertCommand
- Сверх сильно грузит процессор на сервере с .NET и создает колосальный сетевой трафик
- игрался в нем параметром UpdateBatchSize, опять же около 1000 было оптимально
- работает в разы медленнее, особенно на 5 млн...

2) var blkCpy = new DB2BulkCopy( connection)
- грузит процессор, но терпимо
- создает большой сетевой трафик
- работает медленнее чем вариант с INSERT INTO tbl (id, rel) values (1, 2), (2,3),... где-то на 20-30%

3) вариант с INSERT INTO tbl (id, rel) values (1, 2), (2,3),... пачками по 1000 пока самый быстрый и оптимальный

4) анализирую вариант с LOAD
...
Рейтинг: 0 / 0
Максимально быстрая вставка в таблицу 1млн+ записей
    #38533514
Yurgens
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Кстати, производительность немного поднялась, когда стал создавать индекс уже после наполнения таблицы.
...
Рейтинг: 0 / 0
Максимально быстрая вставка в таблицу 1млн+ записей
    #38543045
A.Panskikh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Yurgens,

включите трассировку на стороне апликухи и посмотрите, что выполняется и как. Сразу станет понятно, откуда идет сетевой трафик, на какие операции расходуется время.

Andy
...
Рейтинг: 0 / 0
Максимально быстрая вставка в таблицу 1млн+ записей
    #38544728
Mark Barinstein
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
A.Panskikh,

Начиная с 9.7, появились функции типа MON_FORMAT_XML_*_BY_ROW, с помощью которых можно довольно детально получать информацию о том, на что тратится время по одному запросу, всему соединению, всей базе и ещё по нескольким объектам.
Например, MON_FORMAT_XML_TIMES_BY_ROW .
По какой-то причине не сделана очевидная вещь - сделать так, чтобы показатели, возвращаемые этими функциями, показавались в удобном для просмотра иерархическом виде.
Но это можно сделать самому.
Например, для MON_FORMAT_XML_TIMES_BY_ROW:

FUNCTION MON_FORMAT_XML_TIMES_BY_ROW_TREE
Код: 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.
CREATE FUNCTION MON_FORMAT_XML_TIMES_BY_ROW_TREE(DETAILS BLOB(100M))
RETURNS TABLE(
  LVL                  INT
, COUNT                BIGINT
, TOTAL_TIME_VALUE     BIGINT
, TOTAL_TIME_VALUE_PST INT
, METRIC_NAME          VARCHAR(128)
, CHAIN                VARCHAR(256)
)
READS SQL DATA
DETERMINISTIC
NO EXTERNAL ACTION
RETURN
with w as (
select
  metric_name
, total_time_value
, count
, parent_metric_name
from TABLE(MON_FORMAT_XML_TIMES_BY_ROW(DETAILS)) AS F
)
, t (metric_name, total_time_value, count, total_time_value_pst, lvl, chain) as (
select 
  metric_name
, total_time_value, count, 100
, 0, cast(metric_name as varchar(256))
from w a
where not exists (select 1 from w b where b.metric_name=a.parent_metric_name)
  union all
select 
  w.metric_name
, w.total_time_value, w.count
, 100*w.total_time_value/nullif(t.total_time_value, 0) total_time_value_pst
, t.lvl+1, t.chain||'|'||w.metric_name
from w, t
where w.parent_metric_name=t.metric_name
)
select 
  lvl, count, total_time_value, total_time_value_pst
, repeat('  ', lvl)||metric_name metric_name, chain
from t


Эту функцию можно использовать вместе с любой MON_GET_*_DETAILS, например, так:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
--по своему соединению
select F.*
from 
  TABLE(MON_GET_CONNECTION_DETAILS(MON_GET_APPLICATION_HANDLE(), -2)) AS X
, TABLE(MON_FORMAT_XML_TIMES_BY_ROW_TREE(X.DETAILS)) AS F
ORDER BY F.CHAIN;
--по workload (для тех, кто не использует WLM, это практически равнозначно по всей базе)
select F.*
from 
  TABLE(MON_GET_WORKLOAD_DETAILS('SYSDEFAULTUSERWORKLOAD', -1)) AS X
, TABLE(MON_FORMAT_XML_TIMES_BY_ROW_TREE(X.DETAILS)) AS F
ORDER BY F.CHAIN;
...
Рейтинг: 0 / 0
Максимально быстрая вставка в таблицу 1млн+ записей
    #38546775
Yurgens,

в команде

import ... of [ del или ixf ]

добавьте

MODIFIED BY COMPOUND=50

у меня с этим параметром скорость загрузки увеличилась в 15 раз
...
Рейтинг: 0 / 0
Максимально быстрая вставка в таблицу 1млн+ записей
    #38546936
A.Panskikh
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Марк, не скажу, что это проще...

Есть еще ряд моментов, которые не закрываются - например, определение в .net рекордсета как scrollable пораждает некислый оверхед на каждый запрос

CALL SYSIBM.SQLPRIMARYKEYS(?,?,?,?)
CALL SYSIBM.SQLSTATISTICS(?,?,?,?,?,?)
WITH SYSIBM.SQLPRIMARYKEYS ( TABLE_CAT, TABLE_SCHEM, TABLE_NAME, ...

в итоге стоимость полезной нагрузки в разы меньше паразитной. У меня в одном случае суммарное время выполения 44 сек, из них только 4 сек - на собственно сам запрос.

Andy
...
Рейтинг: 0 / 0
13 сообщений из 13, страница 1 из 1
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Максимально быстрая вставка в таблицу 1млн+ записей
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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