Балансировка потоков в Oracle
При параллельной загрузке данных в хранилище, чтобы уменьшить время общей загрузки таблиц часто применяется динамическая балансировка по потокам. То есть, разные задачи группируются в какое то количество потоков (обычно константа, но может также меняться в зависимости от разных условий). Выходит что на основании веса разбиваем задачи на несколько потоков, желательно чтобы максимальный суммарный вес одного потока был минимальным. Итак получается: Задача о ранце (рюкзаке) (англ. Knapsack problem) .
Но приведу более простой алгоритм, может и не самый эффективный, но простой и удобный в реализации.
Весом могут быть разные параметры, например:
- время загрузки в прошлый раз
- количество строк
- размер таблицы
- статистике
Реализация алгоритма на Oracle:
WITH
--элементы с весом или продолжительностью
ITEMS AS
(SELECT 1 AS ID, 100 AS WEIGHT FROM DUAL UNION ALL
SELECT 5 AS ID, 100 AS WEIGHT FROM DUAL UNION ALL
SELECT 6 AS ID, 100 AS WEIGHT FROM DUAL UNION ALL
SELECT 2 AS ID, 1 AS WEIGHT FROM DUAL UNION ALL
SELECT 3 AS ID, 1 AS WEIGHT FROM DUAL UNION ALL
SELECT 4 AS ID, 1 AS WEIGHT FROM DUAL),
--считаем общую сумму, и накопительную
ITEMS1 AS
(SELECT ITEMS.*,
(SUM(ITEMS.WEIGHT) OVER(PARTITION BY 1)) AS SUM_ALL,
(SUM(ITEMS.WEIGHT) OVER(PARTITION BY 1 ORDER BY WEIGHT ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)) SUM_CURR
FROM ITEMS)
--результат в поле V$FLOW
SELECT ID,
WEIGHT,
SUM_ALL,
SUM_CURR,
WIDTH_BUCKET(SUM_CURR,0,SUM_ALL,4) V$FLOW --количество потоков = 4
FROM ITEMS1
В результате получим:
| ID | WEIGHT | SUM_ALL | SUM_CURR | V$FLOW |
|---|---|---|---|---|
| 3 | 1 | 303 | 1 | 1 |
| 2 | 1 | 303 | 2 | 1 |
| 4 | 1 | 303 | 3 | 1 |
| 5 | 100 | 303 | 103 | 2 |
| 1 | 100 | 303 | 203 | 3 |
| 6 | 100 | 303 | 303 | 5 |
Комментарии
Отправить комментарий