婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > MySQL 百萬級數據的4種查詢優化方式

MySQL 百萬級數據的4種查詢優化方式

熱門標簽:html地圖標注并導航 400電話變更申請 催天下外呼系統 大豐地圖標注app 400電話辦理服務價格最實惠 呂梁外呼系統 南太平洋地圖標注 武漢電銷機器人電話 北京金倫外呼系統

一.limit越往后越慢的原因

當我們使用limit來對數據進行分頁操作的時,會發現:查看前幾頁的時候,發現速度非常快,比如 limit 200,25,瞬間就出來了。但是越往后,速度就越慢,特別是百萬條之后,卡到不行,那這個是什么原理呢。先看一下我們翻頁翻到后面時,查詢的sql是怎樣的:

select * from t_name where c_name1='xxx' order by c_name2 limit 2000000,25;

這種查詢的慢,其實是因為limit后面的偏移量太大導致的。比如像上面的 limit 2000000,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萬條數據可能很慢

三.4種查詢方式

1.普通limit分頁

/*偏移量為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 百萬級數據查詢優化的資料請關注腳本之家其它相關文章!

您可能感興趣的文章:
  • mysql 數據插入優化方法之concurrent_insert
  • mysql優化之query_cache_limit參數說明
  • 如何使用分區處理MySQL的億級數據優化
  • MySQL優化之如何寫出高質量sql語句
  • 帶你快速搞定Mysql優化

標簽:迪慶 西寧 自貢 龍巖 麗水 徐州 無錫 南充

巨人網絡通訊聲明:本文標題《MySQL 百萬級數據的4種查詢優化方式》,本文關鍵詞  MySQL,百萬,級,數據,的,4種,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《MySQL 百萬級數據的4種查詢優化方式》相關的同類信息!
  • 本頁收集關于MySQL 百萬級數據的4種查詢優化方式的相關信息資訊供網民參考!
  • 推薦文章
    主站蜘蛛池模板: 建平县| 南投县| 桐柏县| 奉新县| 柘城县| 隆尧县| 张家港市| 鄂尔多斯市| 房产| 博客| 廉江市| 屏东县| 太保市| 南京市| 马公市| 城市| 新民市| 洪湖市| 新密市| 民乐县| 麻栗坡县| 登封市| 鱼台县| 高州市| 兰西县| 富裕县| 柘荣县| 河曲县| 邯郸市| 香河县| 万年县| 格尔木市| 贵州省| 根河市| 梁平县| 和田县| 连城县| 涟源市| 长沙县| 惠水县| 博野县|