阿裡慢SQL治理5大經典案例

来源:https://www.cnblogs.com/88223100/archive/2022/03/16/5_Classic_Cases_of_Alibaba_Slow_SQL_Governance.html
-Advertisement-
Play Games

菜鳥供應鏈金融慢sql治理已經有一段時間,自己負責的應用持續很長時間沒有慢sql告警,現階段在推進組內其他成員治理應用慢sql。這裡把治理過程中的一些實踐拿出來分享下。 ...


菜鸟供应链金融慢sql治理已经有一段时间,自己负责的应用持续很长时间没有慢sql告警,现阶段在推进组内其他成员治理应用慢sql。这里把治理过程中的一些实践拿出来分享下。

一、全表扫描

1、案例

SELECT count(*) AS tmp_count FROM (

SELECT * FROM `XXX_rules` WHERE 1 = 1 ORDER BY gmt_create DESC ) a

2、溯源

在分页查询治理的文章里已经介绍过我们系统旧的分页查询逻辑,上面的查询sql明显就是分页查询获取总记录数,通过XXX_rules表的分页查询接口溯源,找到发起调用的页面是我们小二后台的一个操作商家准入的页面,页面打开后直接调用分页查询接口,除了分页参数,不传入其他任何查询参数,导致扫描全表。

3、分析

灵魂拷问:为什么要扫描全表?全表数据展示到页面,花里胡哨的数据有用吗?

调研:和经常使用这个页面的运营聊后了解到,打开页面查询出的全表数据对运营是没有用的,他们根本不看这些数据。运营的操作习惯是拿到商家id,在页面查询框中输入商家id,查到商家数据后进行操作。

4、解决方案

由此优化方案就很明朗了:打开页面时不直接查询全量数据,等运营输入商家id后,将商家id作为参数进行查询。XXX_rules表中,商家id这一常用查询条件设置为索引,再结合分页查询优化,全表扫描慢sql得以解决。

优化后的小二后台页面如下:

打开页面时未查询任何数据,查询条件商家账户为必填项。

优化后的sql为:

SELECT count(*) AS tmp_count FROM (

SELECT * FROM `xxx_rules` WHERE 1 = 1 AND `rule_value` = '2928597xxx' ) a

执行EXPLAIN得到结果如下:

可以看到命中了索引,扫描行数为3,查询速度明显提高。

5、思考

扫描全表治理简单来说就是加入查询条件,命中索引,去除全表扫描查询,虽然有些粗暴,但并不是没有道理。实际业务场景中,很少有要扫描全表获取全部数据的情况,限制调用上游必须传入查询条件,且该查询条件能命中索引,能很大程度上避免慢sql。

另外,再引申下,XXX_rules初始的用意是准入表,记录金融货主维度的准入情况,最多也就几千条数据,但是很多同事将这张表理解为规则表,写入很多业务相关规则,导致这个表膨胀到一百多万条数据,表不clean了。这就涉及到数据表的设计使用,明确表的使用规范,不乱写入数据,能给后期维护带来很大的便利。

二、索引混乱

1、示例

2、分析

除了时间、操作人字段,XXX_rules表就rule_name、rule_value、status、product_code四个字段,表的索引对这四个字段做各种排列组合。存在如下问题:

1)rule_name离散度不高,放在索引首位不合适;

2)前三个索引重合度很高;

显然是对索引的命中规则不够了解。XXX_rules表很多业务有定时任务对其写入删除,索引多、混乱,对性能有很大的影响。

高性能的索引有哪些,再来回顾下:

①独立的列:索引列不能是表达式的一部分;

②选择区分度高的列作为索引;

③选择合适的索引列顺序:将选择性高的索引列放在最前列;

④覆盖索引:查询的列均在索引中,不需要回查聚簇索引;

⑤使用索引扫描来做排序;

⑥在遵守最左前缀的原则下,尽量扩展索引,而不是创建索引。

但凡记得第规则,也不至于把索引建成这样。

3、治理

对索引进行整合如下:

系统中有很多任务拉取整个产品下的准入记录,然后进行处理,所以将区分度较高的product_code放在索引首位,然后添加rule_name、status字段到索引里,进一步过滤数据,减少扫描行数,避免慢sql。针对常用的rule_value查询条件,可以命中UK,因此不用单独建立索引。

三、非必要排序

1、问题描述

很多业务逻辑中,需要拉取满足某个条件的记录列表,查询的sql语句带有order by,记录比较多的情况,排序代价往往很大,但是查询出来的记录是否有序对业务逻辑没有影响,比如分页治理里讨论的count语句,只需要统计条数,order by对条数没有影响,再比如查出记录列表后,不依赖记录的顺序遍历列表处理数据,这时候order by多此一举。

2、解决方案

查询sql无limit语句,且业务处理逻辑不依赖于order by后列表记录的顺序,则去除查询sql中的order by语句。

四、粗粒度查询

1、问题描述

业务中有很多定时任务,扫描某个表中某个产品下所有数据,对数据进行处理,比如:

SELECT * FROM XXX_rules

WHERE rule_name = 'apf_distributors'

AND status = '00'

AND product_code = 'ADVANCE'

三个查询条件都是区分度不高的列,查出的数据有27W条,加索引意义也不大。

2、分析

实际业务量没那么大,顶多几千条数据,表里的数据是从上游同步过来的,最好的办法是让上游精简数据,但是由于业务太久远,找上游的人维护难度太大,因此只能想其他的办法。

