首頁>Club>
sql最佳化已經到極限了,還是很慢
8
回覆列表
  • 1 # 會點程式碼的大叔

    不知道開發的同學有沒有遇到過類似這樣的需求:

    相同型別的資料在多個系統中,如果要得到全部的資訊,就要連續調多個系統的介面;

    業務複雜,一個需求需要關聯幾張表甚至幾十張表才能得到想要的結果;

    系統做了分庫分表,但是需要統計所有的資料。

    那麼此類需求要如何滿足呢?我們選擇了“透過 ETL 提前進行資料整合”的方案。

    什麼是 ETL

    說到ETL,很多開發夥伴可能會有些陌生,更多的時候 ETL 是用在大資料、資料分析的相關崗位;我也是在近幾年的工作過程中才接觸到ETL的,現在的專案比較依賴 ETL,可以說是專案中重要的一部分。

    ETL 是三個單詞的縮寫:

    Extraction:抽取、提取;就是把資料從資料庫裡面取出來;

    Transformation:轉換;包括但不限於:資料篩選校驗、資料關聯、資料內容及結構的修改、運算、統計等等;

    Loading:載入;將處理後的資料儲存到目標資料庫。

    從這三個單詞基本可以瞭解 ETL 的作用:將各個業務系統的資料,透過抽取、清洗、轉換之後,將加工後的資料落地到資料庫中(資料倉庫);在這個過程中,ETL 可以將分散、零亂、標準不統一的資料整合到一起。

    使用場景

    我接觸過的專案,使用ETL工具的場景有這個幾種:

    1. 報表、BI系統:

    在公司建設的初期,業務比較少,系統也比較少,一臺資料庫就搞定了;隨著公司業務的增加,業務系統被拆成很多系統;隨著資料量的繼續增加,單個系統的資料增加到一定程度的時候,也做了分庫分表;

    2. 跨系統的資料加工或查詢:

    我們現在所在公司,業務系統有幾百個,由於業務流程比較複雜,前端系統在做業務操作的時候,在正式提交交易之前,有很多業務校驗;

    比如要查詢客戶在 X 系統的交易歷史,在 Y 系統的交易歷史,在 Z 系統的交易歷史;那麼就需要分別呼叫 X、Y、Z 系統的介面,這個對前端系統很不友好,那麼通常的解決方案是什麼?

    A 方案:做一箇中間服務,中間服務去呼叫 X、Y、Z 系統的介面,客戶端直接呼叫這個中間服務;這種方案只是把前端要做的事情,轉移到了中間服務;

    B 方案:整合 X、Y、Z 三個系統,建服務中臺;這種方法很好,但是極為難,對於很多公司來說,別說把 X、Y、Z 三個系統整合成一箇中臺系統,就是其中一個系統本身進行重構,都是非常困難的;

    C 方案:把 X、Y、Z 三個系統中需要的資料,透過 ETL 抽取加工到一個數據倉庫中,對外提供服務;這個系統最大的好處是在不改造 X、Y、Z 三個系統的前提下,又可以實現跨系統的查詢。

    我們在 C 方案的基礎上又往前做了一步,就是將落地後的資料又做了一次加工,將需要跨表關聯的資料,提前關聯好存入 MongoDB 中,對外提供查詢服務;這樣可以將多表關聯查詢,變成了單表查詢。

    吐資料 VS 抽資料

    接上文中第二個例子中的 C 方案,有些同學可能會有個疑問:資料抽取,需要抽取哪些資料呢?為什麼不讓這些系統把資料吐出來呢?

    答案也簡單,“有的時候,資料不一定能吐出來”。

    其他商用資料庫,比如 Oracle、DB2 等,我也查閱過相關的資料,也是有觸發器機制,可以當資料發生變化的時候通知出來,比如呼叫一段程式,將資料傳送到訊息佇列中,再由其他程式監聽訊息佇列做後續處理。

    不管什麼型別的資料庫,這種“吐資料”的方案,對於基礎設施的要求都比較高,並且對原有系統有一定的侵入性;所以我們採用了對原有系統侵入性更小的方案:主動抽資料。

    ETL 方案的優缺點

    1. 優點

    侵入性較低,資料來源系統只需要開通資料庫的訪問許可權即可,為保證資料抽取對業務的影響,通常是訪問源系統的備庫,並且單獨設定一個只讀許可權的資料庫使用者;

    支援不同型別資料來源的資料抽取,比如源庫有 Mysql、DB2、Oracle,透過 ETL 也可以輕鬆搞定;

    資料整合,將不同業務系統的相同資料整合在一起,比如有些系統 M/F 表示男女,有些系統 1/0 表示男女,ETL 在抽取加工後轉換成統一的編碼;

    2. 缺點

    比較致命的一個缺點,就是資料抽取和加工有一定的延遲,需要根據業務場景進行評估,是否接受這個延遲;

    可能會受到源庫表結構變化的影響;

    如果源庫中的表沒有時間戳,或者時間戳不準確,那麼增量抽取就變得很困難;

    需要招聘 ETL 開發崗,從我目前的經驗看,不是特別好招。

  • 2 # Variazioni

    這種情況一般都是因為前期設計沒做好。。資料結構重構一遍吧。。。。

    或者分開查。連表的邏輯放到程式裡做。。

  • 3 # 魚於非技術

    方法又很多

    在不大改架構情況下分表分庫建索引是一個選擇

    除此以外 還可以考慮用物化檢視,oracle和pg都是支援的

  • 4 # 學習驅動前進的腳步

    遇到和你差不多的情況,十幾張報表,幾百個單位在查,之前資料量小,沒事,後面業務量到達千萬級別,就會把線上系統跑崩潰,第一步是再弄一個數據庫,讀寫分離,專門負責報表讀取,這樣就不會影響線上交易那個資料庫,之後再做etl,定時抽取,抽取新生成的資料,還有歷史資料中狀態產生變化的資料也重新抽取,形成寬表,再把寬表做成分割槽表,按時間分割槽,讓客戶每次查詢,都必選時間,設計分割槽表索引的時候,要根據客戶查詢的習慣,返回資料量大小,合理選擇全域性索引或者分割槽索引,合理使用組合索引

  • 5 # 低調守護者

    本人寫sql也有好多年了,但一次查詢關聯10幾張表的情況還沒碰到過。但是這種情況還是有最佳化的方法的。

    首先查詢關聯10幾張表,不管是內聯還是外聯,不管怎麼最佳化你的sql語句,比如建索引,指定返回列,where加限制條件,我相信你的結果還是會很慢的。 因為這已經不是技術層面可以去最佳化的,建議還是從業務層面去最佳化。

    不管多複雜的業務我們都可以去分解它,將它分解成一段段的子結果集,可以將它們作為臨時表或者結果表儲存起來,在最終的查詢時可以從分解的子集去查詢,這樣就避免了多表關聯,而且這樣程式碼可讀性,可維護性更好。也符合我們設計程式碼的基本原則。

  • 6 # 添添Vlog

    sql一次查詢關聯十幾張表,這太誇張了,最多容忍一次查詢5張表或以下,不然那笛卡爾積等太可怕了,一次十幾張表的關聯多半都是表結構沒設計好,從下面這些方法去最佳化吧:

    最佳化方法

    1、部分表可以冗餘經常查詢的欄位

    2、設計表的時候滿足第二正規化就好了,這樣減少表關聯

    3、一些名稱等欄位資料,查詢時可以利用redis映射出來,沒必要再關聯表去查詢,減少關聯表的數量

    4、把一些邊緣表的資料快取起來

    5、涉及到orderby、groupby的欄位,就建下索引,減少檔案排序的產生;儘量都能保證命中索引,最佳化前可以先explain

    6、索引不要盲目去建,要適量合適去建,不然會拖慢查詢,適得其反

    最後

    sql的最佳化和設計是繞不開的,希望大家都可以參考下方法,再結合自己的業務去最佳化,不要盲目去最佳化。

  • 7 # 想早睡的臭小子

    這種查詢大機率不是要求查實時資料,就是統計報表用的,那你為什麼非得要從原資料結構上做這種複雜查詢?為什麼不能去做etl之後再最佳化資料結構?一條路走到黑等著的就肯定是死衚衕。如果是要求查詢實時資料,那就用業務程式碼去簡化查詢邏輯,用業務程式碼做資料計算和拼接,把變動頻率低的資料做快取,把讀庫做分庫分表,辦法多的是,你除了寫sql就不會別的了?

  • 8 # hichenchen

    我記得阿里巴巴開發手冊規定了一次join不能超過3張表,為什麼會有這種規範,顯然是在某種業務場景下要多做資料冗餘,方便查詢,效能更高,帶來的缺點就是更新可能會更復雜,而三正規化結構更清晰,資料量大效能必然會下降,所以要有取捨,設計表結構時,要三正規化和反正規化結合而用,否則那些頭部網際網路公司哪個業務不復雜,雖然可以用es和hbase,但如果都是join十多張表那都不用玩了,我所在的物流公司,業務也是非常複雜,剛來公司的時候就發現,前期表結構規劃不合理,也沒有采用es等中介軟體做資料聚合,一個簡單的例子,掃條碼碼入庫,全鏈路壓測吞吐連10都不到,走讀下程式碼,一個獲取訂單資訊的查詢10張表,整個流程中還有多個系統的同步呼叫,基本上隨便都是七八張表以上,本身也是個新專案,跑了一年左右了,量沒有特別大,但是業務複雜的牽一髮動全身,這種系統就別想重構了,大公司你懂的,所以首先就是各種sql最佳化,能提高多少是多少,待了半年左右就走了,再待下去量上來,系統扛不住,天天就得加班挨叼了。所以說一個好的設計,至少可以讓你係統能抗的住未來一兩年的業務的增長。

  • 9 # IT技術管理那些事兒

    一次查詢需要關聯十幾張表,是不是報表查詢的維度太多了?

    關聯子查詢的執行邏輯和通常的SELECT語句的執行邏輯完成不一樣。這就是SQL關聯子查詢難以理解的原因。

    在關聯查詢時要注意:where子句中一定要包含表之間的連線條件,如 line.lid=track.lid,否則查詢結果會完全超乎我們的想象,造成不必要的麻煩。我看了一下回答,感覺很少有人能說到點子上。

    先說說需求吧,一次十幾張表,這是什麼需求?是不是理解錯誤,還是說這需求必須要做?建議和業務溝通溝通。

    如果說,需求真的不能改,那就用檢視吧。

    使用檢視時,會執行視圖裡的sql查詢語句創建出一張臨時表。

    可以將頻繁使用的select語句儲存成檢視,這樣就不用每次都重新書寫了。

    使用檢視需要注意什麼?

    (1)避免在檢視的基礎上再次建立檢視,因為這樣多重檢視會降低sql的效能和效率;

    (2)不能往視圖裡插入資料,不然會報錯。

    最後,其實做報表真的不復雜,你要是用好報表工具FineReport,寫sql那真的是很輕鬆,回覆“報表”就能有了。

  • 10 # 夢想63863596

    最簡單的方法 就是針對查詢關鍵字做專用的冗餘索引表,當你那些關聯有更新時,如果更新和索引有關,就非同步更新到此索引表。

  • 11 # 五子棋寶典

    如果大部分是關聯碼錶、引數、機構、使用者,用快取或主業務資料獲取後再補充輔助資訊。如果是在OLTP中做複雜報表,可以用ETL做資料抽取加工聚合後在做報表。如果是數模完全依賴了三正規化,可以考慮適當冗餘不變化的欄位。如果就是業務邏輯就是複雜,可以將部分邏輯拆解到Java等業務邏輯中實現。

  • 12 # 你是豬頭666

    這種的最好單表查吧。一個個查,先查基礎資料,把結果當做條件去查業務資料,應該還是比較快,表聯合的笛卡爾積太慢了

  • 中秋節和大豐收的關聯?
  • 經常加班到很晚,你的家人是什麼態度?