* db에 데이터 넣기
- 초안
- 문제 : connection timeout error
-- User 테이블 생성
CREATE TABLE IF NOT EXISTS `User` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`nickname` VARCHAR(30) NOT NULL,
`rank` INT NOT NULL CHECK (`rank` BETWEEN 1 AND 10),
`money` BIGINT NOT NULL CHECK (`money` BETWEEN 1 AND 99999999),
`start_date` DATE NOT NULL,
`last_login` DATETIME
);
-- 인덱스 생성
CREATE INDEX idx_user_rank ON `User`(`rank`);
CREATE INDEX idx_user_money ON `User`(`money`);
CREATE INDEX idx_user_start_date ON `User`(`start_date`);
CREATE INDEX idx_user_nickname ON `User`(`nickname`);
DELIMITER //
CREATE FUNCTION random_korean_name() RETURNS VARCHAR(30)
NOT DETERMINISTIC
NO SQL
BEGIN
DECLARE surnames VARCHAR(100) DEFAULT '김,이,박,최,정,강,조,윤,장,임';
DECLARE names VARCHAR(200) DEFAULT '준,민,서,예,지,현,우,아,은,진,선,영,주,혜,성,민,정,수,윤,태';
DECLARE surname VARCHAR(10);
DECLARE name1 VARCHAR(10);
DECLARE name2 VARCHAR(10);
SET surname = SUBSTRING_INDEX(SUBSTRING_INDEX(surnames, ',', FLOOR(1 + RAND() * 10)), ',', -1);
SET name1 = SUBSTRING_INDEX(SUBSTRING_INDEX(names, ',', FLOOR(1 + RAND() * 20)), ',', -1);
SET name2 = SUBSTRING_INDEX(SUBSTRING_INDEX(names, ',', FLOOR(1 + RAND() * 20)), ',', -1);
RETURN CONCAT(surname, name1, name2);
END //
DELIMITER ;
-- 랜덤 데이터 생성 및 삽입을 위한 프로시저
DELIMITER //
CREATE PROCEDURE generate_user_data(IN num_records INT)
BEGIN
DECLARE i INT DEFAULT 0;
WHILE i < num_records DO
INSERT INTO `User` (nickname, `rank`, money, start_date, last_login)
VALUES (
random_korean_name(),
FLOOR(1 + RAND() * 10),
FLOOR(1 + RAND() * 99999999),
DATE_SUB(CURDATE(), INTERVAL FLOOR(RAND() * 365 * 3) DAY),
IF(RAND() < 0.8,
DATE_SUB(NOW(), INTERVAL FLOOR(RAND() * 180) DAY),
NULL)
);
SET i = i + 1;
END WHILE;
END //
DELIMITER ;
-- 데이터 생성 실행
CALL generate_user_data(3000);
-- 통계 업데이트
ANALYZE TABLE `User`;
- 개선
-- 1. 임시 테이블 생성
CREATE TABLE IF NOT EXISTS `User_Temp` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`nickname` VARCHAR(30) NOT NULL,
`rank` INT NOT NULL,
`money` BIGINT NOT NULL,
`start_date` DATE NOT NULL,
`last_login` DATETIME
) ENGINE=InnoDB;
-- 2. 랜덤 데이터 생성 및 삽입을 위한 프로시저
DELIMITER //
CREATE PROCEDURE generate_user_data_optimized(IN num_records INT, IN batch_size INT)
BEGIN
DECLARE i INT DEFAULT 0;
-- 트랜잭션 시작
START TRANSACTION;
WHILE i < num_records DO
INSERT INTO `User_Temp` (nickname, `rank`, money, start_date, last_login)
SELECT
random_korean_name(),
FLOOR(1 + RAND() * 10),
FLOOR(1 + RAND() * 99999999),
DATE_SUB(CURDATE(), INTERVAL FLOOR(RAND() * 365 * 3) DAY),
IF(RAND() < 0.8,
DATE_SUB(NOW(), INTERVAL FLOOR(RAND() * 180) DAY),
NULL)
FROM (SELECT @rn:=@rn+1 AS rn FROM (SELECT @rn:=0) AS r,
information_schema.columns LIMIT batch_size) AS t
WHERE t.rn <= batch_size;
SET i = i + batch_size;
-- 일정 간격으로 커밋
IF i % (batch_sizeid * 10) = 0 THEN
COMMIT;
START TRANSACTION;
END IF;
END WHILE;
-- 남은 데이터 커밋
COMMIT;
END //
DELIMITER ;
-- 3. 데이터 생성 실행 (배치 크기: 10000)
CALL generate_user_data_optimized(3000000, 5000);
-- 4. 임시 테이블에서 실제 테이블로 데이터 이동
INSERT INTO `User` SELECT * FROM `User_Temp`;
-- 5. 임시 테이블 삭제
DROP TABLE `User_Temp`;
-- 6. 통계 업데이트
ANALYZE TABLE `User`;
- 마스터클래스 내용
- 프로시저보다는 파이썬이나 js를 이용하는게 좋음
- 이유 : 프로시저는 컴파일후 실행이 아니므로 느림
- UNIQUE 제약조건 이 걸린 행 -> 자동 indexing된다.
- bulk insert등을 실행하면 빨리 넣을수있다. (insert문 모아서 보내기)
'CS > DB' 카테고리의 다른 글
[Redis] Redis 사용방법, 세션 불일치 해결 (0) | 2024.11.03 |
---|---|
[Redis] Redis를 이용한 db 접근횟수 줄이기 (0) | 2024.10.20 |
24.9.10. 개발일지 // 인증미들웨어, 트랙잭션, 암호화 (0) | 2024.09.11 |
[DB] db관점 정렬 학습 by.line (0) | 2024.08.29 |
[DB] DATETIME 타입에 DEFAULT 값으로 현재 시간 입력 (0) | 2024.08.27 |