SQL Oracle - 多处理器调度:贪心数字分区
SQL Oracle - Multiprocessor Scheduling: Greedy Number Partitioning
是否有SQL语句来进行贪心数划分? (甲骨文 19c)
我想在 N 个处理器之间分配作业。
示例,
给定以下工作负载数据集:
job
---
4
60
50
1
100
6
预期结果集(假设只有 N=2,其中关系分配给分配给它的作业数量最少的处理器):
job processor
--- ---------
100 1
60 2
50 2
6 1
4 1
1 2
以下 table 可能有助于阐明这些处理器的分配方式。
job processor length count
--- --------- ------ -----
100 1 100 1
60 2 60 1
50 2 110 2
6 1 106 2
4 1 110 3
1 2 111 3
分析函数和分层查询的某种组合似乎可以实现这一点,而无需诉诸过程代码。预先感谢您的想法和帮助。
您可以使用递归 CTE:
with tt as (
select job, row_number() over (order by job desc) as seqnum
from t
),
cte(job, seqnum, processor, proc1, proc2, lev) as (
select job, seqnum, 1, job as proc1, 0 as proc2, 1
from tt
where seqnum = 1
union all
select tt.job, tt.seqnum,
(case when cte.proc1 > cte.proc2 then 2 else 1 end),
(case when cte.proc1 > cte.proc2 then cte.proc1 else cte.proc1 + tt.job end),
(case when cte.proc1 > cte.proc2 then cte.proc2 + tt.job else cte.proc2 end),
lev + 1
from cte join
tt
on tt.seqnum = cte.seqnum + 1
)
select *
from cte
order by seqnum;
Here 是一个 db<>fiddle.
您可以使用以下类型创建流水线函数:
CREATE TYPE job_processor AS OBJECT(
job NUMBER,
processor NUMBER
);
CREATE TYPE job_processor_list AS TABLE OF job_processor;
那么函数就是:
CREATE FUNCTION partition_jobs (
num_processors IN PLS_INTEGER
) RETURN job_processor_list PIPELINED
IS
processor_time SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST();
processor_id PLS_INTEGER;
min_processor_time TABLE_NAME.JOB%TYPE;
BEGIN
processor_time.EXTEND( num_processors );
FOR i IN 1 .. num_processors LOOP
processor_time(i) := 0;
END LOOP;
FOR j IN ( SELECT job FROM table_name ORDER BY job DESC ) LOOP
processor_id := 1;
min_processor_time := processor_time( processor_id );
FOR i IN 2 .. num_processors LOOP
IF processor_time(i) < min_processor_time THEN
processor_id := i;
min_processor_time := processor_time( processor_id );
END IF;
END LOOP;
PIPE ROW ( job_processor( j.job, processor_id ) );
processor_time( processor_id ) := processor_time( processor_id ) + j.job;
END LOOP;
END;
/
其中,对于示例数据:
CREATE TABLE TABLE_NAME ( job ) AS
SELECT 4 FROM DUAL UNION ALL
SELECT 60 FROM DUAL UNION ALL
SELECT 50 FROM DUAL UNION ALL
SELECT 1 FROM DUAL UNION ALL
SELECT 100 FROM DUAL UNION ALL
SELECT 6 FROM DUAL;
然后:
SELECT *
FROM TABLE( partition_jobs( 2 ) );
输出:
JOB | PROCESSOR
--: | --------:
100 | 1
60 | 2
50 | 2
6 | 1
4 | 1
1 | 1
和:
SELECT *
FROM TABLE( partition_jobs( 3 ) );
输出:
JOB | PROCESSOR
--: | --------:
100 | 1
60 | 2
50 | 3
6 | 3
4 | 3
1 | 2
db<>fiddle here
是否有SQL语句来进行贪心数划分? (甲骨文 19c)
我想在 N 个处理器之间分配作业。
示例,
给定以下工作负载数据集:
job
---
4
60
50
1
100
6
预期结果集(假设只有 N=2,其中关系分配给分配给它的作业数量最少的处理器):
job processor
--- ---------
100 1
60 2
50 2
6 1
4 1
1 2
以下 table 可能有助于阐明这些处理器的分配方式。
job processor length count
--- --------- ------ -----
100 1 100 1
60 2 60 1
50 2 110 2
6 1 106 2
4 1 110 3
1 2 111 3
分析函数和分层查询的某种组合似乎可以实现这一点,而无需诉诸过程代码。预先感谢您的想法和帮助。
您可以使用递归 CTE:
with tt as (
select job, row_number() over (order by job desc) as seqnum
from t
),
cte(job, seqnum, processor, proc1, proc2, lev) as (
select job, seqnum, 1, job as proc1, 0 as proc2, 1
from tt
where seqnum = 1
union all
select tt.job, tt.seqnum,
(case when cte.proc1 > cte.proc2 then 2 else 1 end),
(case when cte.proc1 > cte.proc2 then cte.proc1 else cte.proc1 + tt.job end),
(case when cte.proc1 > cte.proc2 then cte.proc2 + tt.job else cte.proc2 end),
lev + 1
from cte join
tt
on tt.seqnum = cte.seqnum + 1
)
select *
from cte
order by seqnum;
Here 是一个 db<>fiddle.
您可以使用以下类型创建流水线函数:
CREATE TYPE job_processor AS OBJECT(
job NUMBER,
processor NUMBER
);
CREATE TYPE job_processor_list AS TABLE OF job_processor;
那么函数就是:
CREATE FUNCTION partition_jobs (
num_processors IN PLS_INTEGER
) RETURN job_processor_list PIPELINED
IS
processor_time SYS.ODCINUMBERLIST := SYS.ODCINUMBERLIST();
processor_id PLS_INTEGER;
min_processor_time TABLE_NAME.JOB%TYPE;
BEGIN
processor_time.EXTEND( num_processors );
FOR i IN 1 .. num_processors LOOP
processor_time(i) := 0;
END LOOP;
FOR j IN ( SELECT job FROM table_name ORDER BY job DESC ) LOOP
processor_id := 1;
min_processor_time := processor_time( processor_id );
FOR i IN 2 .. num_processors LOOP
IF processor_time(i) < min_processor_time THEN
processor_id := i;
min_processor_time := processor_time( processor_id );
END IF;
END LOOP;
PIPE ROW ( job_processor( j.job, processor_id ) );
processor_time( processor_id ) := processor_time( processor_id ) + j.job;
END LOOP;
END;
/
其中,对于示例数据:
CREATE TABLE TABLE_NAME ( job ) AS
SELECT 4 FROM DUAL UNION ALL
SELECT 60 FROM DUAL UNION ALL
SELECT 50 FROM DUAL UNION ALL
SELECT 1 FROM DUAL UNION ALL
SELECT 100 FROM DUAL UNION ALL
SELECT 6 FROM DUAL;
然后:
SELECT *
FROM TABLE( partition_jobs( 2 ) );
输出:
JOB | PROCESSOR --: | --------: 100 | 1 60 | 2 50 | 2 6 | 1 4 | 1 1 | 1
和:
SELECT *
FROM TABLE( partition_jobs( 3 ) );
输出:
JOB | PROCESSOR --: | --------: 100 | 1 60 | 2 50 | 3 6 | 3 4 | 3 1 | 2
db<>fiddle here