Балансировка потоков в 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 |
Комментарии
Отправить комментарий