資料庫相關優化方案

来源:http://www.cnblogs.com/agileai/archive/2017/06/13/7000064.html
-Advertisement-
Play Games

1 背景概述 在大多數的開發項目中,尤其是集成項目,都會有涉及到數據分析部分的工作,數據分析多數是各種圖表的展現和交互(所謂數據可視化),數據分析的展現速度直接影響著用戶的體驗,而且絕大多數管理系統(MES、PDM/PLM、ERP、SCM、OA、HR等等)的數據都存儲在資料庫中,資料庫相關的性能優化 ...


1 背景概述

在大多數的開發項目中,尤其是集成項目,都會有涉及到數據分析部分的工作,數據分析多數是各種圖表的展現和交互(所謂數據可視化),數據分析的展現速度直接影響著用戶的體驗,而且絕大多數管理系統(MES、PDM/PLM、ERP、SCM、OA、HR等等)的數據都存儲在資料庫中,資料庫相關的性能優化可以較容易提高程式系統的整體性能、提升用戶的體驗,保障項目的順利驗收。對應用程式進行整體的性能優化需要全局考慮,比如:硬體選型、軟體架構、部署架構、程式開發等方面。本文主要側重介紹程式開發部分的資料庫層面的相關優化手段,希望能對大家有所幫助。

2 預期讀者

  1. 數通暢聯內部員工
  2. 廣大IT相關從業者

3 優化途徑

無論是開發項目還是集成項目最終的目的是項目的驗收,促進項目的回款,保障公司的資金流進一步的運作。但是如果功能程式的性能不過關,響應速度慢進而影響客戶的體驗,則直接影響著項目的驗收,從而阻礙了公司的正常運作。典型的優化途徑有:硬體選選型、系統軟體、應用程式三個途徑。

3.1 硬體選型

選擇什麼樣的伺服器都會遇到一個相同的問題,那就是選擇什麼硬體配置的伺服器。在日常的項目工作中會將伺服器區分為:應用伺服器、資料庫伺服器、文件伺服器以及其他伺服器。

  • 應用伺服器:一般用於業務系統功能的部署以及應用系統的部署伺服器,對CPU、記憶體、要求都比較高。(推薦配置:CPU 3.0G Hz 及以上、4核及以上 記憶體 32G 硬碟 500G(RAID10)) 。
  • 資料庫伺服器:數據伺服器對CPU、記憶體、磁碟的要求都很高,在實際應用中如果某個硬體是短板都會帶來性能問題。(推薦配置:CPU 3.0G Hz 及以上、4核及以上,記憶體 16G 及以上、固態硬碟 1T(RAID10))。
  • 文件伺服器:文件伺服器主要是對IO、硬碟大小要求較高,記憶體較低。(推薦配置:CPU 3.0G Hz 及以上、記憶體 4G及以上、硬碟 2TB(RAID5))。
  • 其他伺服器:至於其它伺服器就看各位的具體需要具體分析了。

通常情況下硬體配置越高,性能越好,但是綜合考慮(money!)硬體配置一般能滿足展望未來3-5年性能要求即可。註意:雲伺服器現在也是可以考慮的選擇。

3.2 系統軟體

在操作系統的選擇上最常見的就是Linux以及Windows,考慮到伺服器的性能、安全性通常我們選擇Linux操作系統。雖然Server版本操作系統本身的性能已經相對穩定,但是我們可以優化對應操作系統的配置來進一步匹配對應項目的性能需求,而Linux系列的操作系統相對來說有更多的優化策略和空間,更重要的是運維尤其遠程運維很方便。

3.3 應用程式

衡量一個程式的標準首當其衝的是程式的安全性,然後則是程式的性能,也就是程式的響應速度。對於程式的保密性要求並不是所有行業均是嚴格要求的那麼對於程式的性能則是不區分行業均是更改的性能帶來更好的體驗。

應用程式的優化必殺技通常來說就是程式(軟體)本身支持水平擴展,很多書籍都有介紹,百度關鍵字:大型系統架構,可以瞭解很多相關知識,水平擴展是另外一個話題,這個話題也會涉及到很多方面,在本文中就不一一贅述。

系統程式的基礎環境調優對應用程式的優化也較為明顯,比如:Java程式的JVM設置、PHP程式的子進程數配置、.NET程式的認證機制、運行庫設置等等。基礎環境調優也不是本文闡述重點。在下麵我們主要對軟體資料庫相關的優化方案中進行詳細介紹。

4 優化方案

