① Ku:Spark sql操作Ku
摘要: Spark SQL , Ku
參考 https://github.com/xieenze/SparkOnKu/blob/master/src/main/scala/com/spark/test/KuCRUD.scala
引入 spark-core_2.11 , spark-sql_2.11 , ku-spark2_2.11 , hadoop-client 依賴包
指定 ku.master" , ku.table ,如果讀取超時加入 ku.operation.timeout.ms 參數
或者
寫入數據可以使用dataframe的 write 方法,也可以使用 kuContext 的 updateRows , insertRows , upsertRows , insertIgnoreRows 方法
直接調用dataframe的write方法指定 ku.master , ku.table ,只支持 append 模式,對已有key的數據自動更新
調用kuContext的 upsertRows 方法,效果和dataframe調用write append模式一樣
調用kuContext insertRows , insertIgnoreRows 方法,如果插入的數據key已存在insertRows直接報錯,insertIgnoreRows忽略已存在的key,只插入不存在的key
調用kuContext updateRows 方法,對已經存在的key數據做更新,如果key不存在直接報錯
使用已有dataframe的schema建表
使用 StructType 自定義schema
刪除表和判斷表是否存在
② Mysql某個表有近千萬數據,CRUD比較慢,如何優化
數據千萬級別之多,佔用的存儲空間也比較大,可想而知它不會存儲在一塊連續的物理空間上,而是鏈式存儲在多個碎片的物理空間上。可能對於長字元串的比較,就用更多的時間查找與比較,這就導致用更多的時間。
可以做表拆分,減少單表欄位數量,優化表結構。
在保證主鍵有效的情況下,檢查主鍵索引的欄位順序,使得查詢語句中條件的欄位順序和主鍵索引的欄位順序保持一致。
主要兩種拆分 垂直拆分,水平拆分。
垂直分表
也就是「大表拆小表」,基於列欄位進行的。一般是表中的欄位較多,將不常用的, 數據較大,長度較長(比如text類型欄位)的拆分到「擴展表「。 一般是針對 那種 幾百列的大表,也避免查詢時,數據量太大造成的「跨頁」問題。
垂直分庫針對的是一個系統中的不同業務進行拆分,比如用戶User一個庫,商品Proct一個庫,訂單Order一個庫。 切分後,要放在多個伺服器上,而不是一個伺服器上。為什麼? 我們想像一下,一個購物網站對外提供服務,會有用戶,商品,訂單等的CRUD。沒拆分之前, 全部都是落到單一的庫上的,這會讓資料庫的單庫處理能力成為瓶頸。按垂直分庫後,如果還是放在一個資料庫伺服器上, 隨著用戶量增大,這會讓單個資料庫的處理能力成為瓶頸,還有單個伺服器的磁碟空間,內存,tps等非常吃緊。 所以我們要拆分到多個伺服器上,這樣上面的問題都解決了,以後也不會面對單機資源問題。
資料庫業務層面的拆分,和服務的「治理」,「降級」機制類似,也能對不同業務的數據分別的進行管理,維護,監控,擴展等。 資料庫往往最容易成為應用系統的瓶頸,而資料庫本身屬於「有狀態」的,相對於Web和應用伺服器來講,是比較難實現「橫向擴展」的。 資料庫的連接資源比較寶貴且單機處理能力也有限,在高並發場景下,垂直分庫一定程度上能夠突破IO、連接數及單機硬體資源的瓶頸。
水平分表
針對數據量巨大的單張表(比如訂單表),按照某種規則(RANGE,HASH取模等),切分到多張表裡面去。 但是這些表還是在同一個庫中,所以庫級別的資料庫操作還是有IO瓶頸。不建議採用。
水平分庫分表
將單張表的數據切分到多個伺服器上去,每個伺服器具有相應的庫與表,只是表中數據集合不同。 水平分庫分表能夠有效的緩解單機和單庫的性能瓶頸和壓力,突破IO、連接數、硬體資源等的瓶頸。
水平分庫分表切分規則
1. RANGE
從0到10000一個表,10001到20000一個表;
2. HASH取模
一個商場系統,一般都是將用戶,訂單作為主表,然後將和它們相關的作為附表,這樣不會造成跨庫事務之類的問題。 取用戶id,然後hash取模,分配到不同的資料庫上。
3. 地理區域
比如按照華東,華南,華北這樣來區分業務,七牛雲應該就是如此。
4. 時間
按照時間切分,就是將6個月前,甚至一年前的數據切出去放到另外的一張表,因為隨著時間流逝,這些表的數據 被查詢的概率變小,所以沒必要和「熱數據」放在一起,這個也是「冷熱數據分離」。
分庫分表後面臨的問題
事務支持
分庫分表後,就成了分布式事務了。如果依賴資料庫本身的分布式事務管理功能去執行事務,將付出高昂的性能代價; 如果由應用程序去協助控制,形成程序邏輯上的事務,又會造成編程方面的負擔。
跨庫join
只要是進行切分,跨節點Join的問題是不可避免的。但是良好的設計和切分卻可以減少此類情況的發生。解決這一問題的普遍做法是分兩次查詢實現。在第一次查詢的結果集中找出關聯數據的id,根據這些id發起第二次請求得到關聯數據。
跨節點的count,order by,group by以及聚合函數問題
這些是一類問題,因為它們都需要基於全部數據集合進行計算。多數的代理都不會自動處理合並工作。解決方案:與解決跨節點join問題的類似,分別在各個節點上得到結果後在應用程序端進行合並。和join不同的是每個結點的查詢可以並行執行,因此很多時候它的速度要比單一大錶快很多。但如果結果集很大,對應用程序內存的消耗是一個問題。
數據遷移,容量規劃,擴容等問題
來自淘寶綜合業務平台團隊,它利用對2的倍數取余具有向前兼容的特性(如對4取余得1的數對2取余也是1)來分配數據,避免了行級別的數據遷移,但是依然需要進行表級別的遷移,同時對擴容規模和分表數量都有限制。總得來說,這些方案都不是十分的理想,多多少少都存在一些缺點,這也從一個側面反映出了Sharding擴容的難度。
ID問題
一旦資料庫被切分到多個物理結點上,我們將不能再依賴資料庫自身的主鍵生成機制。一方面,某個分區資料庫自生成的ID無法保證在全局上是唯一的;另一方面,應用程序在插入數據之前需要先獲得ID,以便進行SQL路由.
一些常見的主鍵生成策略
UUID
使用UUID作主鍵是最簡單的方案,但是缺點也是非常明顯的。由於UUID非常的長,除佔用大量存儲空間外,最主要的問題是在索引上,在建立索引和基於索引進行查詢時都存在性能問題。
Twitter的分布式自增ID演算法Snowflake
在分布式系統中,需要生成全局UID的場合還是比較多的,twitter的snowflake解決了這種需求,實現也還是很簡單的,除去配置信息,核心代碼就是毫秒級時間41位 機器ID 10位 毫秒內序列12位。
跨分片的排序分頁
一般來講,分頁時需要按照指定欄位進行排序。當排序欄位就是分片欄位的時候,我們通過分片規則可以比較容易定位到指定的分片,而當排序欄位非分片欄位的時候,情況就會變得比較復雜了。為了最終結果的准確性,我們需要在不同的分片節點中將數據進行排序並返回,並將不同分片返回的結果集進行匯總和再次排序,最後再返回給用戶。