MySQL 백만 급 데이터 의 4 가지 조회 최적화 방식
우리 가 limit 을 사용 하여 데 이 터 를 페이지 별로 조작 할 때 앞의 몇 페이지 를 볼 때 속도 가 매우 빠르다 는 것 을 발견 할 수 있다.예 를 들 어 limit 200,25,순간 에 나 왔 다.하지만 뒤로 갈수 록 속도 가 느 려 집 니 다.특히 백만 개가 지나 면 걸 리 지 않 습 니 다.그럼 이 원 리 는 무엇 입 니까?먼저 우리 가 페이지 를 뒤로 넘 겼 을 때 조회 한 sql 이 어떤 지 보 세 요.
select * from t_name where c_name1='xxx' order by c_name2 limit 2000000,25;
이런 조회 가 느 린 것 은 사실 limit 뒤의 오프셋 이 너무 많아 서 생 긴 것 이다.예 를 들 어 위의 limit 20000,25 와 같이 이것 은 데이터베이스 에서 2000025 개의 데 이 터 를 스 캔 한 다음 에 앞의 20000000 개의 데 이 터 를 버 리 고 나머지 25 개의 데 이 터 를 사용자 에 게 되 돌려 주 는 것 과 같다.이런 취 법 은 현저히 불합리 하 다.백만 데이터 시 뮬 레이 션
1.직원 표 와 부서 표를 만 들 고 저장 과정 을 작성 하여 데 이 터 를 삽입 합 니 다.
/* , */
drop table if EXISTS dep;
create table dep(
id int unsigned primary key auto_increment,
depno mediumint unsigned not null default 0,
depname varchar(20) not null default "",
memo varchar(200) not null default ""
);
/* , */
drop table if EXISTS emp;
create table emp(
id int unsigned primary key auto_increment,
empno mediumint unsigned not null default 0,
empname varchar(20) not null default "",
job varchar(9) not null default "",
mgr mediumint unsigned not null default 0,
hiredate datetime not null,
sal decimal(7,2) not null,
comn decimal(7,2) not null,
depno mediumint unsigned not null default 0
);
/* */
DELIMITER $
drop FUNCTION if EXISTS rand_string;
CREATE FUNCTION rand_string(n INT) RETURNS VARCHAR(255)
BEGIN
DECLARE chars_str VARCHAR(100) DEFAULT 'abcdefghijklmlopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
DECLARE return_str VARCHAR(255) DEFAULT '';
DECLARE i INT DEFAULT 0;
WHILE i < n DO
SET return_str = CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1));
SET i = i+1;
END WHILE;
RETURN return_str;
END $
DELIMITER;
/* */
DELIMITER $
drop FUNCTION if EXISTS rand_num;
CREATE FUNCTION rand_num() RETURNS INT(5)
BEGIN
DECLARE i INT DEFAULT 0;
SET i = FLOOR(100+RAND()*10);
RETURN i;
END $
DELIMITER;
/* : emp */
DELIMITER $
drop PROCEDURE if EXISTS insert_emp;
CREATE PROCEDURE insert_emp(IN START INT(10),IN max_num INT(10))
BEGIN
DECLARE i INT DEFAULT 0;
/*set autocommit =0 autocommit 0, */
SET autocommit = 0;
REPEAT
SET i = i + 1;
INSERT INTO emp(empno,empname,job,mgr,hiredate,sal,comn,depno) VALUES ((START+i),rand_string(6),'SALEMAN',0001,now(),2000,400,rand_num());
UNTIL i = max_num
END REPEAT;
COMMIT;
END $
DELIMITER;
/* : dep */
DELIMITER $
drop PROCEDURE if EXISTS insert_dept;
CREATE PROCEDURE insert_dept(IN START INT(10),IN max_num INT(10))
BEGIN
DECLARE i INT DEFAULT 0;
SET autocommit = 0;
REPEAT
SET i = i+1;
INSERT INTO dep( depno,depname,memo) VALUES((START+i),rand_string(10),rand_string(8));
UNTIL i = max_num
END REPEAT;
COMMIT;
END $
DELIMITER;
2.저장 프로시저 실행
/* 120 */
call insert_dept(1,120);
/* 500W */
call insert_emp(0,5000000);
500 만 개의 데 이 터 를 삽입 하 는 것 은 느 릴 수 있 습 니 다.3.4 가지 조회 방식
1.일반 제한 페이지
/* 100, 25*/
SELECT a.empno,a.empname,a.job,a.sal,b.depno,b.depname
from emp a left join dep b on a.depno = b.depno order by a.id desc limit 100,25;
/* 4800000, 25*/
SELECT a.empno,a.empname,a.job,a.sal,b.depno,b.depname
from emp a left join dep b on a.depno = b.depno order by a.id desc limit 4800000,25;
실행 결과
[SQL]
SELECT a.empno,a.empname,a.job,a.sal,b.depno,b.depname
from emp a left join dep b on a.depno = b.depno order by a.id desc limit 100,25;
: 0
: 0.001s
[SQL]
SELECT a.empno,a.empname,a.job,a.sal,b.depno,b.depname
from emp a left join dep b on a.depno = b.depno order by a.id desc limit 4800000,25;
: 0
: 12.275s
뒤로 갈수 록 조회 효율 이 느리다2.색인 덮어 쓰기+하위 검색 최적화 사용
홈 키 id 가 있 고 위 에 색인 을 만 들 었 기 때문에 색인 트 리 에서 시작 위치의 id 값 을 찾 은 다음 에 찾 은 id 값 에 따라 줄 데 이 터 를 조회 할 수 있 습 니 다.
/* 100 id, 25*/
SELECT a.empno,a.empname,a.job,a.sal,b.depno,b.depname
from emp a left join dep b on a.depno = b.depno
where a.id >= (select id from emp order by id limit 100,1)
order by a.id limit 25;
/* 4800000 id, 25*/
SELECT a.empno,a.empname,a.job,a.sal,b.depno,b.depname
from emp a left join dep b on a.depno = b.depno
where a.id >= (select id from emp order by id limit 4800000,1)
order by a.id limit 25;
실행 결과
[SQL]
SELECT a.empno,a.empname,a.job,a.sal,b.depno,b.depname
from emp a left join dep b on a.depno = b.depno
where a.id >= (select id from emp order by id limit 100,1)
order by a.id limit 25;
: 0
: 0.106s
[SQL]
SELECT a.empno,a.empname,a.job,a.sal,b.depno,b.depname
from emp a left join dep b on a.depno = b.depno
where a.id >= (select id from emp order by id limit 4800000,1)
order by a.id limit 25;
: 0
: 1.541s
3.시작 위치 재 정의홈 키 에 적용 되 는 것 은 홈 키 를 추가 하 는 표 입 니 다.
/* id 100, 100, 101 */
SELECT a.id,a.empno,a.empname,a.job,a.sal,b.depno,b.depname
from emp a left join dep b on a.depno = b.depno
where a.id > 100 order by a.id limit 25;
/* id 4800000, 4800000, 4800001 */
SELECT a.id,a.empno,a.empname,a.job,a.sal,b.depno,b.depname
from emp a left join dep b on a.depno = b.depno
where a.id > 4800000
order by a.id limit 25;
[SQL]
SELECT a.id,a.empno,a.empname,a.job,a.sal,b.depno,b.depname
from emp a left join dep b on a.depno = b.depno
where a.id > 100 order by a.id limit 25;
: 0
: 0.001s
[SQL]
SELECT a.id,a.empno,a.empname,a.job,a.sal,b.depno,b.depname
from emp a left join dep b on a.depno = b.depno
where a.id > 4800000
order by a.id limit 25;
: 0
: 0.000s
이 효율 은 가장 좋다.아무리 페이지 를 나 누 어도 시간 이 거의 일치한다.왜냐하면 그 는 조건 을 실행 한 후에 25 개의 데이터 만 스 캔 했 기 때문이다.4.강등 전략(바 이 두 의 방법)
이 정책 은 가장 간단 하고 효과 적 입 니 다.일반적인 빅 데이터 조회 에는 검색 조건 이 있 기 때문에 100 페이지 이후 의 내용 에 관심 을 가 지 는 사람 이 없습니다.사용자 가 페이지 수 를 너무 많 을 때 오 류 를 되 돌려 주면 됩 니 다.예 를 들 어 바 이 두 는 76 페이지 만 검색 할 수 있 습 니 다.
이상 은 MySQL 백만 급 데이터 의 4 가지 조회 최적화 방식 의 상세 한 내용 입 니 다.MySQL 백만 급 데이터 조회 최적화 에 관 한 자 료 는 우리 의 다른 관련 글 을 주목 하 세 요!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Redash를 사용할 때 몰랐던 SQL을 쓰는 법을 배웠습니다.최근 redash에서 sql을 쓸 기회가 많고, 이런 쓰는 방법이 있었는지와 sql에 대해 공부를 다시하고 있기 때문에 배운 것을 여기에 씁니다. Redash란? 월별로 데이터를 표시하고 싶습니다 주별로 데이터를 표...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.