sql怎么撤回update_腾讯SQL“现役运动员”给你的实践小技巧
引言
SQL的全稱是Structured Query Language(結(jié)構(gòu)化查詢語言),是一種古老而簡潔的程序設(shè)計語言。看似平平無奇,一直被各種吐槽,但卻有著眾多語言所難得的漫長壽命,并展現(xiàn)出極好的拓展性,在不同時期衍生出不同的子語言。筆者作為騰訊TDW體系下的SQL現(xiàn)役運動員,對日常工作中常用的基礎(chǔ)知識和展開的業(yè)務(wù)實踐予以了總結(jié),可供讀者參考。
結(jié)構(gòu)化查詢語言,顧名思義,它的基礎(chǔ)在于結(jié)構(gòu)化的數(shù)據(jù)庫表,最主要的應(yīng)用場景在于數(shù)據(jù)查詢,雖然SQL也可以像其它語言一樣有一些高級的寫法,但它的主戰(zhàn)場并不在此,仍要回歸到對數(shù)據(jù)庫表的操作和處理中。以下分為基礎(chǔ)知識篇和業(yè)務(wù)實踐篇展開介紹,其中基礎(chǔ)知識篇盤點了一些常用的技能點,業(yè)務(wù)實踐篇則總結(jié)了幾點日常工作里的思考。
第一部分 基礎(chǔ)知識篇
圍繞著數(shù)據(jù)庫表,可以展開許多的主題工作,有些是比較專業(yè)性的領(lǐng)域,如事務(wù)處理和權(quán)限管控等,這些更多是面向底層的技術(shù)基礎(chǔ),部分屬于DBA的工作范疇。對于使用SQL的很大部分用戶群體來說,則集中于對數(shù)據(jù)庫表的增刪查改,聚合匯總里,這些是面向業(yè)務(wù)的數(shù)據(jù)工作。針對這一塊的內(nèi)容,繼續(xù)將其細分到不同的子場景里,逐一展開介紹。
1.庫表基本操作
庫表預(yù)覽:SQL最基礎(chǔ)和最核心的兩個對象,便是數(shù)據(jù)庫和數(shù)據(jù)表,基于一個業(yè)務(wù)場景,可以有N個數(shù)據(jù)庫,在一個數(shù)據(jù)庫里面,又可以有N張數(shù)據(jù)表。數(shù)據(jù)庫的連接與切換,數(shù)據(jù)表的創(chuàng)建與刪除,是使用SQL進行庫表預(yù)覽的基本操作。這些基本操作,可以通過前端的可視化界面進行,也可以從后臺直連數(shù)據(jù)庫展開,需由使用者所擁有的權(quán)限級別來選擇。
數(shù)據(jù)增刪:除了一些常規(guī)的每日運行的計算任務(wù)外,很多時候我們只是單純地想對一張表進行處理,比如插入幾條數(shù)據(jù),更新某個字段值,或者剔除幾條數(shù)據(jù)。這些操作往往是單次的,局部的,目的清晰,所以掌握幾個關(guān)鍵字就可以實現(xiàn),如INSERT/UPDATE/DELETE等。
視圖應(yīng)用:視圖的引入,相當(dāng)于在統(tǒng)計邏輯和實際庫表之間提供了一種折中的方案。完成這個功能,邏輯上是必須有這么幾道工序的,但又不想在每一道工序里都落地一張實際的數(shù)據(jù)表,顯得繁瑣而臃腫,那就引入視圖吧,把這些中間的工序用視圖的形式去實現(xiàn)和替代。
關(guān)鍵字:其實SQL真的是一門很簡潔的語言,市面上也不會有大本的書籍專門講述SQL的書寫方式,因為相對于其它語言來說,SQL歸根到底,只是圍繞著幾個關(guān)鍵字的一些基礎(chǔ)語句而已。只要把這幾個關(guān)鍵字掌握了,SQL的大部分內(nèi)容其實就已經(jīng)展開了。
2.數(shù)據(jù)查詢語句
SQL作為面向數(shù)據(jù)庫表的基礎(chǔ)語言,用戶群體具有多樣性,從技術(shù)底層往業(yè)務(wù)層走,往往會有DBA,數(shù)據(jù)開發(fā),數(shù)據(jù)分析,產(chǎn)品經(jīng)理等這些用戶角色。不同用戶群體對SQL的側(cè)重點是有差異的,但無論是哪一個群體,基本都繞不開數(shù)據(jù)查詢語句,是一塊必要內(nèi)容。
簡單查詢:能寫一個簡單查詢語句,其實就已展開了和數(shù)據(jù)庫表的對話過程。不管是哪種SQL的拓展語言,簡單查詢里的語法基本都還是一致的。比如用*代表全量查詢,用distinct去重,用top和limit對數(shù)據(jù)條數(shù)做基本限制,以及用as對原表字段名進行替換更新等。
過濾查詢:在簡單查詢的基礎(chǔ)上,添加一些約束條件,也就是過濾查詢。比如你可以用關(guān)鍵字where查看其中某天的數(shù)據(jù),用between或者in來限制一個范圍,用like或者relike來做正則匹配,也可以用and或者or這兩個通配符對這些約束條件進行排列組合。
排序查詢:排序查詢可以細分為兩個場景,一個是在查詢內(nèi)部的排序,即根據(jù)某個字段的屬性值進行表內(nèi)部分區(qū),對分區(qū)進行排序查詢后輸出,可以用row_number的形式來實現(xiàn);另一個是把整個查詢當(dāng)做一個整體,對結(jié)果表進行排序查詢后輸出,用order by來實現(xiàn)即可。
3.數(shù)據(jù)聚合與連接
前面講數(shù)據(jù)查詢語句,不管怎么查詢,其實并不影響原生的表結(jié)構(gòu),即原來的表是按照什么邏輯寫的數(shù)據(jù),查詢結(jié)果里的數(shù)據(jù)也是基于這種邏輯,只是篩選了局部數(shù)據(jù)而已。但數(shù)據(jù)聚合與連接就不一樣了,聚合會在縱向上改變原生表結(jié)構(gòu),連接則在橫向上拓展了表結(jié)構(gòu)。
數(shù)據(jù)聚合:要對一張表做數(shù)據(jù)聚合,其實理解了兩個概念即可,維度和指標(biāo)。維度是你要基于哪些字段來做聚合,指標(biāo)是在這個維度之上,你想用什么匯總函數(shù)生成哪些指標(biāo)。數(shù)據(jù)聚合的關(guān)鍵字是group by,維度里的屬性值仍來自于原生表,指標(biāo)則是新生成的匯總值。
數(shù)據(jù)連接:對兩張表或者N張表做連接,是SQL里面非常重要的一個內(nèi)容,也是最容易埋坑的一個坑點。盡管數(shù)據(jù)連接只涉及四種方式,七個語法,但其仍然是絕大部分SQL腳本的核心內(nèi)容。選擇合適的可靠的數(shù)據(jù)連接方式,應(yīng)該是一個SQL運動員的基本功了。
4.函數(shù)應(yīng)用
函數(shù)庫,其實就像是一個數(shù)據(jù)處理與分析的百寶箱,收藏著各種場景下需要用到的車輪子。對函數(shù)庫的熟悉和掌握,可以較好地提升工作效率,也讓計算腳本顯得輕量而簡潔。畢竟站在通用的函數(shù)的肩膀上,很多統(tǒng)計邏輯是可以一步到位的,不需要沉迷于山重水復(fù)的自主構(gòu)造里。以下參考TDW的函數(shù)庫分類,將日常所用的函數(shù)細分為幾個子類別。
4.1數(shù)學(xué)函數(shù):SQL里的數(shù)學(xué)函數(shù)主要和數(shù)值處理有關(guān),有取值函數(shù)和變換函數(shù)等。取值函數(shù)包括round四舍五入,abs取絕對值,ceil向上取整等,主要用于對具體數(shù)值的細節(jié)調(diào)整;變換函數(shù)則會改變該字段的數(shù)據(jù)分布形態(tài),如正弦sin,余弦cos,或者開根號sqrt等。
4.2聚合函數(shù):在數(shù)據(jù)聚合中,選擇了具體字段作為聚合維度后,之后便是應(yīng)用各種聚合函數(shù)得到匯總值的過程。其中有簡單聚合函數(shù)如count計數(shù),sum求和,avg求平均,也可以基于分布特征,max/min取極值,std取標(biāo)準(zhǔn)差,variance取方差,另外若在聚合過程中涉及分區(qū)處理的話,也有rank,first/last_value,row_number等函數(shù)可以應(yīng)用。
4.3時間和日期函數(shù):對時間數(shù)據(jù)的處理,同樣也是SQL里的一個重要課題,主要細分為時間的加減,取值和轉(zhuǎn)換這么三類。其中時間加減里,又涉及不同的時間維度,比如按日維度有date_diff,date_add,date_sub等,按月維度有month_between,add_months等。時間取值函數(shù)則是在一個詳細的時間戳里,取出自己想要的部分,如year,month,day,hour等。時間轉(zhuǎn)換函數(shù)則是時間形式的切換,如日期格式,格林尼治時間戳格式等。
4.4文本處理:數(shù)據(jù)類型可以粗糙地分為數(shù)值數(shù)據(jù)和文本數(shù)據(jù),對于文本數(shù)據(jù)的處理,也有很多對應(yīng)的函數(shù)。其中有一些簡單取值函數(shù),如通過length和size獲得字段長度和數(shù)組大小,通過upper和lower可以切換大小寫;字符串的切割與拼接,由淺入深有split,substr,concat,wm_concat等;最后正則表達式也是文本處理中一個特別重要的模塊。
4.5其它函數(shù):除了以上所盤點的一些通用函數(shù)外,其實在日常工作中會有很多垂直的業(yè)務(wù)場景,在這些特定場景下也有一些特定的函數(shù)邏輯。比如涉及數(shù)組結(jié)構(gòu)拆分與重構(gòu)時,可以應(yīng)用later view函數(shù);涉及字段編碼時,也有加密與解析函數(shù);除此之外,還有邏輯函數(shù),轉(zhuǎn)換函數(shù)等多種特殊函數(shù),在特定的場景下,這些函數(shù)其實也是必要的。
5.具體開發(fā)環(huán)境的注意點
和其它眾多語言一樣,SQL的編寫也不能脫離其自身的開發(fā)環(huán)境,不同的數(shù)據(jù)庫形態(tài),不同的IDE,都會有一些差異點和新特性。同樣的一段腳本,在A環(huán)境下可能跑的疾速如飛,在B環(huán)境下卻可能滿屏報錯,可以拿出來討論的,往往只是一些通用的邏輯和思考。除此之外,具體開發(fā)環(huán)境里的注意事項,一些細節(jié)的加速點,則是要在具體環(huán)境里去發(fā)現(xiàn)和探索。第二部分 業(yè)務(wù)實踐篇
一種語言,一個函數(shù)庫,就像是廚房里的各種廚具,它們可能或優(yōu)良或劣質(zhì),但本質(zhì)上還是一些標(biāo)準(zhǔn)化的組件。基于這些公共的組件,如何去烹制自己的美食,以及在烹制過程中的心得和思考,則屬于業(yè)務(wù)實踐的篇章。在業(yè)務(wù)實踐的過程中,不管怎樣去規(guī)范化,標(biāo)準(zhǔn)化,每個人輸出的腳本內(nèi)容,難免還是要帶上私人的特質(zhì)的,這同樣也是一個需要修習(xí)的部分。
以下通過三個問題點,來引出筆者在實際工作中的一些反思。其中如何盡量地少給未來挖坑,介紹了一些反面的案例,這些反面的細節(jié)在積累之后,容易引起整個系統(tǒng)的不穩(wěn)定性;如何健康地做數(shù)據(jù)規(guī)劃,則是從一個創(chuàng)建者的身份,展開幾點數(shù)據(jù)規(guī)劃的思考;但不管做了多么縝密和豐富的準(zhǔn)備,隨著時間推移,總還是會出現(xiàn)變化的,所以在破舊與立新之間要找到平衡點。這些反思是基于工作實踐的層面,難免會有幼稚和紕漏之處,還請讀者輕拍。
1.如何盡量地少給未來挖坑
不要起一些奇奇怪怪的名字:SQL里的數(shù)據(jù)庫表,就像是其它語言里的對象,往往是數(shù)量極大的,并在時間的推進,業(yè)務(wù)的發(fā)展中,基數(shù)會持續(xù)放大。所以對于數(shù)據(jù)庫名,數(shù)據(jù)表名,字段名,尤其是一些主鍵,索引的命名,務(wù)必要有一套相對統(tǒng)一的規(guī)范。缺乏規(guī)范的約束時,你無法想象人的想象力會多么發(fā)散,這些奇奇怪怪的名字,最終會把人深深地困住的。
不要并行維護多個版本的數(shù)據(jù):因為業(yè)務(wù)的拓展,數(shù)據(jù)背后的口徑可能有所變更,基于舊有的數(shù)據(jù)報表,簡單修改后出一份新數(shù)據(jù),是一種成本較低的實現(xiàn)方式。但最好不要并行維護多個版本的數(shù)據(jù),當(dāng)版本超過3個的時候,維護的成本是直線拉升的。所以當(dāng)要做數(shù)據(jù)變更時,一方面可以降低變更的頻率,另一方面盡量在原有報表里修改,并替換掉原有口徑。
不要在單個腳本里寫過多內(nèi)容:統(tǒng)計邏輯的實現(xiàn),就像是傳統(tǒng)工業(yè)里的不同工序,這個過程里存在兩種極端。一種是把一個邏輯在橫向/縱向細分為太多的工序,部署過多計算任務(wù),形成很大冗余;另一種是完全打包在一個大腳本里,這種情況也不利于問題定位和中間數(shù)據(jù)處理。所以不要在單個腳本里寫過多內(nèi)容,可以將它拆分進最優(yōu)數(shù)量的計算任務(wù)中。
要有一些基本的約束條件:做一些事情時,不僅要立足于眼下的問題點,也要考慮一下未來可能發(fā)生的變化。就像是造一座橋,修一條路,總要考慮極限情況下的壓力。很多的數(shù)據(jù)異常,往往是在業(yè)務(wù)變化時,舊有的邏輯不能適應(yīng)當(dāng)前的場景。所以在一開始寫腳本時,要考慮一下未來的場景,有一些基本的約束條件,這樣會讓所部署的任務(wù)會有較好的穩(wěn)定性。
要采用盡量簡潔的寫法:能夠一步到位的統(tǒng)計邏輯,就采用盡量簡潔的寫法,千萬不要去繞圈子。尤其是一些核心腳本,是要在不同環(huán)節(jié),不同階段的同事之間傳承的,很多人并不了解當(dāng)時的業(yè)務(wù)背景和需求邏輯,如果寫法太繞圈子的話,最終就把大家一起繞進去了。
2.如何健康地做數(shù)據(jù)規(guī)劃
數(shù)據(jù)規(guī)劃是一個層級比較中等的概念,往下一層,做需求開發(fā)時,往往只聚焦于特定的需求點,并不涉及其它內(nèi)容;往上一層,做數(shù)據(jù)工程的話,又是基于整個部門,整個產(chǎn)品形態(tài)的框架搭建。但數(shù)據(jù)規(guī)劃更多是應(yīng)對一個相對獨立的業(yè)務(wù)場景,所做的規(guī)劃與設(shè)計。
一個不夠好的數(shù)據(jù)規(guī)劃,可能會引發(fā)后續(xù)的諸多問題點,比如:
痛點1:PM提出要在視圖上擴展一個細分字段,覺得很簡單。我也覺得很簡單,但就是更改不了,因為這個字段在數(shù)據(jù)源處理中就舍棄了,無法從上一層數(shù)據(jù)表中獲得。
痛點2:想要重跑一個時間范圍內(nèi)的數(shù)據(jù),但這張表不是分區(qū)表,無法并行處理;想要剔除某個日期內(nèi)的數(shù)據(jù),但不同表中時間格式不一致,導(dǎo)致處理結(jié)果有差漏等。
痛點3:同樣的一條統(tǒng)計鏈路,部分為了保障每日推送而獨立出去,部分為了特性統(tǒng)計而獨立出去,由此產(chǎn)生了眾多的細分鏈路,此后的變更也要在不同鏈路之間同步處理。
?以上列出的三個痛點,分別對應(yīng)了原始信息的保留,技術(shù)實現(xiàn)的最優(yōu)路徑,以及計算任務(wù)的細分問題等,不過也只是數(shù)據(jù)規(guī)劃需要思考的其中一部分問題點。在不同的業(yè)務(wù)場景下里,可以有不同的數(shù)據(jù)規(guī)劃思路。粗糙地講,可以分為數(shù)據(jù)基礎(chǔ)層和業(yè)務(wù)細分層獨立處理。
數(shù)據(jù)基礎(chǔ)層:做一個數(shù)據(jù)規(guī)劃,首先應(yīng)該要考慮數(shù)據(jù)本身,在數(shù)據(jù)基礎(chǔ)層里,應(yīng)暫時拋開具體的業(yè)務(wù)細節(jié),以數(shù)據(jù)為重。這個時候應(yīng)在處理中盡量地保留原始信息,同時要對數(shù)據(jù)源做好質(zhì)量檢驗,第一道防線,往往是很重要的一道防線。原始信息要完整,數(shù)據(jù)質(zhì)量要合格,任務(wù)部署要輕便,這些是數(shù)據(jù)基礎(chǔ)層的一些目標(biāo),也是后續(xù)工作的一個前提。
業(yè)務(wù)細分層:數(shù)據(jù)基礎(chǔ)要獨立而完整,面向數(shù)據(jù)本身;業(yè)務(wù)細分層則可以去細分實現(xiàn),面向業(yè)務(wù)細節(jié)。基于不同的業(yè)務(wù)目標(biāo),可以從源表中篩選不同的內(nèi)容,用于應(yīng)對特定的場景。這樣的數(shù)據(jù)+業(yè)務(wù)層級,形成了一種“總-分”結(jié)構(gòu),是數(shù)據(jù)規(guī)劃的其中一種實現(xiàn)方式。
3.如何在破舊與立新之間尋找平衡點
很多的工作,都是基于當(dāng)下的場景,即使做了詳盡的規(guī)劃和思考,也不可能應(yīng)對未來的所有問題。當(dāng)業(yè)務(wù)逐漸地深入發(fā)展時,很多的內(nèi)容也需要做一些同步處理,小的層面上是一些數(shù)據(jù)表和視圖的表更,大的層面上可能涉及計算平臺的遷移,視圖系統(tǒng)的重建等。
破舊與立新,往往是一個長期存在的問題點。不需要每天都進行自我“革命”,但改良和優(yōu)化,則是一個長期過程。在這個長期過程里,我們需要在破舊與立新之間尋找到平衡點。
以上是筆者在TDW體系下寫SQL的一些實踐和思考,歡迎評論區(qū)留言關(guān)注~
從微信支付看研發(fā)如何提高運營效能
全民K歌 7.0 [更好看] — 產(chǎn)品設(shè)計思考與總結(jié)
帶你了解騰訊最堅實的支撐事業(yè)群
總結(jié)
以上是生活随笔為你收集整理的sql怎么撤回update_腾讯SQL“现役运动员”给你的实践小技巧的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: diskgeniusv4.4.0_入门T
- 下一篇: cross_val_score 如何对孤