-- 한 문장씩 차례대로 실행하는 것을 권장합니다.
-- 컴퓨터와 MySQL 설정에 따라 많은 시간이 걸릴 수 있습니다.
USE startdbmy;
-- -----------------------------------------------------------------------
-- 튜닝용 테이블 제거
-- -----------------------------------------------------------------------
DROP TABLE IF EXISTS startdbmy.ms_mbr_big;
DROP TABLE IF EXISTS startdbmy.ms_shop_big;
DROP TABLE IF EXISTS startdbmy.tr_ord_big_tmp;
DROP TABLE IF EXISTS startdbmy.tr_ord_big;
DROP TABLE IF EXISTS startdbmy.tr_ord_det_big;
DROP TABLE IF EXISTS startdbmy.tr_event_entry_big
-- -----------------------------------------------------------------------
-- 튜닝용 테이블 생성(startuppg DB에 접속해서 실행해야함)
-- -----------------------------------------------------------------------
CREATE TABLE startdbmy.ms_shop_big
(
shop_id VARCHAR(40) NOT NULL
,shop_nm VARCHAR(100) NULL
,shop_size INTEGER NULL
,shop_oper_tp VARCHAR(40) NULL
,table_qty INTEGER NULL
,chair_qty INTEGER NULL
,open_time VARCHAR(100) NULL
,close_time VARCHAR(100) NULL
,shop_st VARCHAR(40) NULL
,shop_start_ymd VARCHAR(8) NULL
,shop_end_ymd VARCHAR(8) NULL
);
CREATE TABLE startdbmy.ms_mbr_big
(
mbr_id VARCHAR(40) NOT NULL
,nick_nm VARCHAR(100) NULL
,mobl_no VARCHAR(100) NULL
,emal_adr VARCHAR(100) NULL
,join_dtm DATETIME NULL
,join_tp VARCHAR(40) NULL
,mbr_gd VARCHAR(40) NULL
,mbr_st VARCHAR(40) NULL
,leave_dtm DATETIME NULL
);
CREATE TABLE startdbmy.tr_ord_big_tmp
( ord_no BIGINT NOT NULL
,ord_dtm DATETIME NULL
,prep_cmp_dtm DATETIME NULL
,pkup_dtm DATETIME NULL
,mbr_id VARCHAR (40) NULL
,shop_id VARCHAR (40) NULL
,ord_st VARCHAR (40) NULL
,ord_amt DECIMAL (18,3) NULL
,pay_tp VARCHAR (40) NULL
,PRIMARY KEY (ord_no)
);
CREATE TABLE startdbmy.tr_ord_big
( ord_no BIGINT UNSIGNED NOT NULL
,ord_dtm DATETIME NULL
,ord_ymd VARCHAR(8) NULL
,prep_cmp_dtm DATETIME NULL
,pkup_dtm DATETIME NULL
,mbr_id VARCHAR (40) NULL
,shop_id VARCHAR (40) NULL
,ord_st VARCHAR (40) NULL
,ord_amt DECIMAL (18,3) NULL
,pay_tp VARCHAR (40) NULL
,PRIMARY KEY (ord_no)
);
CREATE TABLE startdbmy.tr_ord_det_big
( ord_no BIGINT UNSIGNED NOT NULL
,ord_det_no INTEGER NOT NULL
,item_id VARCHAR (40) NULL
,ord_qty DECIMAL (10,0) NULL
,sale_prc DECIMAL (18,3) NULL
,PRIMARY KEY(ord_no, ord_det_no)
);
CREATE TABLE startdbmy.tr_event_entry_big
( event_id VARCHAR(40) NOT NULL
,entry_no INTEGER NOT NULL
,shop_id VARCHAR(40) NOT NULL
,mbr_id VARCHAR(40) NOT NULL
,entry_dtm DATETIME NOT NULL
,entry_rslt_cd VARCHAR(40) NOT NULL
,entry_rslt_dtm DATETIME NOT NULL
);
-- -----------------------------------------------------------------------
-- ms_shop -> startdbmy.ms_shop_big 생성
-- -----------------------------------------------------------------------
INSERT INTO startdbmy.ms_shop_big
(
shop_id
,shop_nm
,shop_size
,shop_oper_tp
,table_qty
,chair_qty
,open_time
,close_time
,shop_st
,shop_start_ymd
,shop_end_ymd
)
SELECT shop_id
,shop_nm
,shop_size
,shop_oper_tp
,table_qty
,chair_qty
,open_time
,close_time
,shop_st
,shop_start_ymd
,shop_end_ymd
FROM startdbmy.ms_shop;
-- -----------------------------------------------------------------------
-- ms_mbr -> startdbmy.ms_mbr_big 생성
-- -----------------------------------------------------------------------
INSERT INTO startdbmy.ms_mbr_big
(mbr_id ,nick_nm ,mobl_no ,emal_adr ,join_dtm, join_tp, mbr_gd ,mbr_st, leave_dtm)
SELECT CONCAT('M' , LPAD(t1.rno,5,'0'))
,CONCAT(t1.nick_nm ,
CASE WHEN t1.rno_by_mbr = 0 THEN ''
ELSE CONCAT('-' , t1.rno_by_mbr) END) nick_nm
,CONCAT('100' , LPAD(t1.rno,5,'0')) mobl_no
,CONCAT(LPAD(t1.rno,5,'0') , '@gm.com') emal_adr
,DATE_SUB(t1.join_dtm, INTERVAL (t1.rno_by_mbr + MOD(t1.rno, 60)) DAY) join_dtm
,CASE WHEN MOD(rno,10) <= 6 THEN 'DRCT'
WHEN MOD(rno,10) <= 8 THEN 'SNS'
ELSE 'INV' END join_tp
,t1.mbr_gd
,t1.mbr_st
,t1.leave_dtm
FROM (
SELECT t1.mbr_id
,t1.nick_nm
,t1.mobl_no
-- 위에서 신규로 부여 ,t1.emal_adr
,t1.join_dtm
,t1.mbr_gd
,t1.mbr_st
,t1.leave_dtm
,ROW_NUMBER() OVER(ORDER BY t1.mbr_id ,t2.rno) rno
,ROW_NUMBER() OVER(PARTITION BY t1.mbr_id ORDER BY t2.rno asc)-1 rno_by_mbr
FROM startdbmy.ms_mbr t1
,(SELECT ROW_NUMBER() OVER() - 1 rno
FROM startdbmy.ms_mbr LIMIT 10) t2
) t1;
-- -----------------------------------------------------------------------
-- startdbmy.tr_ord_big_tmp 데이터 생성 프로시저 생성(월별로 반복 실행되는 프로시저)
-- 다른 SQL과 같이 실행하면 정상적으로 생성안될수 있음. 별도 창에서 Alt+x로 단독 실행을 권장함.
-- -----------------------------------------------------------------------
DELIMITER $$;
CREATE PROCEDURE startdbmy.usp_insert_tr_ord_big_tmp()
BEGIN
-- 커서 관련 변수
DECLARE v_yyyymm CHAR(6);
DECLARE done INT DEFAULT FALSE;
-- 커서 선언: 월별(YYYYMM) 목록
DECLARE curs CURSOR FOR
SELECT DATE_FORMAT(ord_dtm, '%Y%m') AS yyyymm
FROM startdbmy.tr_ord
GROUP BY DATE_FORMAT(ord_dtm, '%Y%m')
ORDER BY DATE_FORMAT(ord_dtm, '%Y%m');
-- NOT FOUND 시 done 플래그 세팅
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-- 커서 오픈
OPEN curs;
-- LOOP 시작
read_loop: LOOP
FETCH curs INTO v_yyyymm;
IF done THEN
LEAVE read_loop;
END IF;
-- 실제 Insert 로직
INSERT INTO startdbmy.tr_ord_big_tmp
(ord_no
,ord_dtm
,prep_cmp_dtm
,pkup_dtm
,mbr_id
,shop_id
,ord_st
,ord_amt
,pay_tp
)
SELECT /*+ SET_VAR(sort_buffer_size=512M) */
ROW_NUMBER() OVER (ORDER BY T3.new_ord_dtm, T3.shop_id, T3.new_mbr_id)
+ COALESCE(
(SELECT MAX(x.ord_no) FROM startdbmy.tr_ord_big_tmp x),
0
) AS new_ord_no
,T3.new_ord_dtm
,T3.new_prep_cmp_dtm
,T3.new_pkup_dtm
,T3.new_mbr_id
,T3.shop_id
,T3.ord_st
,NULL AS ord_amt
,T3.pay_tp
FROM
(
SELECT
-- second 단위로 더하기
DATE_ADD(t1.ord_dtm, INTERVAL t2.n SECOND) AS new_ord_dtm,
DATE_ADD(t1.prep_cmp_dtm, INTERVAL t2.n SECOND) AS new_prep_cmp_dtm,
DATE_ADD(t1.pkup_dtm, INTERVAL t2.n SECOND) AS new_pkup_dtm,
-- mbr_id 생성 로직 ('M' + right padding)
CONCAT(
'M',
LPAD(
-- ( substring(t1.mbr_id, 2, 4)::integer + (t1.ord_no % 999 + 1) ) * (t2.n + 1) % 99990 + 1
MOD(
(
(CAST(SUBSTR(t1.mbr_id, 2, 4) AS UNSIGNED)
+ (MOD(t1.ord_no, 999) + 1)
) * (t2.n + 1)
),
99990
) + 1,
5,
'0'
)
) AS new_mbr_id,
t1.shop_id,
t1.ord_st,
NULL AS ord_amt,
t1.pay_tp
FROM startdbmy.tr_ord t1
-- generate_series(0,35) → 재귀 CTE 사용
JOIN (
WITH RECURSIVE nums AS (
SELECT 0 AS n
UNION ALL
SELECT n + 1 FROM nums WHERE n < 35
)
SELECT n FROM nums
) t2 ON 1=1
WHERE
t1.ord_dtm >= STR_TO_DATE(CONCAT(v_yyyymm,'01'), '%Y%m%d')
AND t1.ord_dtm < DATE_ADD(STR_TO_DATE(CONCAT(v_yyyymm,'01'), '%Y%m%d'), INTERVAL 1 MONTH)
) T3;
-- 월별 처리 후 COMMIT
COMMIT;
END LOOP;
-- 커서 종료
CLOSE curs;
END$$
DELIMITER ;
-- -----------------------------------------------------------------------
-- startdbmy.tr_ord_big_tmp 데이터 생성 프로시저 실행
-- -----------------------------------------------------------------------
CALL startdbmy.usp_insert_tr_ord_big_tmp();
-- -----------------------------------------------------------------------
-- startdbmy.tr_ord_big_tmp -> startdbmy.tr_ord_det_big 데이터 생성
-- -----------------------------------------------------------------------
-- 14분.
INSERT INTO startdbmy.tr_ord_det_big(ord_no, ord_det_no, item_id, ord_qty, sale_prc)
SELECT /*+ SET_VAR(sort_buffer_size=512M) */
t1.ord_no,
ROW_NUMBER() OVER(PARTITION BY t1.ord_no ORDER BY t1.item_id) AS ord_det_no,
t1.item_id,
SUM(t1.ord_qty) AS ord_qty,
MAX(t1.sale_prc) AS sale_prc
FROM
(
SELECT
T1.ord_no,
1 AS ord_det_no,
T2.item_id,
1 AS ord_qty,
T2.sale_prc
FROM startdbmy.tr_ord_big_tmp T1
INNER JOIN
(
SELECT
t1.item_id,
t1.prc_start_dt,
t1.prc_end_dt,
ROW_NUMBER() OVER(ORDER BY t1.prc_start_dt, t1.prc_end_dt, t1.item_id) AS item_no,
t1.sale_prc
FROM startdbmy.ms_item_prc_hist t1
WHERE t1.item_id IN ('AMB','AMR','IAMB','IAMR','CLB','CLR','ICLB','ICLR')
AND t1.prc_start_dt < '2023-01-01'
) T2 ON (T2.item_no = MOD(T1.ord_no, 8) + 1)
WHERE T1.ord_dtm >= T2.prc_start_dt
AND T1.ord_dtm < DATE_ADD(T2.prc_end_dt, INTERVAL 1 DAY)
AND T1.ord_dtm < '2023-01-01'
UNION ALL
SELECT
T1.ord_no,
2 AS ord_det_no,
T2.item_id,
1 AS ord_qty,
T2.sale_prc
FROM startdbmy.tr_ord_big_tmp T1
INNER JOIN
(
SELECT
t1.item_id,
t1.prc_start_dt,
t1.prc_end_dt,
ROW_NUMBER() OVER(ORDER BY t1.item_id DESC, t1.prc_start_dt, t1.prc_end_dt) AS item_no,
t1.sale_prc
FROM startdbmy.ms_item_prc_hist t1
) T2 ON (T2.item_no = MOD(T1.ord_no, 44) + 1)
WHERE T1.ord_dtm >= T2.prc_start_dt
AND T1.ord_dtm < DATE_ADD(T2.prc_end_dt, INTERVAL 1 DAY)
AND T1.ord_dtm < '2023-01-01'
) t1
GROUP BY t1.ord_no, t1.item_id;
-- 21분
INSERT INTO startdbmy.tr_ord_det_big(ord_no, ord_det_no, item_id, ord_qty, sale_prc)
SELECT /*+ SET_VAR(sort_buffer_size=512M) */
t1.ord_no,
ROW_NUMBER() OVER(PARTITION BY t1.ord_no ORDER BY t1.item_id) AS ord_det_no,
t1.item_id,
SUM(t1.ord_qty) AS ord_qty,
MAX(t1.sale_prc) AS sale_prc
FROM
(
SELECT
T1.ord_no,
1 AS ord_det_no,
T2.item_id,
1 AS ord_qty,
T2.sale_prc
FROM startdbmy.tr_ord_big_tmp T1
INNER JOIN
(
SELECT
t1.item_id,
t1.prc_start_dt,
t1.prc_end_dt,
ROW_NUMBER() OVER (ORDER BY t1.prc_start_dt, t1.prc_end_dt, t1.item_id) AS item_no,
t1.sale_prc
FROM startdbmy.ms_item_prc_hist t1
WHERE t1.item_id IN ('AMB','AMR','IAMB','IAMR','CLB','CLR','ICLB','ICLR')
AND t1.prc_start_dt >= '2023-01-01'
) T2 ON (T2.item_no = MOD(T1.ord_no, 8) + 1)
WHERE T1.ord_dtm >= T2.prc_start_dt
AND T1.ord_dtm < DATE_ADD(T2.prc_end_dt, INTERVAL 1 DAY)
AND T1.ord_dtm >= '2023-01-01'
UNION ALL
SELECT
T1.ord_no,
2 AS ord_det_no,
T2.item_id,
1 AS ord_qty,
T2.sale_prc
FROM startdbmy.tr_ord_big_tmp T1
INNER JOIN
(
SELECT
t1.item_id,
t1.prc_start_dt,
t1.prc_end_dt,
ROW_NUMBER() OVER (ORDER BY t1.item_id DESC, t1.prc_start_dt, t1.prc_end_dt) AS item_no,
t1.sale_prc
FROM startdbmy.ms_item_prc_hist t1
) T2 ON (T2.item_no = MOD(T1.ord_no, 44) + 1)
WHERE T1.ord_dtm >= T2.prc_start_dt
AND T1.ord_dtm < DATE_ADD(T2.prc_end_dt, INTERVAL 1 DAY)
AND T1.ord_dtm >= '2023-01-01'
) t1
GROUP BY t1.ord_no, t1.item_id;
-- -----------------------------------------------------------------------
-- startdbmy.tr_ord_big_tmp + startdbmy.tr_ord_det_big -> startdbmy.tr_ord_big 데이터 생성
-- -----------------------------------------------------------------------
-- 33분
INSERT INTO startdbmy.tr_ord_big(ord_no,ord_dtm,ord_ymd,prep_cmp_dtm,pkup_dtm,mbr_id,shop_id,ord_st,ord_amt,pay_tp)
SELECT /*+ SET_VAR(sort_buffer_size=512M) */
t1.ord_no ,t1.ord_dtm, DATE_FORMAT(t1.ord_dtm,'%Y%m%d') ord_ymd ,t1.prep_cmp_dtm ,t1.pkup_dtm, t1.mbr_id ,t1.shop_id ,t1.ord_st
,t2.ord_amt ,t1.pay_tp
FROM startdbmy.tr_ord_big_tmp t1
INNER JOIN (
select x.ord_no , sum(x.ord_qty * x.sale_prc) ord_amt
from startdbmy.tr_ord_det_big x
group by x.ord_no
) t2
on (t1.ord_no = t2.ord_no)
;
-- -----------------------------------------------------------------------
-- startdbmy.tr_ord_big_tmp 제거
-- -----------------------------------------------------------------------
DROP TABLE startdbmy.tr_ord_big_tmp;
-- -----------------------------------------------------------------------
-- startdbmy.tr_ord_big -> startdbmy.tr_event_entry_big 생성
-- -----------------------------------------------------------------------
INSERT INTO startdbmy.tr_event_entry_big
(
event_id
,entry_no
,shop_id
,mbr_id
,entry_dtm
,entry_rslt_cd
,entry_rslt_dtm
)
SELECT
t2.event_id,
ROW_NUMBER() OVER (
PARTITION BY t2.event_id
ORDER BY t2.entry_dtm, t2.mbr_id, t2.shop_id
) AS entry_no,
t2.shop_id,
t2.mbr_id,
t2.entry_dtm,
CASE
/* “mmss” 값을 정수로 바꾼 뒤 5로 나눈 나머지로 성공/실패 결정 */
WHEN MOD(CAST(DATE_FORMAT(t2.entry_dtm, '%i%S') AS UNSIGNED), 5) = 0
THEN 'SUCC'
ELSE 'FAIL'
END AS entry_rslt_cd,
/* 해당 시각을 시(00분 00초)에 맞춘 뒤 +30 분 */
TIMESTAMP(DATE_FORMAT(t2.entry_dtm, '%Y-%m-%d %H:00:00'))
+ INTERVAL 30 MINUTE AS entry_rslt_dtm
FROM (
SELECT
CONCAT('EV-', DATE_FORMAT(t1.ord_dtm, '%y%m%d%H')) AS event_id,
MIN(t1.shop_id) AS shop_id,
t1.mbr_id,
MIN(t1.ord_dtm) AS entry_dtm
FROM startdbmy.tr_ord_big AS t1
WHERE DATE_FORMAT(t1.ord_dtm, '%H') BETWEEN '08' AND '20'
GROUP BY
CONCAT('EV-', DATE_FORMAT(t1.ord_dtm, '%y%m%d%H')),
t1.mbr_id
) AS t2;
-- -----------------------------------------------------------------------
-- PK 생성
-- -----------------------------------------------------------------------
ALTER TABLE startdbmy.ms_shop_big ADD CONSTRAINT ms_shop_big_pk PRIMARY KEY(shop_id);
ALTER TABLE startdbmy.ms_mbr_big ADD CONSTRAINT ms_mbr_big_pk PRIMARY KEY(mbr_id);
ALTER TABLE startdbmy.tr_event_entry_big ADD CONSTRAINT tr_event_entry_big_pk PRIMARY KEY(event_id,entry_no);
-- -----------------------------------------------------------------------
-- 통계 생성
-- -----------------------------------------------------------------------
ANALYZE TABLE startdbmy.ms_shop_big;
ANALYZE TABLE startdbmy.ms_mbr_big;
ANALYZE TABLE startdbmy.tr_ord_big;
ANALYZE TABLE startdbmy.tr_ord_det_big;
ANALYZE TABLE startdbmy.tr_event_entry_big;
SQL
복사