这个定时任务目的是拉出XXX_rules表的某些产品下的数据,和另一张表数据对比,更新有差异的数据。每天凌晨处理,对时效性没有很高的要求,因此,能不能转移任务处理的地方,不在本应用机器上实时处理那么多条数据?

3、解决方案

数据是离线任务odps同步过来的,首先想到的就是dataWork数据处理平台。

建立数据对比任务,将定时任务做的数据对比逻辑放到dataWork上用sql实现,每天差异数据最多几百条,且结果集含有区分度很高的列,将差异数据写入odps表,再将数据回流到idb。

新建定时任务,通过回流回来的差异数据中区分度高的列作为查询条件查询XXX_rules,更新XXX_rules,解决了慢sql问题。

这个方法的前提是对数据实效性要求不高,且离线产出的结果集很小。

五、OR导致索引失效

1、案例

SELECT count(*)

FROM XXX_level_report

WHERE 1 = 1

AND EXISTS (

SELECT 1

FROM XXX_white_list t

WHERE (t.biz_id = customer_id

OR customer_id LIKE CONCAT(t.biz_id, '@%'))

AND t.status = 1

AND (t.start_time <= CURRENT_TIME

OR t.start_time IS NULL)

AND (t.end_time >= CURRENT_TIME

OR t.end_time IS NULL)

AND t.biz_type = 'GOODS_CONTROL_BLACKLIST'

2、分析

explain上述查询语句,得到结果如下:

XXX_white_list表有将biz_id作为索引,这里查询XXX_white_list表有传入biz_id作为查询条件,为啥explain结果里type为ALL,即扫描全表?索引失效了?索引失效有哪些情况?

索引失效场景:

①OR查询左右有未命中索引的;

②复合索引不满足最左匹配原则;

③Like以%开头;

④需要类型转换;

⑤where中索引列有运算;

⑥where中索引列使用了函数;

⑦如果mysql觉得全表扫描更快时(数据少时)

上述查询语句第8行,customer_id为XXX_level_report表字段,未命中XXX_white_list表索引,导致索引失效。

3、解决方案

这个语句用condition、枚举、join花里胡哨的代码拼接起来的,改起来好麻烦,而且看起来“OR customer_id LIKE CONCAT(t.biz_id, '@%')”这句不能直接删掉。最后重构了该部分的查询语句,去除or查询,解决了慢sql。

作者丨如期

本文来自博客园,作者:古道轻风,转载请注明原文链接:https://www.cnblogs.com/88223100/p/5_Classic_Cases_of_Alibaba_Slow_SQL_Governance.html


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

-Advertisement-
Play Games
更多相關文章
  • MySQL 索引(入門): 一、介紹 1.什麼是索引? 一般的應用系統,讀寫比例在10:1左右,而且插入操作和一般的更新操作很少出現性能問題,在生產環境中,我們遇到最多的,也是最容易出問題的,還是一些複雜的查詢操作,因此對查詢語句的優化顯然是重中之重。說起加速查詢,就不得不提到索引了。 2.為什麼要 ...
  • 博客推行版本更新,成果積累制度,已經寫過的博客還會再次更新,不斷地琢磨,高質量高數量都是要追求的,工匠精神是學習必不可少的精神。因此,大家有何建議歡迎在評論區踴躍發言,你們的支持是我最大的動力,你們敢投,我就敢肝 ...
  • 使用爬蟲等獲取實時數據+Flume+Kafka+Spark Streaming+mysql+Echarts實現數據動態實時採集、分析、展示 主要工作流程如下所示: 其中爬蟲獲取實時數據,並把數據實時傳輸到Linux本地文件夾中。 使用Flume實時監控該文件夾,如果發現文件內容變動則進行處理,將數據 ...
  • 存儲過程與函數 類似與Java的方法和C語言的函數 存儲過程概述 含義 一組經過預先編譯的SQL語句的封裝 執行過程:存儲過程預先存儲在MySQL伺服器上,客戶端發出命令後,伺服器可以把預先存儲好的SQL語句全部執行 好處 簡化操作,提高了SQL語句的通用性,減少開發程式員的壓力 減少操作中的失誤, ...
  • 作者:Álvaro Hernández 當技術決策人考慮在 Kubernetes 上部署資料庫時,面臨的第一個問題就是:“Kubernetes 有應對有狀態服務的能力嗎?”多年來的答案都是“不建議”,而且理由充分。畢竟,Kubernetes 最初的設計便是用於處理無狀態服務的容器編排。如今,有狀態服 ...
  • 博客推行版本更新,成果積累制度,已經寫過的博客還會再次更新,不斷地琢磨,高質量高數量都是要追求的,工匠精神是學習必不可少的精神。因此,大家有何建議歡迎在評論區踴躍發言,你們的支持是我最大的動力,你們敢投,我就敢肝 ...
  • 視圖 常見的資料庫對象 視圖概述 為什麼使用視圖 可以幫助我們使用表中的部分數據,對其修改可以改變原來表中的值 可以簡化查詢 控制數據的訪問(許可權) 視圖的理解 視圖是一種虛擬表,本身不具有數據的,占用極少的記憶體 視圖建立在已有表的基礎上,我們可以視圖所依據的表叫做基表 視圖的創建和刪除只會影響視圖 ...
  • 目前各大公司的產品需求和內部決策對於數據實時性的要求越來越迫切,需要實時數倉的能力來賦能。傳統離線數倉的數據時效性是 T+1,調度頻率以天為單位,無法支撐實時場景的數據需求。即使能將調度頻率設置成小時,也只能解決部分時效性要求不高的場景,對於實效性要求很高的場景還是無法優雅的支撐。因此實時使用數據的... ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...