記一次mysql千萬訂單彙總查詢優化

来源:http://www.cnblogs.com/wappin/archive/2017/10/27/7725049.html
-Advertisement-
Play Games

公司訂單系統每日訂單量龐大,有很多表數據超千萬。公司SQL優化這塊做的很不好,可以說是沒有做,所以導致查詢很慢。 正題 節選某個功能中的一句SQL EXPLAIN 查看執行計劃 EXPLAIN + SQL 查看SQL執行計劃 一個索引沒用到,受影響行接近2000萬,難怪會慢。 原來的SQL列印出來估 ...


 

公司訂單系統每日訂單量龐大,有很多表數據超千萬。公司SQL優化這塊做的很不好,可以說是沒有做,所以導致查詢很慢。

 

正題

節選某個功能中的一句SQL EXPLAIN 查看執行計劃

EXPLAIN + SQL 查看SQL執行計劃

一個索引沒用到,受影響行接近2000萬,難怪會慢。

 原來的SQL列印出來估計有好幾張A4紙,我發個整理後的簡版。

SELECT
  COUNT(t.w_order_id) lineCount,
  SUM(ROUND(t.feel_total_money / 100, 2)) AS lineTotalFee,
  SUM(ROUND(t.feel_fact_money / 100, 2)) AS lineFactFee
FROM
  w_orders_his t