雖然NoSQL也開始流行,但是更多場景下它只是資料庫的補充,資料庫自從誕生開始起就牢牢占據著管理軟體後臺存儲的主場,而且從未離開。資料庫層面的性能優化屬於短平快調整就能見效、或者在開發中稍微註意就可以大幅度提升性能的常規系統調優手段。

4.1 整體策略

我們通常需要從整體策略發的角度出發,將資料庫調優從彙總查詢、視圖方式、數據緩存等三個方面來進行。

4.1.1 彙總查詢

在日常工作中如果所涉及的查詢語句較為複雜,或者需要訪問第三方的資料庫,而在訪問第三方資料庫時常常會因為不同的資料庫中不同數據表的讀取頻率不同,進而影響性能。面對這種情況我們通常將需要查詢的內容彙總到中間表,然後直接從中間表進行數據查詢。

4.1.2 視圖方式

一般情況下創建視圖是不會直接提高性能的,但是如果需要查詢的內容涉及到多個數據表之間的關聯且關聯關係較為複查,查詢出的結果集被高頻的訪問。這時如果沒有創建視圖那麼每要查詢這個結果集就需要重新創建SQL,但是如果創建統一的視圖並且在創建視圖是已經進行SQL調優,方便大家的統一調用從而來提升資料庫的性能。

4.1.3 緩存方式

當前查詢結果的結果集是為展現內容提供數據展現,不是交互性數據操作,不經常被改變是我們可以將數據的查詢結果集放入緩存中,這樣在讀取時在緩存中進行獲取,減少了對資料庫的訪問操作進一步的提升程式的響應速率。在程式應用中常見的緩存處理手段如下:

靜態緩存

靜態緩存通常為創建一個靜態的HashMap 變數,在數據獲取是判斷Map中是否含有,如果有在Map變數中獲取,如果沒有則在資料庫中查詢然後放入緩存的Map變數中。

分散式緩存

分散式緩存通常是應用於集群部署的場景,通常應用部署於不同的業務伺服器,通過Redis 或者Mncached來進行分散式緩存的管理。

4.2 常規優化

在資料庫優化的方案中最常見也是性能優化的最關鍵的部分就是資料庫的SQL優化,本篇文章分別在查詢優化、更新優化、其他說明三個方面來進行說明常見的SQL優化。

4.2.1 查詢優化

避免在客戶端返回大數據量

儘量避免在客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。如果一定要返回大數據量,考慮使用資料庫分頁來處理。

查詢避免使用*

SELECT子句中避免使用*號資料庫在解析的過程中,會將*依次轉換成所有的列名,這個工作是通過查詢數據字典完成的,這意味著將耗費更多的時間。如:

Select * from emp

應該為:

Select id,name,code from emp

慎用DISTINCT

用EXISTS替換DISTINCT: 當提交一個包含一對多表信息(比如部門表和雇員表)的查詢時,避免在SELECT子句中使用DISTINCT. 一般可以考慮用EXIST替換, EXISTS 使查詢更為迅速,因為RDBMS核心模塊將在子查詢的條件一旦滿足後,立刻返回結果. 例子:

(低效):

SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D , EMP E WHERE D.DEPT_NO = E.DEPT_NO

(高效):

SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT ‘X' FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);

UNION和UNION-ALL

用UNION-ALL 替換UNION ( 如果有可能的話): 當SQL 語句需要UNION兩個查詢結果集合時,這兩個結果集合會以UNION-ALL的方式被合併, 然後在輸出最終結果前進行排序. 如果用UNION ALL替代UNION, 這樣排序就不是必要了. 效率就會因此得到提高. 需要註意的是,UNION ALL 將重覆輸出兩個結果集合中相同記錄. 因此還是要從業務需求分析考慮使用UNION ALL的可行性。

條件子句的註意事項

創建索引

對where中的條件列創建索引,可以加快查詢速度。對於表中的主鍵、外鍵、有對像或身份標識意義的欄位視情況添加索引。

避免null判斷

應儘量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:

select name from system_users where id is null

最好不要給資料庫留NULL,儘可能的使用 NOT NULL填充資料庫。備註、描述、評論之類的可以設置為 NULL,其他的,最好不要使用NULL。不要以為 NULL 不需要空間,比如:char(100) 型,在欄位建立時,空間就固定了, 不管是否插入值(NULL也包含在內),都是占用 100個字元的空間的,如果是varchar這樣的變長欄位, null 不占用空間。

可以在id上設置預設值0,確保表中id列沒有null值,然後這樣查詢:

