摘要:高效使用數據庫是一個合格的開發工程師的必備技能,如何使用DWS進行高效開發,提升應用效率,技術干貨來嘍~~~
高效使用數據庫是一個合格的開發工程師的必備技能,如何使用DWS進行高效開發,提升應用效率,下面這5個要點可以指導你進行DWS開發。
一、怎么創建索引?
•在經常需要搜索查詢的列上創建索引,可以加快搜索的速度。
•在作為主鍵的列上創建索引,強制該列的唯一性和組織表中數據的排列結構。
•在經常使用連接的列上創建索引,這些列主要是一些外鍵,可以加快連接的速度。
•在經常需要根據范圍進行搜索的列上創建索引,因為索引已經排序,其指定的范圍是連續的。
•在經常需要排序的列上創建索引,因為索引已經排序,這樣查詢可以利用索引的排序,加快排序查詢時間。
•在經常使用WHERE子句的列上創建索引,加快條件的判斷速度。
•為經常出現在關鍵字ORDER BY、GROUP BY、DISTINCT后面的字段建立索引。
二、怎么建立表結構?
建表的原則:
(1)、表數據均勻分布在各個DN上,以防止單個DN對應的存儲設備空間不足造成集群有效容量下降。選擇合適分布列,避免數據分布傾斜可以實現該點
(2)、表Scan壓力均勻分散在各個DN上,以避免單DN的Scan壓力過大,形成Scan的單節點瓶頸。分布列不選擇基表上等值filter中的列可以實現該點
(3)、減少掃描數據數據量。通過分區的剪枝機制可以實現該點
(4)、盡量極少隨機IO。通過聚簇/局部聚簇可以實現該點
(5)、盡量避免數據shuffle,減小網絡壓力。通過選擇join-condition或者group by列為分布列可以最大程度的實現這點
怎么選擇存儲類型:
a) 行存表:點查詢,返回記錄少,基於索引的簡單查詢;增刪改較多的表
b) 列存表:大表,統計分析類查詢,group、join比較多的表
怎么選擇分布方式:
a) 復制表:適用於記錄較少的的維度表
b) 哈希表:數據量比較大的實事表
怎么選擇分布列:
a) 列值應比較離散,以便數據能夠均勻分布到各個DN。例如,考慮選擇表的主鍵為分布列,如在人員信息表中選擇身份證號碼為分布列
b) 在滿足第一條原則的情況下盡量不要選取存在常量filter的列。例如,表dwcjk相關的部分查詢中出現dwcjk的列zqdh存在常量的約束(例如zqdh=’000001’),那么就應當盡量不用zqdh做分布列
c) 在滿足前兩條原則的情況,考慮選擇查詢中的連接條件為分布列,以便Join任務能夠下推到DN中執行,且減少DN之間的通信數據量
怎么使用PCK局部聚簇:
a) 受基表中的簡單表達式約束。這種約束一般形如col op const,其中col為列名,op為操作符 =、>、>=、<=、<,const為常量值
b) 盡量采用選擇度比較高(過濾掉更多數據)的簡單表達式中的列
c) 盡量把選擇度比較低的約束col放在Partial Cluster Key中的前面
d) 盡量把枚舉類型的列放在Partial Cluster Key中的前面
三、怎么創建分區表?
分區表創建使用原則如下
1、 對於記錄數小於100萬的表,可以不使用分區表。
2、 對於記錄數超過100萬、低於500萬的表,宜使用分區表。
3、 對於記錄數超過500萬且空間占用超過2GB的表,應使用分區表。
4、 分區表的單個分區記錄數可超過500萬,空間占用不宜超過2GB。
5、 暫不支持復合分區、二級分區。
6、 對於如下特殊場景,可不使用分區表:
A) 備份表或者老化表
此類數據表存放應用系統不再使用到的數據,在聯機程序和批量程序均不訪問此類數據,僅用於某些特殊場景下(例如生產問題排查、公/檢/法查詢等)使用,通過直接查詢數據庫的方式訪問,相關數據應使用truncate或者drop來進行清理。
B) 交換分區表
此類數據表是存放分區表某個分區的數據,通過交換分區技術與分區表進行數據傳遞。
C) 采用分庫分表設計的表
此類數據表已通過分庫、分表策略進行了數據分割,可不使用分區表。
D) 批量處理中使用到的中間表、臨時表,可不使用分區表。
E) 外公司產品中達到分區表條件的數據表,經評估如因外公司產品原因無法分區,應按應用維度提交規范例外,並隨規范例外管理流程定期與外公司確認分區的可行性。
F) 對於存量應用達到分區條件的數據表,如應用規划廢止,可不使用分區表。
7、 對於記錄數超過100萬且需要進行歷史數據清理的表,宜通過業務發生日期等數據清理條件進行分區,通過分區truncate或exchange技術進行數據清理。
8、 分區的關鍵字應是where字句中的查詢條件之一,分區的關鍵字不宜進行更新操作,避免數據因分區條件變化進行分區移動,導致性能下降。
9、 從數據的維護和使用效率情況看,除非是業務的特別需求,宜使用分區索引並設計為前綴分區索引。
10、 當表中的數據量很大時,應當對表進行分區,一般需要遵循以下原則:
− 應使用具有明顯區間性的字段進行分區,比如日期、區域等字段上建立分區。
− 分區名稱應當體現分區的數據特征。例如,關鍵字+區間特征。
− 將分區上邊界的分區值定義為MAXVALUE,以防止可能出現的數據溢出。
典型的分區表定義如下:
CREATE TABLE staffS_p1 ( staff_ID NUMBER(6) not null, FIRST_NAME VARCHAR2(20), LAST_NAME VARCHAR2(25), EMAIL VARCHAR2(25), PHONE_NUMBER VARCHAR2(20), HIRE_DATE DATE, employment_ID VARCHAR2(10), SALARY NUMBER(8,2), COMMISSION_PCT NUMBER(4,2), MANAGER_ID NUMBER(6), section_ID NUMBER(4) ) PARTITION BY RANGE (HIRE_DATE) ( PARTITION HIRE_19950501 VALUES LESS THAN ('1995-05-01 00:00:00'), PARTITION HIRE_19950502 VALUES LESS THAN ('1995-05-02 00:00:00'), PARTITION HIRE_maxvalue VALUES LESS THAN (MAXVALUE) );
四、怎么選擇數據類型?
a) 盡量使用執行效率比較高的數據類型,一般來說整型數據運算(包括=、>、<、≧、≦、≠等常規的比較運算,以及group by)的效率比字符串、浮點數要高
b) 盡量使用短字段的數據類型,長度較短的數據類型不僅可以減小數據文件的大小,提升IO性能;同時也可以減小相關計算時的內存消耗,提升計算性能。比如對於整型數據,如果可以用smallint就盡量不用int,如果可以用int就盡量不用bigint
c) 使用一致的數據類型,表關聯列盡量使用相同的數據類型。如果表關聯列數據類型不同,數據庫必須動態地轉化為相同的數據類型進行比較,這種轉換會帶來一定的性能開銷
d) 應盡量使用高效數據類型。選擇數值類型時,在滿足業務精度的情況下,選擇數據類型的優先級從高到低依次為整數、浮點數、NUMREIC
e) 對於字符串數據,建議使用變長字符串數據類型,並指定最大長度。請務必確保指定的最大長度大於需要存儲的最大字符數,避免超出最大長度時出現字符截斷現象。除非明確知道數據類型為固定長度字符串,否則,不建議使用CHAR(n)、BPCHAR(n)、NCHAR(n)、CHARACTER(n)
f) 對於日期類型,時間精度要求大於等於1天的,可以使用varchar2存儲;時間精度要求大於等於1秒的,宜使用date類型;時間精度要求小於1秒的,應使用timestamp類型
g) 在需要數據類型轉換(不同數據類型進行比較或轉換)時,應使用強制類型轉換,以防隱式類型轉換結果與預期不符
五、 sql開發經驗總結
a) 使用union all代替union,union在合並兩個集合時會執行去重操作,而union all則直接將兩個結果集合並、不執行去重。執行去重會消耗大量的時間,因此,在一些實際應用場景中,如果通過業務邏輯已確認兩個集合不存在重疊,可用union all替代union以便提升性能。
b) join列增加非空過濾條件,若join列上的NULL值較多,則可以加上is not null過濾條件,以實現數據的提前過濾,提高join效率
c) not in轉not exists,not in語句需要使用nestloop anti join來實現,而not exists則可以通過hash anti join來實現。在join列不存在null值的情況下,not exists和not in等價。因此在確保沒有null值時,可以通過將not in轉換為not exists,通過生成hash join來提升查詢效率
d) 避免對索引使用函數或表達式運算,對索引使用函數或表達式運算會停止使用索引轉而執行全表掃描
e) 盡量避免在where子句中使用!=或<>操作符、null值判斷、or連接、參數隱式轉換
f) 對復雜SQL語句進行拆分,對於過於復雜並且不易通過以上方法調整性能的SQL可以考慮拆分的方法,把SQL中某一部分拆分成獨立的SQL並把執行結果存入臨時表
本文分享自華為雲社區《DWS開發指導》,原文作者: 獨孤求敗馬? 。