淺談大數據量下數據庫查詢插入的優化

數據庫常常要作一些查詢與插入,可是若是查詢和插入的數據量過大的時候就會引起數據庫性能問題,下降數據庫工做效率。所以性能調優是你們在工做中都可以預見的問題,大到世界五百強的核心繫統,小到超市的庫存系統,幾乎都會有要調優的時候。面對形形色色的系統,林林總總的需求,調優的手段也是豐富多彩。
1.儘可能使語句符合查詢優化器的規則避免全表掃描而使用索引查詢
2.避免頻繁建立和刪除臨時表,以減小系統表資源的消耗。
3.儘可能避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。 
4.創建高效的索引
SQL語句的Select部分只寫必要的列;儘可能將In子查詢重寫爲Exists子查詢;
去除在謂詞列上編寫的任何數學運算;儘量不用Distinct;
因爲優化工具處理「或」邏輯可能有問題,因此儘可能採用其餘方式重寫;
確保所處理的表中數據分佈和其餘統計信息正確,並反映當前情況;儘量用UNION ALL取代UNION;
儘量減小DB2的SQL請求;儘可能將區間謂詞重寫爲Between謂詞;不要只是爲了排序而選擇某一列;
我目前所在的系統就是這麼一個有實時插入又須要大數據的查詢的一個系統。
採用了以下手段:
1,當天的記錄會放在一個獨立的表中.主要是針對實時的插入的記錄,記錄不要太多以避免插入的時候維護索引的開銷穩定在一個範圍內。
2,歷史的記錄會按天分區的形式保存在歷史表中。這個表一天只會批量的插入一次數據(用的是分區交換的方法)。
3,分區的索引對個人業務性能很差,由於要跨天 查詢。歷史查詢最長時間段是一個月的時間,若是按照一個月一個分區的話,一個分區差很少是一個億的記錄,
就算是按月分區的話,再建立分區的本地索引,若是是時間段跨了月份的話估計分區的本地索引性能估計也不行。
4,後來採用一個方案,DB層上面再放了一個緩衝層,就是我最近在測試的Timesten關係型內存數據庫,按照時間的老化策略緩衝一個月的數據。具體不展開說了。涉及的內容不少。
只是對於這個系統,我總結一下有如下須要注意的地方:
1,對於一個系統來講,若是查詢性能反應很差的話,第一個調整的地方是思考業務的需求是不是合理的?
一個查詢既要分頁獲取前面一頁或者幾頁的數據,又要根據條件獲取總的記錄數,若是符合的記錄總數是上億條的話,感受就是一個不合理的要求。
2,市場需求調研人員業務水平根本不合格。
3,前臺開發人員寫的SQL差,根本沒有調優的基本概念,術業有專攻啊。
4,若是業務需求合理,SQL的調整無非是從執行計劃開始,若是是ORACLE10g,開了cbo,能夠用 SQL優化器 (SQL Tuning Advisor :STA)
分析你的sql。
5,最近的nosq和海量分佈式的數據庫概念很熱。公司也在考慮HBASE了。
分區,
讀寫分離。
細節的優化手段你們都說了不少,我說些幾個粗略的方面:
1.使用分區表
2.並行查詢
3.按期的數據信息採集
4.能夠考慮使用sql hint(生產庫上我我的認爲仍是少指定 HINT,能夠考慮用 SQL_PROFILE固定執行計劃)
對於大數據量的處理,我一般採用以下方法:
1、對於大數據存儲的處理(如下是假設硬件指標合格的狀況)
(1)對大表進行分區,根據不一樣的業務以及數據特徵,採用不一樣的分區方法。好比,銷售,能夠考慮採用間隔分區技術,多分公司或是多部門,能夠考慮採用列表分區或是上述的組合分區等。
(2)若是硬件具有,對於大表進行分離存儲,從而減小磁盤爭用。
(3)對歷史數據進行按期的歸檔處理。好比,銷售的區間分區,能夠採用表與分區交換的技術去處理。對於含有複雜的業務的數據表的歸檔,採用PL/SQL腳本與後臺做業定時完成。
2、對於查詢的處理(如下是基於成本優化器的狀況)
對於查詢,優化的方法一般會多一些,可是也是最頻繁調整的一塊內容。一般,我從以下這幾個方面來進行考慮並調優.
(1)對於SQL自己的編寫是否合理。好比基礎寫法與高級寫法之間的配合,在知足業務要求的基礎上,作到儘可能減小表的訪問。
(2)索引的建立是否合理,優化器是否選擇了較正確的索引。在不一樣的業務場景下,B*樹索引與位圖索引的相互配合是否合理等。
(3)監控系統中產生的爭用,根據產生的不一樣的閂或鎖,對SQL或是業務處理邏輯進行調整。
(4)若是有必要,根據當前系統的負載與硬件自己的支持,對PGA,SGA進行一個分配,使之更爲合理。
(5)若是有必要,在優化器參數進行一個調整。
(6)採用並行處理。
3、對數據插入的處理
這是考慮問題當中最薄弱的一塊內容,通常不做必要的優化處理,但有以下一些技巧:
(1)對於大數據量的表與表之間的插入,能夠採用並行,直接路徑、最小化日誌。
(2)若是必要,對錶自己參數進行一個修改,如freelist。
(3)若是是同數據源多目標的插入,能夠採用多表插入技術。
(4)若是能夠,儘可能使用INSERT INTO SELECT,CREATE TABLE AS SELECT方法。
若是在前期需求調研,設計階段就作好了工做。那麼後面的性能優化問題麻煩就能夠少不少。
固然一般因爲各類緣由,每每前期作不到那麼好。
那麼找到問題,發現問題,解決問題,一般
1. 經過工具來定位問題,例如選擇用10046 TRACE 工具包來實現
2. 找到問題所在之後去理解需求,探索是否能少作事完成需求(選擇用索引來替代全表掃描,從而減小訪問路徑); 
3. 去思考需求背後的真正需求,例如是否能夠用UNION ALL取代UNION ,避免沒必要要的排序引發資源消耗。 
4. 去分析資源如何合理應用 (在系統空閒時使用並行技術)。
5.診斷索引方面的問題。例如是否因爲錯誤的優化器統計信息致使執行了不正確的執行計劃。
數據庫表進行插入、查詢操做當數據達到百萬甚至千萬條級別的時候, 這一切彷佛變得至關困難。幾經折騰,總算完成了任務。在此作些簡單的小結,不足之處,還望高手們幫忙補充補充! 
一、避免使用Hibernate框架 
Hibernate用起來雖然方便,但對於海量數據的操做顯得力不從心。 
關於插入: 
試過用Hibernate一次性進行5萬條左右數據的插入,若ID使用sequence方式生成,Hibernate將分5萬次從數據庫取得 5萬個sequence,構形成相應對象後,再分五萬次將數據保存到數據庫。花了我十分鐘時間。主要的時間不是花在插入上,而是花在5萬次從數據庫取 sequence上,弄得我至關鬱悶。雖而後來把ID生成方式改爲increase解決了問題,但仍是對那十分鐘的等待心有餘悸。 
關於查詢: 
Hibernate對數據庫查詢的主要思想仍是面向對象的,這將使許多咱們不須要查詢的數據佔用了大量的系統資源(包括數據庫資源和本地資 源)。因爲對Hibernate的偏心,本着不拋棄、不放棄的做風,作了包括配SQL,改進SQL等等的至關多的嘗試,可都以失敗了結,不得不忍痛割愛 了。 
二、寫查詢語句時,要把查詢的字段一一列出 
查詢時不要使用相似select * from x_table的語句,要儘可能使用select id,name from x_table,以免查詢出不須要的數據浪費資源。對於海量數據而言,一個字段所佔用的資源和查詢時間是至關可觀的。 
三、減小沒必要要的查詢條件 
當咱們在作查詢時,經常是前臺提交一個查詢表單到後臺,後臺解析這個表 單,然後進行查詢操做。在咱們解析表單時,爲了方便起見,經常喜歡將一些不須要查詢的條件用永真的條件來代替(如:select count(id) from x_table where name like ‘%’),其實這樣的SQL對資源的浪費是至關可怕的。我試過對於一樣的近一千萬條記錄的查詢來講,使用select count(id) from x_table 進行表查詢須要11秒,而使用select count(id) from x_table where name like ‘%’卻花了33秒。 
四、避免在查詢時使用錶鏈接 
在作海量數據查詢時,應儘可能避免錶鏈接(特別是左、右鏈接),萬不得已要進行錶鏈接時,被鏈接的另外一張表數據量必定不能太大,若鏈接的另外一張表也是數萬條的話,那估計能夠考慮從新設計庫表了,由於那須要等待的時間決不是正經常使用戶所能忍受的。 
五、嵌套查詢時,儘量地在第一次select就把查詢範圍縮到最小 
在有多個select嵌套查詢的時候,應儘可能在最內層就把所要查詢的範圍縮到最小,能分頁的先分頁。不少時候,就是這樣簡單地把分頁放到內層查詢裏,對查詢效率來講能造成質的變化。 
特別是銀行系統的,數量級是億級別的,因此更要考慮下面的方法。
1,怎樣造Java對象。有句話說得好:儘量的少造對象。別說千萬級,就是上萬級都不要考慮造對象了。由於幾個請求一併發,喀嚓,系統確定完蛋。
2,合理擺正系統設計的位置。大量數據操做,和少許數據操做必定是分開的。大量的數據操做,確定不是ORM框架搞定的。絕對不能ORM,由於1,要少造對象;2,數據庫資源合理利用。就像博主的例子:id分配就是一個好例子。
3,合理利用數據庫的分區、索引技術。
4,有的時候能夠考慮臨時表之類的,尤爲是大數據量。
5,有人說很是大的數據量,必定要用存儲過程:jdbc,效果很是好
6,控制好內存,讓數據流起來,而不是所有讀到內存再處理,而是邊讀取邊處理;
7,合理利用內存,有的數據要緩存。
 sql

相關文章
相關標籤/搜索