国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

慢SQL,壓垮團隊的最后一根稻草

開發 開發工具
今天只討論一種應用模式,就是最普遍的,前端實時調用后端web服務,服務端經過DB的增刪改查作出響應的應用。至于離線數據分析,在線規則引擎模板執行,流式計算等不在本次討論范疇。

先說結論,我支持將邏輯寫在 Java 等應用系統中。

[[225954]]

背景:

今天只討論一種應用模式,就是最普遍的,前端實時調用后端web服務,服務端經過DB的增刪改查作出響應的應用。至于離線數據分析,在線規則引擎模板執行,流式計算等不在本次討論范疇。

重SQL開發的場景

先看一個例子吧。用經典的 Controller Service DAO 開發模式描述。

需求:

查詢出每個學生所在的城市名以及分數展示到前端。

重SQL模式

  1. class Controller{ 
  2.   Service service; 
  3.   Map<String,String> get(Map<String,Object> param){ 
  4.     return service.get(param); 
  5.   } 
  6.  
  7. class Service{ 
  8.   DAO dao; 
  9.   Map<String,String> get(Map<String,Object> param){ 
  10.     return dao.get(param); 
  11.   } 
  12. class DAO{ 
  13.   SQLTemplate template; 
  14.   Map<String,String> get(Map<String,Object> param){ 
  15.     String sql = "select city_name,student_name,score from student,score,city where city.city_code=student.city_code and score.student_id=student.student_id" ; 
  16.     return template.execute(sql,param); 
  17.   } 

重Java模式

  1. class View
  2.   String studentName; 
  3.   String cityName; 
  4.   String score; 
  5.  
  6. class Requent{ 
  7.  
  8. class Controller{ 
  9.   Service service; 
  10.   List<View> get(Requent request){ 
  11.     return service.get(param); 
  12.   } 
  13.  
  14. class Service{ 
  15.   StudentDAO studentDAO; 
  16.   ScoreDAO scoreDAO; 
  17.   CityDAO cityDAO; 
  18.   List<View> get(Requent param){ 
  19.     Student studentRequest = new Student(); 
  20.     //查詢學生 
  21.     List<Student> students = studentDAO.select(studentRequest); 
  22.     List<View> result = new ArrayList(students.size()); 
  23.      
  24.     for(Student student : students){ 
  25.       View view = new View(); 
  26.       view.setStudentName(student.getStudentName()); 
  27.      
  28.        //拼接城市名 
  29.       City cityRequest  = new City(); 
  30.       cityRequest.setStudentId(student.getStudentId()); 
  31.       City city = cityDAO.select(cityRequest); 
  32.       view.setCityName(city); 
  33.        
  34.       //拼接分數 
  35.       Score scoreRequest = new Score(); 
  36.         scoreRequest.setStudentId(student.getStudentId()); 
  37.       Score score = scoreDAO.select(scoreRequest); 
  38.       view.setScode(score.getScore()); 
  39.        
  40.       result.add(view); 
  41.     } 
  42.     return result; 
  43.   } 
  44.  
  45. class StudentDAO{ 
  46.   SQLTemplate template; 
  47.   Student select(Student param){ 
  48.     String sql = "select * from Student where param = ..."
  49.     template.select(sql,param); 
  50.   }  
  51.  
  52. class ScoreDAO{ 
  53.   SQLTemplate template; 
  54.    Score select(Score param){ 
  55.     String sql = "select * from Score where param = ..."
  56.     template.select(sql,param); 
  57.   } 
  58.  
  59. class CityDAO{ 
  60.   SQLTemplate template; 
  61.   City select(City param){ 
  62.   String sql = "select * from City where param = ..."
  63.     template.select(sql,param); 
  64.   } 

可以看到,使用重SQL的模式來進行開發確實很快很快,只需要把SQL開發出來基本就完事了,但是看著用重 Java 的模式開發,需要寫一堆的代碼,這么看來好像是 SQL 勝利一籌。

好,PD突然說了,我要把城市名為 “大蕉” 的,分數乘于2展示出來。握草,這個怎么搞??

重SQL模式

  1. class DAO{ 
  2.   SQLTemplate template; 
  3.   Map<String,String> get(Map<String,Object> param){ 
  4.     String sql = "select city_name,student_name,CASE WHEN city.city_name='大蕉' THEN 2*score.score ELSE score END score from student,score,city where city.city_code=student.city_code and score.student_id=student.student_id " ; 
  5.     return template.execute(sql,param); 
  6.   } 

好了。。這個SQL已經變得很復雜了基本沒法看了。。

重 Java 模式

  1. Service.class    
  2.  
  3.      //拼接分數 
  4.       Score scoreRequest = new Score(); 
  5.         scoreRequest.setStudentId(student.getStudentId()); 
  6.       Score score = scoreDAO.select(scoreRequest); 
  7.        
  8.       if("大蕉".equals(city.getCityName()){ 
  9.         view.setScode(score.getScore() * 2); 
  10.       }else
  11.             view.setScode(score.getScore()); 
  12.       } 
  13.        

咦好像改動也不多嘛。

這時候PD又來了我要把城市名為 “大蕉” ,并且城市Code小于10086的,分數乘于2展示出來。握草,完蛋了,之前全是SQL,這個需求要怎么搞??繼續疊加上去繼續 CASE WHEN?

還沒想清楚呢,突然 DBA 電話飛過來了,兄dei你的SQL太慢了,現在把整個庫拖垮了,你是不是沒有加索引?

我:索引加了啊。。。難道是沒走到?那是先解決慢SQL還是先開發需求呢?拆庫是不可能了,邏輯這么死鬼復雜拆庫完全沒法跑啊,加CPU加內存啊 DBA大佬!!!

[DBA日報] 慢SQL 180+,已解決10。

又上了一個版本

[DBA日報] 慢SQL 200+,已解決15。

又上了一個版本

[DBA日報] 慢SQL 250+,已解決30。

慢慢的,開發和運營和DBA每天都疲勞于監控這些SQL。。。。

前言

觀察了一下,傳統企業以及絕大部分轉型中的企業的 Java 應用中,很神奇的是,他們的開發人員包括我自己以前,大家都非常非常希望使用一個 SQL 來完成所有的邏輯的編寫,非常多企業更是把數據庫的存儲過程和數據庫自定義函數來完成。

這些關于邏輯應該寫在哪里的爭論從來沒有停止過,不僅僅發生在后端和數據庫端,連前后端都經常會發生這種爭論,現在只討論后端和數據庫端的糾結。

我將從這五個方面分別對比一下兩種模式的異同。

  • 出現場景
  • 開發效率
  • 缺陷排查
  • 架構升級
  • 系統維護

出現場景

SQL

我們絕大多數的歷史代碼都是用存儲過程來實現的啊,如果有新需求不往上面做的話,很難兼容原來的邏輯啊啊。

前面的人呢是這樣寫的,我來了看大家都這樣寫就這樣寫了。

Java

新應用嘛,我想怎么樣寫就怎樣寫。

監控和埋點寫起來簡單吖,排查問題可方便了。

前面的人呢是這樣寫的,我來了看大家都這樣寫就這樣寫了。

開發效率

SQL

這樣寫起來很快啊,而且寫 Java 代碼多難受啊,寫 SQL 我自己在數據庫開發環境跑一下結果正確我就直接丟到代碼中提交了,多爽啊。

老實說,這樣子確實會提高開發的效率,因為不用寫那么多查庫聚合的操作,一切都在 SQL 中搞定了。另一方面來看,這確實會讓 Java 代碼看起來很雞肋,好像只是把數據從 web 層到數據層的一個管道而已,一切 if else 能寫在 SQL 中的都寫在 SQL 中了。

但是新需求來或者需求變更的時候,我經常要重新寫SQL,如果變動不多我可能要改動到原來的 SQL,但是我又不敢改,所以只好 copy 重新寫一個,改 SQL 的風險好大,一報錯又要重啟好難受。

Java

一次要寫N個類,有點煩。

新需求來或者需求變更的時候,如果邏輯比較復雜,我直接抽成方法或者改成一些設計模式,維護起來效率還是可以接受的。

缺陷排查

SQL

開發排查問題的時候,除了看日志,直接把SQL和參數丟到 PL/SQL 或者 其他工具里跑一下,基本就能知道數據問題出現在哪了。測試同學在進行測試的時候,如果發現有不對的東西,直接跟開發同學一樣的思路,把SQL 跑一下,問題基本就定位得七七八八了。

但是呢,一旦遇到跑 SQL 無法一眼看出問題的 bug 或者 SQL 實在是太長太長了的的時候,就蒙圈了。我曾經就維護了一個幾千行的存儲過程,一旦發生問題,排查問題的過程巨艱難。但是呢直接用一個數據庫一個功能搞定所有功能未嘗不是一件很爽的事情,因為關系型數據庫實在是實在是太太太穩定了,一次編寫***運行。

Java

看日志看監控。

根據報錯的代碼位置 check 一下代碼邏輯。

一些入參分支肉眼 check 不出來,只能遠程 debug 慢慢看數據流向。

測試的同學基本無法幫忙 check 缺陷,只能靠程序的表現來判斷。

架構升級

SQL

SQL 慢沒關系,它穩定啊,慢就把機器垂直擴展一下好啦,加cpu,加內存,換SSD,加加加絕對可以解決事情的。

SQL 有各種索引和優化策略,說不定跑起來比我們自己寫邏輯還快呢。

加加加,加內存加cpu垂直升級。也沒有其他招數了,除了前置緩存,但是如果查詢都很個性化SQL很復雜,前置緩存也基本沒啥亂用。。。

如果你的邏輯全部寫在 SQL 中,那完蛋了,你這個表基本就沒法分表了,因為你的業務邏輯跟數據庫的數據完整性是強耦合的,需要一切數據基本都在一個數據庫中,這是一件很難受很難受的事情,不信你去問問那些所有業務邏輯全寫在 SQL 中的小伙。

數據庫中非常復雜的表關聯會極大程度拖慢數據庫處理每條 SQL 的平均時間,極大程度拖慢數據庫 RT,降低了數據庫的 RT ,如果邏輯都寫在 SQL 中,那么只能進行垂直升級。因為一旦進行水平擴展,那么多機器的非常復雜的分布式表關聯,RT 基本不是一個高并發的業務應用的能容忍的。

Java

如果是數據庫瓶頸,加數據庫機器,分庫分表一下,應用層基本不用改,在DAO層進行路由一下。

如果是服務器cpu瓶頸,多加幾臺機器就好了。

如果還有瓶頸,增加一下查詢緩存。

在應用快速發展的過程中一般都會分庫分表的拆分或者自動水平擴展,這時候其實只需要數據庫層面做好自己的數據遷移和同步就好了,對于業務層來說是完全無感知的。即使業務非常非常復雜,需要拆應用,其實也非常簡單,只需要把對應的 DAO 層的操作拆分出去,換成 RPC 或者其他方式的調用就好了。

系統維護

SQL

舊SQL完全不敢動,來一個需求加一個 SQL。

慢SQL日益增加,應對疲乏。

Java

SQL寫完一次基本不用動,來一個需求加一個方法聚合一下數據操作即可。

應用維護比較簡單,只要監控做好了,定位到問題基本都能很快解決。

邏輯越來越復雜,沒有好的開發框架的話,代碼維護起來也是挺要命,因為完全不知道跑哪個分支去了。但是現在已經有很多優秀的開源框架來更好地維護代碼了,比如 Spring 的全家桶。

怎么破

舊的重 SQL 邏輯暫時不要動,新的邏輯都基于 Java 模式開發,先保證慢 SQL 不增加,舊的 SQL 穩定運行,畢竟業務穩定是***要素。

如果業務初期需要非常非常快速開發,那么使用重 SQL 模式也是可以理解的,但是還是要抽時間重構成 Java 模式。

結論

我支持將邏輯寫在 Java 等應用系統中。其實原因在上面基本描述完了,***就是復雜 SQL 的表關聯其實跟個人的能力有非常大的關系,如果一個 SQL 寫得不好,那是極慢極慢的非常容易把整個數據庫拖慢的。第二就是維護這些 SQL 也是一件很難受的事情,因為你完全不知道這個 SQL 背后的數據流轉是怎樣的,你只能根據自己的猜測去查看 SQL 中的 bug,Java 應用好歹還能 debug 一下還有打點看看數據不是?如果邏輯寫在 Java 中那么其實你的 DAO 層只需要編寫一次,但是可以***使用,基本不會在這一層浪費很多的時間(用過 ibatis 的都知道改了 SQL 需要重啟應用吧?)。第三就是邏輯都寫在 SQL ,中對于分庫分表和應用拆分來說是一件非常難受的事情,真的難受。

昨天寫的被吐槽了,回爐重造了,重新看看。

責任編輯:武曉燕 來源: 51CTO專欄
相關推薦

2022-08-15 07:32:03

SQL語句數據庫

2014-01-10 10:53:29

移動廣告平臺進化分發

2011-07-28 09:09:23

Java

2020-05-08 09:37:32

網線網絡網速

2025-04-03 00:03:00

數據內存網絡

2011-07-22 10:40:04

思科裁員

2015-03-23 11:56:58

2017-02-07 09:15:54

光纖傳輸介質通信網絡

2009-03-12 10:03:00

雙絞線連接網絡

2016-12-01 09:30:03

運維網絡網線

2021-03-23 08:21:06

GolangPython字符

2016-05-18 14:50:57

運維PortfastAPI

2010-09-10 16:17:27

2020-07-16 11:16:57

云計算SD-WAN運營

2022-12-13 10:28:53

2021-04-06 08:20:24

二叉搜索樹數據結構算法

2017-08-14 16:36:23

ASActivity內存

2017-12-28 11:25:51

2019-09-02 10:38:30

網線攻擊MVP

2016-11-18 13:58:33

點贊
收藏

51CTO技術棧公眾號

佐山爱痴汉视频一区二区三区| 中出在线观看| 黄色综合网站| 日本高清不卡在线| 97精品国产综合久久久动漫日韩| 日韩一区二区免费在线电影| 日本一卡二卡四卡精品| 亚洲另类在线一区| 国产毛片视频| 亚洲激情欧美激情| 国产激情视频网址| 一区二区三区在线免费视频| 成人性生交大片免费看视频r| 欧美国产激情一区二区三区蜜月| 久久一区欧美| 97人人澡人人爽| 国产精品久久久久久| 日韩av片免费在线观看| 日本福利一区| 国产成人+综合亚洲+天堂| 久久综合影院| 成人免费高清完整版在线观看| 欧美日韩精品一区二区视频| 国产成人久久久精品一区| 精品视频国产| 国产精品pans私拍| 色综合色综合| 国产二区一区| 亚洲欧美日本国产专区一区| 欧美一区2区三区4区公司二百| 亚洲欧美日韩精品一区二区| 亚洲7777| 福利一区二区在线| www.超碰com| 亚洲一区在线观看免费 | 一区二区三区国产好| 久久91精品国产91久久跳| 91精品国产自产在线丝袜啪| 97超碰国产精品女人人人爽| 欧美绝顶高潮抽搐喷水合集| 国产主播精品在线| 亚洲精品日本| 欧美精品久久96人妻无码| 国产精品一品视频| 成人观看免费完整观看| 亚洲欧美激情在线| 少妇激情av一区二区| 欧美喷水一区二区| 捆绑调教日本一区二区三区| 欧美成人合集magnet| 色中色综合网| 亚洲欧洲久久| 国产女人aaa级久久久级| 中文字幕视频在线观看| 日韩欧美在线影院| 亚州一区二区| 成人xxxxx色| 成人小视频免费观看| 视频免费在线看| 精品久久久久久久一区二区蜜臀| 亚洲免费一区| 91在线观看免费观看| 麻豆极品一区二区三区| www午夜视频| 欧美日韩1区2区| 日本一区二区三区电影免费观看| 91视频8mav| www.一区二区| 在线免费国产| 精品亚洲va在线va天堂资源站| 美女一区二区在线观看| 日韩精品不卡| 一区二区三区欧美| 精品91久久| 国产美女直播视频一区| 久久精品噜噜噜成人av农村| 日韩中文字幕a| 3atv在线一区二区三区| 日韩在线成人| 日本视频一区在线观看| 欧美国产成人在线| sm久久捆绑调教精品一区| 国产精品高潮呻吟久久av野狼 | 99久久国产综合精品女不卡| 中国国产一级毛片| 亚洲视频axxx| 精品电影一区| av免费高清观看| 亚洲性生活视频| 欧美日韩福利| 五月天亚洲激情| 亚洲欧美一区二区三区在线| 欧美a级一区| 啦啦啦中文高清在线视频 | www.久久热.com| 91国产美女视频| 韩国精品一区二区| 高清av电影在线观看| 欧美日韩成人在线播放| 久久se这里有精品| a中文在线播放| 日日欢夜夜爽一区| 99久久国产综合精品色伊| 在线观看免费毛片| 最近更新的2019中文字幕| 日韩视频一区二区三区在线播放免费观看| 欧美成人一区二区在线观看| 91精品国产欧美一区二区18| 国产精品免费不| 黄www在线观看| 亚洲激情久久久| 亚洲网站在线| 天海翼一区二区三区免费| 欧美国产第二页| 国产精品一品视频| 欧美性爽视频| 国产精品加勒比| 精品久久在线播放| 九九亚洲精品| 成人毛片免费在线观看| 久久精品视频网站| 国产成a人亚洲精| 韩日毛片在线观看| 欧美精品人人做人人爱视频| 欧美日韩国产一区二区三区| 欧美成人午夜77777| 中国丰满人妻videoshd| 中文字幕亚洲色图| 国产suv一区二区三区88区| av不卡高清| 亚洲国产精品日韩| 欧美一级免费大片| 国产深夜精品| 黄网页免费在线观看| 成人激情直播| 色婷婷国产精品综合在线观看| 色婷婷色综合| 在线中文字幕av| 国产日韩av高清| 亚洲一线二线三线视频| 久草成人在线| 嫩草嫩草嫩草| 成人黄色在线免费| 欧美视频在线观看免费| 欧美日韩精品一本二本三本 | 91原色影院| 国产91露脸中文字幕在线| 亚洲美女在线一区| 日韩精品2区| 女人偷人在线视频| 欧美亚洲丝袜| 亚洲欧洲一区二区三区在线观看| 国产69精品久久99不卡| 一区二区三区国产好| 欧美12一14sex性hd| 国产欧美日韩视频一区二区三区| 欧美一区二区国产| 国产精品一二三| 国产伦精品一区二区三区在线播放 | 欧美日韩国产123| 一区二区三区在线观看网站| 精品久久久久久久| 国产尤物视频在线| 日韩在线第一区| 国产亚洲精品久久久久久牛牛| 国产亚洲一区字幕| 青青草综合网| 日本高清成人vr专区| 成熟了的熟妇毛茸茸| 国产精品美女久久久免费| 91精品在线免费| 99久久久国产精品免费蜜臀| 日韩欧美在线精品| 蜜桃视频在线观看网站| 偷拍视频一区二区| 久久在线精品视频| 精品久久久久久中文字幕| 精品一区在线看| 国产精品一区二区中文字幕| 成人免费黄色网页| 色综合久久综合网欧美综合网 | 天海翼一区二区三区免费| 亚洲一区二区三区777| 精品国内片67194| 国产精品污污网站在线观看 | 成年永久一区二区三区免费视频| 欧美性猛交xxx高清大费中文| 91成人福利社区| 开心久久婷婷综合中文字幕| 网红女主播少妇精品视频| 在线视频亚洲欧美中文| 成人性做爰aaa片免费看不忠| 国产精品久久久久久久久| 国产精品久久网| 亚洲亚裔videos黑人hd| 色偷偷av一区二区三区乱| 亚洲精品自拍动漫在线| 黄色成人av网| 欧美日韩一级片在线观看| 最近最新中文字幕在线|