爲了預防內存緊張的operator,presto容許將中間操做的結果轉存到磁盤上。這個機制的目的是爲了讓那些須要的內存超過一臺機器一個query內存限制的query可以執行。html
這個機制相似於操做系統級的頁交換。可是,它是被應用在應用程序級去知足presto的特殊需求。node
溢寫的屬性在https://prestodb.io/docs/current/admin/properties.html#tuning-spilling這裏描述併發
默認狀況下,presto殺掉那些執行內存超過會話屬性query_max_memory 或 query_max_memory_per_node。這個機制保證內存的公平分配,防止內存分配形成死鎖。當集羣中有不少小查詢的時候,這是很是有效的。可是會殺掉那些超過限制的大查詢。函數
爲了克服這個問題,可撤回的內存概念被提出。一個查詢能夠請求不限制的內存,可是這個內存能夠被任什麼時候候被內存管理回收。當內存被回收,這個查詢在內存中的數據被溢寫到磁盤上,稍後繼續處理。性能
事實上,當集羣是空閒的時候,全部內存均可以獲取,一個消耗內存的查詢能夠用完整個集羣的內存。相反的,當集羣沒有足夠的內存,一樣的查詢當前的數據被強制寫到磁盤上。被溢寫到磁盤上的查詢可能有一個較長的執行時間比徹底在內存中運行。spa
請注意開啓溢寫到磁盤機制不保證消耗內存的查詢運行成功。當加載數據到內存的時候,查詢運行程序可能沒法將中間數據劃分爲足夠小的塊,以便每一個塊都適合於內存,致使 out of memory 錯誤。操作系統
溢寫中間數據到磁盤,而後再加載到內存是一個高IO的操做,所以,磁盤多是這些查詢的瓶頸。爲了提升性能,建議在分開的磁盤上提供多重路徑。相關屬性https://prestodb.io/docs/current/admin/properties.html#tuning-spilling。rest
系統驅動盤不要被用做溢寫,也不要運行在JVM運行和寫日誌的地方。這樣作可能會致使系統不穩定。除此以外,建議監控溢寫路徑磁盤的飽和狀態。日誌
presto將溢寫路徑做爲獨立的磁盤,沒有必要用 RAID 作溢寫。htm
不是全部的操做支持溢寫到磁盤,每個處理溢寫不一樣。目前,這個機制被用於以下操做。
在join期間,其中一個表被存在內存。這個表被稱爲生成表。若是另外一張表裏的記錄與生成表裏的記錄匹配,則被傳遞給下一個操做。join中最費內存的部分就是生成表。
當任務的併發性大於1,生成表被分區。分區的數目等於任務的併發數task.concurrency 。屬性配置如https://prestodb.io/docs/current/admin/properties.html#task-properties
當生成表被分區,溢寫磁盤機制能下降join操做須要內存的峯值。當一個查詢接近內存限制,生成表的部分分區被溢寫到內存,與此同時,這些分區內的另外一張表的記錄也被寫入磁盤。被溢寫到磁盤的分區數量決定着佔用磁盤空間的大小。
後面,被溢寫的分區一個一個的讀會內存,完成join操做。
有了這個機制,join操做使用的內存峯值被下降到生成表的最大分區的大小。假設沒有數據傾斜,這將是整個生成表的 1/task.concurrency
聚合函數處理一組數據返回一個值。若是分組數目很是大,須要的內存也天然就不少。當啓動溢寫機制,直接計算的聚合結果被寫到磁盤,當有內存資源的時候,它被讀入內存合併。