select name from system_users where id = 0

避免不等於操作
儘量避免在 where 子句中使用 != 或 <> 操作符,否則將引擎放棄使用索引而進行全表掃描。

避免in或not in

in 和 not in 也要慎用,否則會導致全表掃描,如:

select id from t where num in(1,2,3)

對於連續的數值,能用 between 就不要用 in 了:

select id from t where num between 1 and 3

很多時候用 exists 代替 in 是一個好的選擇:

select num from a where num in(select num from b)

用下麵的語句替換:

select num from a where exists(select 1 from b where num=a.num)

避免對欄位進行函數操作

儘量避免在where子句中對欄位進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。如下:

select id from t where substring(name,1,3) = ’abc’

查詢所有以abc開頭的名字的id

應改為:

select id from t where name like 'abc%'

4.2.2 更新優化

更新批量使用bach處理

在程式中儘量避免大量的insert或者delete同時處理,如果遇到這種情況需要使用bach進行批量統一處理。

避免大批量的insert和delete

因為這兩個操作是會鎖表的,表一鎖住了,別的操作都進不來了。所以,如果有一個大的處理,一定把其拆分,使用 LIMIT oracle(rownum),sqlserver(top)條件。

Update註意

如果只更改1、2個欄位,不要Update全部欄位,否則頻繁調用會引起明顯的性能消耗,同時帶來大量日誌。

杜絕count(*)

select count(*) from table;

這樣不帶任何條件的count會引起全表掃描,並且沒有任何業務意義,是一定要杜絕的。

4.2.3 事務處理

在資料庫使用中儘量減少長事務

在資料庫中如果涉及到主表、從表、附屬從表,這時如果同時操作三個數據表同時成功以及同時失敗,如果當前數據表的數據量較大,為了降低資料庫的性能壓力,我們可以採用批處理方式分別批處理三個數據表來進行資料庫性能的提升。

減少分散式事務的使用

一般的資料庫均是支持分散式事務,當涉及到跨資料庫的不同數據表的操作時我們可以使用分散式事務。但為了提高性能損耗,儘量減少這種強一致性需求,更多情況下轉化為最終一致性方式來滿足業務需求,通常來說引入消息中間件是這種場景下的常規解決手段。

4.2.4 其他說明

多用varchar和nvarchar

儘可能的使用 varchar/nvarchar 代替 char/nchar ,因為首先變長欄位存儲空間小,可以節省存儲空間,其次對於查詢來說,在一個相對較小的欄位內搜索效率顯然要高些。

減少大欄位的使用

在資料庫中定義類型是儘量避免使用大欄位類型如:BLOB、TEXT、LONG以及Object等大對象的類型

不要在資料庫中存儲文件

在程式設計以及資料庫存儲是不要將圖片文件、其他日誌文件的文件類型存儲於資料庫中,而是在資料庫中存儲文件索引的URL將文件存儲於文件伺服器中。

4.3 配置優化

在進行資料庫連接操作時,我們可以通過選擇合適的驅動、釋放連接池中的資源、選擇符合應用場景的介面,構造只讀結果集來進一步的優化JDBC的配置。下麵我們通過連接處理、匹配介面以及返回結果三個方面進行詳細的說明。

4.3.1 連接處理

對於Java程式而言, Connention的優化通常使用數據連接池(dbcp、proxool、c3p0)來進行Connention對象的管理,這樣程式的靈活性強,便於移植。但要註意的是對象池裡中是沒有回收機制,並且對象池裡有容量限制,對於對象池裡的閑置對象儘早的釋放資源

下麵來簡單說明不用的連接池的對比:

Dbcp(DataBase connection pool):是apache上的一個 java連接池項目。

優點:配置方便,可以設置最大和最小連接,連接等待時間等,持續運行的穩定性,速度快。

缺點:沒有自動的去回收空閑連接的功能,大併發量的壓力下穩定性不高,不能夠進行連接池監控。

ProxoolProxool是一種Java資料庫連接池技術。是sourceforge下的一個開源項目。

優點:可以設置最大和最小連接,具備監控功能。

缺點:明顯的性能問題持,續運行的穩定性不高。

C3p0是在Hibernate和Spring中預設支持該資料庫連接池,實現了數據源和jndi綁定,支持jdbc3規範和jdbc2的標準擴展。

優點:支持高併發,非同步操作,有自動回收空閑連接功能。

缺點:沒有Dbcp的速度快。

4.3.2 匹配介面

對於Statement對象的優化,我們需要根據不同的應用場合選擇合適的Statement介面。如:

