天天看點

内置的資料無法實作高性能

内置的資料無法實作高性能

這裡說的“内”, 是指資料庫之内。

當資料量變大時,我們常常會感到資料庫的性能下降明顯,但是,無論怎樣優化 SQL(存儲過程)都仍然與根據資料量和運算複雜度計算出來的理論性能相差甚遠。這主要由如下幾方面原因造成:

1. SQL 限制與優化困難

我們已經多次說過,由于關系代數和 SQL 文法的限制,有許多高效的算法無法實施,比如前面說過的周遊複用技術,以及去年談過的 JOIN 優化方法。使用 SQL 實作這類運算時,隻能采用複雜度更高的方法,備援的資料通路量和計算量非常大,而且也很難利用多 CPU 進行并行計算。

SQL 不提倡分步計算,經常一條語句寫出幾百行、嵌套很多層。不分步的長語句很難利用某個子句的計算結果,常常帶來不必要的重複計算。而且過于複雜的也會給資料庫優化引擎造成負擔,優化引擎不能很好地了解運算邏輯而設計出最優的執行路徑。我們常常發現一條語句的幾個子部分執行都很快,結果集也不大,但合起來寫到一句 SQL 中就會很慢。

2. 存儲過程性能差

對于複雜的多步驟計算,我們常常要編寫存儲過程才能實作。而和 SQL 相比,存儲過程的取數周遊過程要慢得多。同一個表的資料,使用存儲過程先 FETCH 出來再做聚合,要比直接用 SQL 聚合的性能慢出幾倍到十幾倍,本來這兩者的運算性能應當是差不多的(計算複雜度與資料通路量都一樣)。有些針對明細資料的複雜處理隻能把資料一條條取出才能實作時,這個性能就沒辦法得到保證了。

在存儲過程中,為了利用前面計算出來的中間結果,隻要涉及集合性資料一般都要使用臨時表。而建表寫數的動作也是非常慢的,資料庫有太多限制性要求,而且常常需要把臨時表落地到外存。

3. 直接外部計算不現實

如果我們不采用 SQL,而将資料讀出後在庫外計算,是否可以提高性能呢?

大多數情況仍然不可以。一方面原因是資料庫 IO 性能大都很差,從資料庫中取數,要比從檔案系統中讀數的性能差出一個資料量,經常發生取數時間遠遠超過計算時間的現象。

而且,有些高效算法會要求有特殊的存儲格式,比如需要事先将資料排序存儲,進而可以采用分段定位查找或實作有序歸并算法,而基于無序集合的 SQL 在理論上就無法支援,必須先排序才能保證取出資料的有序性,結果排序時間會超過計算本身。再比如行存或列存的選擇,一般資料庫隻會采用一種(支援 OLTP 用行存且不壓縮,面向 OLAP 用列存并壓縮),但使用行存還是列存需要由計算目标決定,在周遊式計算采用列存較為合适,而使用索引定位查找時則更适合用行存。有時為了性能還可能把同一份資料存儲備援的多份以面向不同用途,而在資料庫中很難有這麼靈活的處理方式。

解決辦法,就是資料外置,具體說就是把資料搬出資料庫。使用合理的存儲方案再配以适用的算法,對于許多幾百上千行的存儲過程,經過這樣的改造後,性能常常都有幾倍的增長。

當然,這又會帶來新的問題。主要有三個方面:一是可管理性,在資料庫中有統一的資料視圖和限制性檢查,而外部檔案系統則沒有這些東西;二是安全性,資料庫是個封閉體系,擷取資料的接口很單一,總有帳号認證的過程,而檔案系統也沒有這些東西;三是資料更新能力,資料在不斷地變化中,資料庫有完整的資料更新功能,檔案系統這方面卻很弱,一般隻能做追加,還很難保證追加過程中的一緻性(中途出錯時恢複)。

目前階段這個事還是需要權衡,獲得了資料庫的友善性就得不到高性能,要資料外置的高性能就要犧牲友善性。不過,随着技術的進步,在檔案系統上加強可管理性、安全性以及可更新能力又不犧牲或很少犧牲其性能,還是有可能做到的,資料庫的封閉性總要被打破。

作者:279400248

連結:

http://c.raqsoft.com.cn/article/1535513386417

來源:乾學院

著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。