程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> MySQL分頁優化

MySQL分頁優化

編輯:MySQL綜合教程

MySQL分頁優化。本站提示廣大學習愛好者:(MySQL分頁優化)文章只能為提供參考,不一定能成為您想要的結果。以下是MySQL分頁優化正文


比來,幫同事重寫了一個MySQL SQL語句,該SQL語句觸及兩張表,個中一張表是字典表(需前往一個字段),另外一張表是營業表(自己就有150個字段,需全體前往),固然,字段的個數能否公道在這裡不予評價。日常平凡,前往的數據年夜概5w閣下,體系尚能收到數據。但12月31日那天,數據量年夜概20w,招致SQL履行時光太長,未能在劃定的時光內反應成果,因而體系直接報錯。

普通的思緒是用MySQL的分頁功效,即直接在原SQL語句前面增長LIMIT子句。但請留意,固然你看到的反應成果只是LIMIT前面指定的數目,因而想固然的認為MySQL只是檢索了指定命量的數據,然後賜與前往。其實,MySQL外部完成的道理是,檢索一切相符where前提的記載,然後前往指定命量的記載。從這個角度來看,直接在原SQL語句前面添加LIMIT子句只能說是一種可以完成功效的計劃,但未必最優。

詳細在本例中,起首我們來看一下150個字段的表的統計信息:

一行年夜概就占2k,而Innodb默許頁的年夜小為16k,這意味著,一個頁中最多可存儲8行的數據。隨機讀的能夠性年夜年夜增長。而這無疑會對數據庫體系的IO形成極年夜的壓力。 

優化前

假如采取上述計劃,即直接在原SQL語句前面增長LIMIT子句,上面,我們來看看它的履行情形。

起首,直接添加LIMIT子句後的SQL語句以下(已省略a1表的150個字段和a2中的一個字段):

FROM upay_csys_scquery_txn_log_his a1  LEFT JOIN upay_csys_trans_code a2 on(a1.int_trans_code=a2.trans_code) WHERE STATUS<>'00' AND settle_date=20151230 limit 50000,10000;
其履行時光以下:

年夜概履行了32s,絕年夜部門都消費到Sending data上了。Sending data指的是辦事器檢索數據,讀取數據,並將數據前往給客戶真個時光。

關於上述履行成果,有以下幾點須要解釋:

1. 這是SQL語句屢次履行後的成果,如許便可以消除成果緩存的影響,現實上,每次查詢的時長都是32s閣下。

2. 為何選用的是limit 50000,10000,而不是0,10000,這個重要是斟酌到關於LIMIT子句來講,越到前面,分頁的本錢越高。基於此,選擇了中央值來作為分頁的成果。

該語句的履行籌劃以下:

優化後:

優化的思緒:

只對該表的主鍵停止分頁,然後用前往的主鍵作為子查詢的成果,來檢索該表其它字段的值。

改寫後的SQL語句以下:

FROM upay_csys_scquery_txn_log_his a1  LEFT JOIN upay_csys_trans_code a2 on(a1.int_trans_code=a2.trans_code) where seq_id in (select seq_id from (select seq_id FROM upay_csys_scquery_txn_log_his a1  WHERE STATUS<>'00' AND settle_date=20151230 order by 1 limit 50000,10000) as t);
其履行時光以下:

年夜概3s多,比第一種計劃快了差不多10倍,後果明顯。

上面來看看其履行籌劃(explain extended)

 總結:

1. 改寫後的語句本來以下:

FROM upay_csys_scquery_txn_log_his a1  LEFT JOIN upay_csys_trans_code a2 on(a1.int_trans_code=a2.trans_code) where seq_id in (select seq_id FROM upay_csys_scquery_txn_log_his a1  WHERE STATUS<>'00' AND settle_date=20151230 order by 1 limit 50000,10000);
但MySQL報以下毛病:

ERROR 1235 (42000): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
需再增長一個嵌套子查詢,

好比如許的語句是不克不及准確履行的。
select * from table where id in (select id from table limit 12);

然則,只需你再加一層就行。如:
select * from table where id in (select t.id from (select * from table limit 12)as t)

如許便可以繞開limit子查詢的成績。
成績處理。

2. 假如想檢查MySQL查詢優化器等價改寫後的SQL語句,可起首經由過程explain extended獲得詳細的履行籌劃,然後經由過程show warnings檢查。

詳細在本例中,等價改寫後的SQL語句以下:

與假想中的履行次序分歧~

3. 若何檢查MySQL語句各步調的履行時光。

以上就是本文的全體內容,願望對年夜家MySQL分頁優化有所贊助。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved