成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

MySQL中的SQL優化建議那么多,該如何有的放矢

數據庫 MySQL
今天早上看到同事的一個優化需求,優化的時間其實不多,但是對于這條SQL的優化思考了很多,希望有一些參考。

 今天早上看到同事的一個優化需求,優化的時間其實不多,但是對于這條SQL的優化思考了很多,希望有一些參考。

[[282433]]

業務同學提供的SQL如下:

  1. SELECT  
  2. b.order_id 
  3. FROM 
  4. SELECT 
  5. a.order_id, 
  6. a.order_time AS create_time 
  7. FROM 
  8. trade_order a 
  9. WHERE 
  10. a.user_id = 12345678 
  11. 。。。。。。 
  12. AND a.deleted = 0 
  13. UNION 
  14. SELECT 
  15. v.order_id, 
  16. v.create_time 
  17. FROM 
  18. virtual_order v 
  19. WHERE 
  20. v.user_id = 12345678 
  21. 。。。。 
  22. ORDER BY 
  23. order_id DESC 
  24. AS b 
  25. LIMIT 0, 
  26.  10; 

根據反饋,這條SQL的執行時長在200毫秒,在壓測情況下會到500毫秒左右,從業務層面來看,目前是不滿足需求的,想看看我們有沒有優化的建議。

第一印象這條SQL執行時長200~500毫秒,要優化好像可打的牌不多啊,如果要想得到一個可接受的基準值,當然反饋會是越快越好。所以從這個角度來看,我們不妨按照毫秒級優化的標準來看,這條SQL需要做哪些補充的工作。

首先通過SQL看下邏輯情況,整體的邏輯是按照用戶id去查詢兩個數據源(trade_order和virtual_order),從兩個數據源查詢出10條單號數據返回。這個用戶在兩個數據源中可能有單號,也可能沒有,只要有匹配的就返回,累計返回10條,看起來是為了去重才選擇了union的組合方式。

先不看表結構信息,我大體有了如下的建議:

  1. union的模式更建議采用union all,兩個數據源存在數據重合應該是不合理的。
  2. 查詢語句里面使用了order_time但是數據返回壓根沒有用到,建議去掉
  3. SQL層面承載了太多的數據處理壓力,比如多數據源,去重和過濾,分頁,是不是可以做下精簡。

當然到了這里,和業務的需求就產生了脫節,這就屬于那種看啥都不順眼的狀態,總想找出點問題來,而且對于業務同學來說,哪怕十個八個需求,你得有一個需求的收益更高,他們采用其他需求的可能性才越大,否則就是不作為了。

所以到了這里,我們開始做下分析,要優化SQL不看看執行計劃是不過關的,在執行前,我的大體感覺表數據量很大,應該是生成了派生表,然后在數據去重過濾層面的消耗比較大,而兩個子查詢來說,返回的結果集應該很少。 預測的執行情況是:

1)子查詢trade_order應該很快,毫米級響應

2)子查詢virtual_order應該也很快,但是最后有一個order by操作,可能代價略高

3)union的去重過濾代價相對較大,涉及到兩個結果集的合并,如果返回結果較多,可能是瓶頸

從執行結果來看,讓我有些意外,其中virtual_order的返回結果竟然有40多萬行,相當于直接走了全表掃描。

 

而其他的部分也會收到相關影響,所以后續的處理都會受到影響。

為了快速定位問題,我把兩個子查詢拆開單獨執行,查看執行計劃,這是分析瓶頸最快的一種處理思路。

  1. >>explain SELECT 
  2.     -> v.order_id, 
  3.     -> v.create_time 
  4.     -> FROM 
  5.     -> virtual_order v 
  6.     -> WHERE 
  7.     -> v.user_id = 12345678 
  8.     。。。; 

執行計劃如下:

 

