MySQL的分頁優化

来源:http://www.cnblogs.com/ivictor/archive/2016/01/04/5099870.html
-Advertisement-
Play Games

今天下午,幫同事重寫了一個MySQL SQL語句,該SQL語句涉及兩張表,其中一張表是字典表(需返回一個欄位),另一張表是業務表(本身就有150個欄位,需全部返回),當然,欄位的個數是否合理在這裡不予評價。平時,返回的數據大概5w左右,系統尚能收到數據。但12月31日那天,數據量大概20w,導致SQ...


今天下午,幫同事重寫了一個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語句各步驟的執行時間,可參考:http://www.cnblogs.com/ivictor/p/5085965.html

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 什麼是跨站請求偽造(CSRF) CSRF(Cross-site request forgery跨站請求偽造,也被稱為“One Click Attack”或者Session Riding,通常縮寫為CSRF或者XSRF,是一種對網站的惡意利用。儘管聽起來像跨站腳本(XSS),但它與XSS非常不同...
  • string str5=Application.StartupPath;//獲取啟動了應用程式的可執行文件的路徑,不包括可執行文件的名稱。string str1 =Process.GetCurrentProcess().MainModule.FileName;//可獲得當前執行的exe的文件名。st...
  • 一.Ajax介紹 Ajax是2005年2月才誕生但是現在已經炙手可熱的一項全新技術.這項新技術能夠極大地改善網站的用戶體驗. 什麼是Ajax Ajax是非同步Javascript和XML(Asynchronous JavaScript and XML)的英文縮寫. Ajax的核心理...
  • /// /// 根據年月日計算星期幾/// /// 年/// 月/// 日/// publicstaticstringCaculateWeekDay(inty,intm,intd){if(m == 1) m = 13;if(m == 2) m = 14;intweek = (d + 2 * m + ...
  • 如題目所示,本文要來聊一聊在游戲開發中經常會涉及到的話題——游戲AI。設計游戲AI的目標之一是要找到一種便於使用並容易拓展的的方案,常見的一些游戲AI方案包括了有限狀態機(FSM)、分層有限狀態機(HFSM)、面向目標的動作規劃(GOAP)以及分層任務網路(HTN)和行為樹(BT)等等。下麵我們就來...
  • 1.新建一個頁面,ImageCode.aspx2.在Page_Load中添加如下代碼string tmp = RndNum(4); HttpCookie a = new HttpCookie("ImageV ", tmp); Respo...
  • 存儲管理子系統(DFSMS)存儲管理也是系統的一項基本服務。系統存儲管理子系統(Storage Management System,SMS)定義了系統中的各種輸入/輸出設備,並控制這些設備的操作;同時,它還提供文件系統的基本功能,使用戶可以方便、快速地訪問數據。系統的各種程式及數據都保存在硬碟上,如...
  • 一.TCP/IP協議族 TCP/IP是一個協議族,通常分不同層次進行開發,每個層次負責不同的通信功能。包含以下四個層次:1. 鏈路層,也稱作數據鏈路層或者網路介面層,通常包括操作系統中的設備驅動程式和電腦中對應的網路介面卡。它們一起處理與電纜(或其他任何傳輸媒介)的物理介面細節。2. 網路層,.....
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...