Statement不帶參數,例如:查詢時,不需要到任何參數。

PreparedStatement PreparedStatement可以寫參數化查詢,比Statement能獲得更好的性能,可以阻止常見的SQL註入式攻擊,提高安全性。

CallableStatement專門針對存儲過程,使用它能享受到所有存儲過程帶來的優勢,但也包括存儲過程帶來的劣勢如Java程式可移植性查,依賴資料庫等。

4.3.3 返回結果

優化結果集(ResultSet)查詢時候,返回的結果集有不同的類型。結果集分兩種類型:只讀和可更改。返回的結果集預設就是只讀的。而在Oracle中我們可以設置手工加鎖語句(Select XXX forUpdate)。

明確指定主鍵,並且有此數據則鎖定若無則不鎖定

SELECT * FROM products WHERE id='3' FOR UPDATE;

無主鍵或者主鍵不明確則進行表鎖定

SELECT * FROM products WHERE name='Mouse' FOR UPDATE;

 

5 個人總結

應用程式優化是一個系統工程,需要綜合考慮,更多時候要提前考慮,在系統架構層面來保障系統具有更多優化的能力。系統運維有一種消極的說法,系統能用就行,不要輕易去改變;但對於系統開發而言,每一次代碼重構都是一次系統調優以及增強調優能力的機會。Devops也慢慢開始盛行了,開發和運營越來越密切,甚至是一套班子兩種角色,你(們)如何選擇?我個人而言,傾向主動調優、擁抱變化,即便可能帶來一些風險。

無論是對公司的產品進行開發還是在項目開發的過程中,要在全局的角度出發整體考慮、制定規範、落實到每一項的工作中,從制度上保障系統性能調優的能力。筆者作為數通暢聯公司的一名技術員工,今天將自己所學所用的常見的資料庫優化相關處理總結出來與大家分享。如果對本文檔相關的描述信息存在疑問歡迎加入數通暢聯官方技術群(299719834)進行討論。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文主要參考 http://hadoop.apache.org/docs/r2.8.0/hadoop-project-dist/hadoop-common/RackAwareness.html hadoop組件是機棧敏感(譯註rack,機棧,可以簡單理解為節點的擺放)。 例如,HDFS塊的分佈會利用 ...
  • MSSQL 2016支持了utf8編碼的文件,之前處理比較麻煩的bcp 方式導入特殊字元一下子就方便了。 但是之前的版本,處理起來還是有一點麻煩。這次處理使用的資料庫版本是sql server 2014, 用於測試的例子用2個字元串 T3 Rénové tout Confort proche mét ...
  • Power BI 報表伺服器讓你的用戶能夠訪問數據、獲取見解,並能夠使用 SQL 報表伺服器服務的企業報告功能 - 這一切都在現代本地解決方案中完成。讓用戶能夠直觀瀏覽數據並快速發現模式,以便更快作出更好的決策。同時生成滿足你業務需求的精確格式的報表。你還可以胸有成竹地擴展到數千名用戶,因為 Pow ...
  • SQL%NOTFOUND 是一個布爾值。與最近的sql語句(update,insert,delete,select)發生交互,當最近的一條sql語句沒有涉及任何行的時候,則返回true。否則返回false。這樣的語句在實際應用中,是非常有用的。例如要update一行數據時,如果沒有找到,就可以作相應 ...
  • 1. Aggregate Aggregate即聚合操作。直接上代碼: acc即(0,0),number即data,seqOp將data的值累加到Tuple的第一個元素,將data的個數累加到Tuple的第二個元素。由於沒有分區,所以combOp是不起作用的,這個例子裡面即使分區了,combOp起作用 ...
  • 為什麼Oracle 查詢出來的數據會產生亂碼? 安裝的資料庫和客戶端編碼編碼不一致就會產生亂碼,要想解決此問題改一下客戶端的編碼即可 1. select * from table; 如果是這種問題則解決的辦法有許多,以下這種是比較通用一點的方法 1.查字元集編碼 select * from v$nl ...
  • 本文主要參考 http://hadoop.apache.org/docs/r2.8.0/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html 主要內容是對該文章的翻譯,部分內容參考其他的網路文章。 1.簡介 hadoop分散式文件系統(HDFS)是一個分散式 ...
  • 伺服器重啟後,資料庫登錄信息為空 錯誤信息: (Not logged on) - PL/SQL Developer Initialization errorCould not initialize "D:\app\Administrator\product\11.2.0\dbhome_1\bin\o ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...