vertica是惠普公司推出的列式分布式數據庫,在OLAP領域有其獨到的地方,目前社區版免費,但是只能存放1T的數據。我在工作中維護的bi系統后端就是使用的vertica數據庫,平時也經常需要對於數據庫的查詢進行一些優化。所以寫下這篇博客記錄一下。
- 定位問題
所謂的數據庫調優、程序優化之類的工作,實際上是一個解決問題的過程,而解決問題,第一部就是需要定位問題。找到問題的手段多種多樣,可以通過分析程序、監控生產上服務器的性能、定期生成數據庫的負載報告等手段,而最不應該的就是通過生產上用戶的反饋來反映問題了,因為到了那個時候,一切都已經晚了。具體到vertica來說,通過QUERY_PROFILES這個數據庫本身提供的視圖,可以找到耗時和執行的多的sql語句。以下三條sql語句,分別統計出執行次數top10,單次執行耗時top10,執行總耗時top10的sql語句。
SELECT query, count(*) as times FROM QUERY_PROFILES WHERE query_type = 'QUERY' and query_start>='2015-02-13' group by query ORDER BY times DESC limit 10; SELECT query, avg(query_duration_us) as avg_cost FROM QUERY_PROFILES WHERE query_type = 'QUERY' and query_start>='2015-02-13' group by query ORDER BY avg_cost DESC limit 10; SELECT query, sum(query_duration_us) as total_cost FROM QUERY_PROFILES WHERE query_type = 'QUERY' and query_start>='2015-02-13' group by query ORDER BY total_cost desc limit 10;
- 分析問題
數據庫調優,其實非常依賴於數據庫本身提供的各種性能分析工具,例如執行計划解釋器,跟着profile工具。在vertica中,可以通過profile,分析一條具體的sql語句。我們分析一條第一步中獲取到的sql語句:
獲取到這個語句的transcation_id和 statement_id 以后,可以通過查詢系統表 query_plan_profiles獲得語句實際的執行計划和各個階段的執行時間,這個不同於執行計划,這是真實的執行過程。如圖:
sql的執行是從下往上的,在這個表里面列出了PATH ID,我們可以從PATH ID從大到小一步一步分析,每一步的執行耗時。注意PATH ID:4這一步,查詢了一張事實表,cost是2K,處理了4M的數據。這一步就是我們分析的重點,因為它排在執行步驟的較前面並且處理了較多的數據。 - 解決問題
通過運行analyze_wordload,可以得到對某個表具體的優化建議。我們對,PATH ID:4的這個步驟查詢的事實表,進行分析,可以得到如下優化建議:
其中第一條指的是,運行vertica提供的database designer工具,對這個事實表建立映射,此方法代價比較大,而且只能對特定的查詢優化,這里進行第二條操作,對於此事實表進行分析,得到它的統計信息。
這條命令,只會訪問此表10%的數據,返回0表示成功。進行了統計信息之后,重新執行第1步和第2步,得到新的計划如下:
可以觀察到,執行步驟被調整了,原來PATH ID:4的步驟比較耗時,現在被提前到PATH ID:5了,而且執行的成本和消耗資源也不一樣,以下是詳細對比:優化之前:
| | | +-- Outer -> STORAGE ACCESS for T330143 [Cost: 2K, Rows: 4M (NO STATISTICS)] (PATH ID: 4)
優化之后:
| | | +-- Outer -> STORAGE ACCESS for T330143 [Cost: 94, Rows: 18K] (PATH ID: 5)。
可見,對於事實表的dt自動進行分析以后,通過dt字段獲取數據,掃描行數從4M減少到了18k,cost從2k減少了94,整個sql的執行時間也從0.34秒降低到了0.17秒。至此,此次優化得到了目的(執行時間減少了50%)。
- 分析背后的機制
為什么Vertica數據庫獲取了統計信息以后,就可以優化查詢?因為這張事實表是按照dt字段進行分區,但是在沒有統計信息的時候,即使查詢條件帶上了分區字段,仍然沒有利用分區信息,通過查詢v_monitor.query_events視圖可以看到sql執行過程中發生的事件。優化之前:
優化之后:
其中PARTITIONS_ELIMINATED的描述Some storage containers will not be processed because they contain no relevant data說明分區信息起作用了。
- 總結
簡單的vertica優化,一步的步驟如下:
- 收集sql統計信息,找出執行次數很多或者執行時間久的sql語句。
- 對要優化是sql進行profile,拿到此次執行profile的transaction_id和statement_id
- 利用vertica本身提供的工具和系統表,例如Datab Designer、Workload Analyzer、query_plan_profiles、v_monitor.query_events得到sql的執行計划和具體的優化建議。
對於查詢的優化,從簡單到復雜依次為:更新統計信息,運行database designer自動在表上建立projection(類似於物理視圖)、手工建立projection 。
- 可以研究的地方
同樣是分區表, 為什么在oracle中如果查詢條件帶上了分區健,就能正確的利用分區信息進行優化,而且vertica確不行呢?我猜可能有以下幾點可能
- 建表方式不對,所謂的分區並沒有起到作用。(類似於vertica中的主鍵約束)
- vertica本身不支持,需要利用額外的統計信息去做優化。
- 因為應用是OLAP場景,每天導入的數據量過大,所以統計信息很快失效。