WHERE 1=1
AND DATE_FORMAT(t.create_time, '%Y-%m-%d') >= STR_TO_DATE(#{beginTime},'%Y-%m-%d') 
AND DATE_FORMAT(t.create_time, '%Y-%m-%d') <= STR_TO_DATE(#{endTime},'%Y-%m-%d')
AND t.pay_state = #{payState}
AND t.store_id LIKE '%#{storeId}%'
limit 0,10

 這條sql需求是在兩千萬的表中撈出指定時間和條件的訂單進行總數總金額彙總處理。

優化sql需要根據公司的業務,技術的架構等,且針對不同業務每條SQL的優化都是有差異的。

 

優化點1:

AND DATE_FORMAT(t.create_time, '%Y-%m-%d') >= STR_TO_DATE(#{beginTime},'%Y-%m-%d') 
AND DATE_FORMAT(t.create_time, '%Y-%m-%d') <= STR_TO_DATE(#{endTime},'%Y-%m-%d')

  我們知道sql中絕對要減少函數的使用,像左邊DATE_FORMAT(t.create_time, '%Y-%m-%d') 是絕對禁止使用的,如果資料庫有一百萬數據那麼就會執行一百萬次函數,非常非常影響效率。右邊STR_TO_DATE(#{beginTime},'%Y-%m-%d')的函數會執行一次,但還是不建議使用函數。所以去掉函數直接使用  >=,<= 或BETWEEN AND速度就會快很多,但有的資料庫設計時間欄位只有日期沒有時間,所以需要在日期後面拼接時間如:"2017-01-01" + " 00:00:00"

更好的辦法是用時間戳,資料庫中存時間戳,然後拿時間戳去比較,如:BETWEEN '開始時間時間戳' AND '結束時間時間戳'

 

優化點2:

AND t.store_id LIKE '%#{storeId}%'

這句使用了LIKE並且前後匹配,前後匹配會導致索引失效,一般情況下避免使用,應該改成 AND t.store_id LIKE '#{storeId}%'

 

優化點3:

一般利用好索引,根據主鍵、唯一索引查詢某一條記錄,就算上億數據查詢也是非常快的。但這條sql需要查詢數據統計需要用到COUNTSUM,所以可以建立聯合索引。

聯合索引有一點需要註意:key index (a,b,c)可以支持a | a,b| a,b,c 3種組合進行查找,但不支持 b,c進行查找 ,當最左側欄位是常量引用時,索引就十分有效。

所以把必要欄位排放在左邊key index(create_time,w_order_id,feel_total_money,feel_fact_money,payState,storeId)

 結果

   優化之前大概幾分鐘,現在是毫秒級。其實改的東西也不多,避免在語句上踩雷,善用EXPLAIN查詢SQL效率。 

   有時間我會舉點別的SQL優化的例子

      

  說幾點平常可以優化的地方

  • JOIN 後的的條件必須是索引,最好是唯一索引,否則數據一旦很多會直接卡死
  • 一般禁止使用UNIION ON,除非UNION ON 前後的記錄數很少 
  • 禁止使用OR
  • 查總數使用COUNT(*)就可以,不需要COUNT(ID),MYSQL會自動優化
  • 資料庫欄位設置 NOT NULL,欄位類型 INT > VARCHAR 越小越好
  • 禁止SELECT  * ,需要確定到使用的欄位
  • 一般情況不在SQL中進行數值計算
  • SQL要寫的簡潔明瞭

      

參考

EXPLAIN type(從上到下,性能從差到好)

  • all 全表查詢
  • index 索引全掃描
  • range 索引範圍掃描
  • ref 使用非唯一或唯一索引的首碼掃描,返回相同值的記錄
  • eq_ref 使用唯一索引,只返回一條記錄
  • const,system 單表中最多只有一行匹配,根據唯一索引或主鍵進行查詢
  • null 不訪問表或索引就可以直接得到結果

 

MYSQL 五大引擎

  • ISAM :讀取快,不占用記憶體和存儲資源。 不支持事物,不能容錯。
  • MyISAM :讀取塊,擴展多。
  • HEAP :駐留在記憶體里的臨時表格,比ISAM和MyISAM都快。數據是不穩定的,關機沒保存,數據都會丟失。
  • InnoDB :支持事物和外鍵,速度不如前面的引擎塊。
  • Berkley(BDB) :支持事物和外鍵,速度不如前面的引擎塊。

  一般需要事物的設為InnoDB,其他設為MyISAM

 


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

-Advertisement-
Play Games
更多相關文章
  • 因為偶爾關註QQ運動, 看到QQ運動的積分抽獎界面比較有意思,所以就嘗試用自定義View實現了下,原本想通過開發者選項查看下界面的一些信息,後來發現積分抽獎界面是在WebView中展示的,應該是在H5頁面中用js代碼實現的,暫時不去管它了。 這裡的自定義View針對的是繼承自View的情況,你可以將 ...
  • 移動互聯網近幾年發展尤為迅速,越來越多的企業也開始將目光聚集到了移動互聯網,這意味著移動互聯網時代到來,而移動APP應用是競爭的一個因素。在移動互聯網時代,移動APP開發已經不再是什麼新鮮事了,許多的企業都知道,專屬的獨立品牌APP開發是企業在移動互聯網未來生存發展的重要選擇。 那開發一款APP要多 ...
  • 一直不明白,hdfs管理的可視化工具不算難寫,為什麼找不到一個能用的,我知道的其實也就是eclipse的hadoop插件。 插件還算好用,但是和eclipse綁定的,加入用其他工具開發呢?找到了一個c#版的源碼,不過,學的是java,c#編譯完後實在是不會打包, 所以就自己寫一個java版的吧! 花 ...
  • CentOS6.9安裝Mysql5.7 一、上傳安裝包 二、建立用戶以及mysql的目錄 1、建立一個mysql的組 輸入命令: groupadd mysql 2、建立mysql用戶,並放到mysql組 輸入命令:useradd -r -g mysql mysql 3、給mysql用戶設置密碼 輸入 ...
  • oracle PROCEDURE 關鍵字: oracle 存儲過程 1.基本結構 CREATE OR REPLACE PROCEDURE 存儲過程名字 ( 參數1 IN NUMBER, 參數2 IN NUMBER ) IS 變數1 INTEGER :=0; 變數2 DATE; BEGIN END 存 ...
  • 這篇為理論篇,稍後會有實踐篇 1、分片集群是個啥玩意兒 要回答這個問題,首先得知道它是由什麼東東組成的。 MongoDB分片集群由以下組件組成: mongos:mongos作為查詢路由器,提供客戶端應用程式和分片集群之間的介面。 配置伺服器:配置伺服器存儲集群的元數據和配置信息。從MongoDB 3 ...
  • mysql安裝 登陸 設置可以遠程鏈接 把bind註釋掉 打開mysql 修改mysql資料庫下的user表中的root列HOTST為% 重啟 ...
  • 一、MySQL鎖概述 資料庫鎖機制簡單來說,就是資料庫為了保證數據併發訪問的一致性、有效性,使得數據被併發訪問變得有序所設計的一種規則。 由於MySQL有不同的存儲引擎,而不同的存儲引擎又採用不同的鎖機制。比如:MyISAM存儲引擎採用的是表級鎖(table-level locking);InnoD ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...