{eval=Array;=+count(Array);}

国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

問答專欄Q & A COLUMN

sql一次查詢需要關聯十幾張表,有什么優化方案么?

MarvinZhangMarvinZhang 回答0 收藏1
問題描述:sql優化已經到極限了,還是很慢
收藏問題

10條回答

ghnor

ghnor

回答于2022-06-28 13:46

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

  • 相同類型的數據在多個系統中,如果要得到全部的信息,就要連續調多個系統的接口;

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

  • 系統做了分庫分表,但是需要統計所有的數據。

那么此類需求要如何滿足呢?我們選擇了“通過 ETL 提前進行數據整合”的方案。

什么是 ETL

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


ETL 是三個單詞的縮寫:

  • Extraction:抽取、提??;就是把數據從數據庫里面取出來;

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

  • Loading:加載;將處理后的數據保存到目標數據庫。

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



使用場景

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

1. 報表、BI系統:

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

這時候領導、業務人員在用數據做分析的時候,數據來源可能是多個系統的多張表,這時候企圖通過一個復雜的 SQL 跑出來結果就很困難了;通常公司會建立一個數據倉庫,通過ETL工具把數據抽取到數據倉庫中,再做數據的擬合和展示。

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 方案,有些同學可能會有個疑問:數據抽取,需要抽取哪些數據呢?為什么不讓這些系統把數據吐出來呢?

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

  • MySQL 數據庫往外吐數據有比較成熟的中間件,比如 Canal,它可以通過監聽 Mysql 的 binlog 日志來獲取數據,binlog 設置為 row 模式,能夠獲取到每一條新增、刪除、修改的日志,同時還能獲取到修改前后的數據;

  • 其他商用數據庫,比如 Oracle、DB2 等,我也查閱過相關的資料,也是有觸發器機制,可以當數據發生變化的時候通知出來,比如調用一段程序,將數據發送到消息隊列中,再由其他程序監聽消息隊列做后續處理。

不管什么類型的數據庫,這種“吐數據”的方案,對于基礎設施的要求都比較高,并且對原有系統有一定的侵入性;所以我們采用了對原有系統侵入性更小的方案:主動抽數據。


ETL 方案的優缺點

1. 優點

  • 侵入性較低,數據源系統只需要開通數據庫的訪問權限即可,為保證數據抽取對業務的影響,通常是訪問源系統的備庫,并且多帶帶設置一個只讀權限的數據庫用戶;

  • 支持不同類型數據源的數據抽取,比如源庫有 Mysql、DB2、Oracle,通過 ETL 也可以輕松搞定;

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

2. 缺點

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

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

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

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

我將持續分享Java開發、架構設計、程序員職業發展等方面的見解,希望能得到你的關注。

評論0 贊同0
  •  加載中...
劉東

劉東

回答于2022-06-28 13:46

關聯表都是有復雜度的,一般不超過三個,不然后期維護很難看懂邏輯。

sql優化

可以試試拆分sql,在代碼里多次查詢再主鍵關聯,最后合并數據。



索引

如果很慢的話可以調查一下是不是sql有笛卡爾積現象,沒有加主鍵或缺少索引。一般查詢慢都是缺少索引,或者索引沒用上。


分頁

業務邏輯上要加分頁,不要一次查太大量的數據。


評論0 贊同0
  •  加載中...
用戶84

用戶84

回答于2022-06-28 13:46

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

評論0 贊同0
  •  加載中...
SolomonXie

SolomonXie

回答于2022-06-28 13:46

給你三個建議

建議一:

你應該找需求人員,了解清楚需求,看看能否減少關聯表

建議二:

關聯十幾張表,很大概率,你這個是報表展示的需求,可以用etl工具抽取必要的字段,然后預處理一些簡單匯總,這樣能少掃描記錄,提升查詢速度

建議三:

建議使用適合做數據分析的平臺,如Hadoop,hbase,tispark

評論0 贊同0
  •  加載中...
OldPanda

OldPanda

回答于2022-06-28 13:46

什么業務需要關鍵這么多表檢索?用物化視圖做多次查詢,或先優化一下腦子

評論0 贊同0
  •  加載中...
zhaochunqi

zhaochunqi

回答于2022-06-28 13:46

這種查詢大概率不是要求查實時數據,就是統計報表用的,那你為什么非得要從原數據結構上做這種復雜查詢?為什么不能去做etl之后再優化數據結構?一條路走到黑等著的就肯定是死胡同。如果是要求查詢實時數據,那就用業務代碼去簡化查詢邏輯,用業務代碼做數據計算和拼接,把變動頻率低的數據做緩存,把讀庫做分庫分表,辦法多的是,你除了寫sql就不會別的了?

評論0 贊同0
  •  加載中...
livem

livem

回答于2022-06-28 13:46

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

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

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

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

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

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

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

使用視圖需要注意什么?

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

(2)不能往視圖里插入數據,不然會報錯。

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

評論0 贊同0
  •  加載中...
Yi_Zhi_Yu

Yi_Zhi_Yu

回答于2022-06-28 13:46

互聯網時代倡導非關系型數據庫,首先保證單表查詢速度到極致,然后程序設計數據關聯最終算出結果,這才是解決之道。強烈依賴關系型數據庫是一種偷懶的方式,當今海量數據時代,關系型數據庫用武之地也就剩下對速度要求不高的后臺統計和用戶量低的場景。

評論0 贊同0
  •  加載中...
hsluoyz

hsluoyz

回答于2022-06-28 13:46

良好的設計數據庫,這種情況往往是糟糕的數據庫設計的問題。找個對數據庫有深入了解大牛,幫忙規劃一下,要不了幾天,但很解決問題。

評論0 贊同0
  •  加載中...
Simon_Zhou

Simon_Zhou

回答于2022-06-28 13:46

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

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

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

評論0 贊同0
  •  加載中...

最新活動

您已邀請0人回答 查看邀請

我的邀請列表

  • 擅長該話題
  • 回答過該話題
  • 我關注的人
向幫助了您的網友說句感謝的話吧!
付費偷看金額在0.1-10元之間
<