可以看到是直接走了全表掃描,這是一個基礎需求,不會業務同學漏了索引吧,然后查看表結構:

  1. CREATE TABLE `virtual_order` ( 
  2.   `order_id` varchar(255) NOT NULL COMMENT '訂單ID'
  3. 。。。 
  4.   `user_id` varchar(255) DEFAULT NULL COMMENT '用戶ID'
  5. 。。。 
  6.   `refund` tinyint(3) DEFAULT NULL COMMENT ' 是否退款(1:無,2:是)'
  7.   `atc_pay_status` int(3) NOT NULL DEFAULT '0' COMMENT '支付狀態'
  8. 。。。 
  9.   PRIMARY KEY (`order_id`), 
  10.   KEY `order_status` (`order_status`), 
  11.   KEY `user_id` (`user_id`), 
  12.   KEY `prepaid_account` (`prepaid_account`) 
  13. ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

發現user_id是走了索引的,那么問題來了,user_id既然是索引,但是為什么SQL語句中依然走了全表掃描呢?

此處思考10秒鐘,繼續往下看。

其實這個時候問題的邊界都很清晰了,SQL語句很簡單,索引也存在,走了全表掃描,在MySQL中可以暫時排除直方圖的影響,目前在5.7版本中還不存在直方圖的特性,那么結果只有一個:字段的類型產生了隱式類型轉換。

這個部分可以參考這篇的一篇文章

MySQL中需要重視的隱式轉換

比如初始化語句如下:

  1. create table test(id int primary key,name varchar(20) ,key idx_name(name)); 
  2. insert into test values(1,'10'),(2,'20'); 

然后我們使用如下的兩條語句進行執行計劃的對比測試。

  1. explain select * from test where name=20; 
  2. explain select * from test where  name=’20’; 

在name列為字符類型時,得到的執行計劃列表如下:

可以很明顯的看到,在name為字符串類型時,如果where條件為name=20,則執行全索引掃描,查看warning信息會明確提示:

Message: Cannot use range access on index 'idx_name' due to type or collation conversion on field 'name'

所以此處的問題也顯而易見了。

修改了子查詢的條件為字符后,整個SQL的執行效率就立馬好多了。

使用sql_no_cache的方式測試。

SQL修改前性能:

  1. +-----------------------+ 
  2.  
  3. rows in set (0.27 sec) 
  4.  
  5. 修改后性能: 
  6.  
  7. +-----------------------+ 
  8.  
  9. rows in set (0.00 sec) 

然后再次查看執行計劃,就都規規矩矩了,這樣我們就解決了瓶頸問題,而那些規范,更好的改進就可以逐步展開了,而從建議的角度來看,采用的概率也會高一些。

 

當然在這個基礎上確實有一些補充的建議,在定位瓶頸之后也可以攤開來說了。

優化不是一錘子買賣,在這個基礎上,也發現了一些其他的問題,可以看下這個表的表結構信息,其實能夠發現一些設計上的小問題。

1) 表字段的字符型基本都是varchar(255),需要盡可能避免這種使用習慣,對于存儲性能的開銷會有顯著影響

2)使用的int類型 int(3),這種使用對于int還是存儲4個字節,但是有限范圍大大減少,可以考慮更小的數值類型

3)表的索引比較松散,可以根據業務模型創建復合索引,比如user_id和status的結合場景更多,應該創建的是(user_id,status)的復合索引

責任編輯:武曉燕 來源: 楊建榮的學習筆記
相關推薦

2021-06-07 10:05:56

性能優化Kafka

2012-08-13 14:15:53

廣聯達建筑信息化

2009-06-23 09:43:00

2009-04-24 10:24:12

網絡

2020-04-24 08:15:51

代碼 if else數組

2018-03-27 08:46:01

數據庫NoSQLredis

2022-08-16 15:20:12

微服務IT運維

2020-07-13 08:40:21

BAT模具設計

2013-06-17 10:45:34

2019-12-02 14:22:01

浪費云計算支出

2020-11-02 07:05:54

虛擬內存Go

2020-11-23 11:40:35

MySQSQL數據庫

2019-10-08 14:40:53

Java線程

2015-09-29 10:12:10

2011-12-31 14:47:10

Web App

2020-03-31 10:58:38

2021-02-21 08:48:19

技術升職程序員

2015-06-05 10:17:01

老羅創業不太成功

2024-05-27 00:30:00

NumPyPython開源庫

2017-08-14 18:00:13

共享單車摩拜
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 成人免费一区二区三区牛牛 | 91免费在线看 | www.蜜桃av| 男人天堂国产 | 色视频免费 | 久久久久久久电影 | 午夜精品久久久久久久久久久久久 | 在线黄 | 国产精品九九九 | 狠狠操狠狠操 | 成人影院一区二区三区 | 国产精品久久久久av | 久久精品亚洲 | 精品国产一区二区三区久久久蜜月 | 天天综合永久入口 | 日韩在线欧美 | 天天躁天天操 | 亚洲第一天堂无码专区 | 黄色在线观看网址 | 国产精品明星裸体写真集 | 日韩av一区二区在线观看 | 美女爽到呻吟久久久久 | 一本色道精品久久一区二区三区 | 91伦理片 | www.成人久久 | 国产免费一区 | 免费中文字幕日韩欧美 | 天天色综网 | 欧美精品三区 | 国产高清在线精品一区二区三区 | 久久香蕉精品视频 | 国产日韩欧美 | 91精品国产综合久久香蕉麻豆 | 欧美日韩中文字幕 | 中文字幕乱码视频32 | 国产精品成人在线播放 | 欧美一级在线免费 | 国产精品一区二区三区在线 | www.日本三级| 91久久 | 国产一区二区精华 |