Mariadb

MariaDB 子查詢記憶體範圍和設置

  • October 4, 2015

我正在將一個應用程序從 MySQL 5.6 遷移到 MariaDB 10。MariaDB 的一個主要新特性是子查詢記憶體。我試圖在啟用和測試它之前確定這個記憶體對我們的應用程序產生的預期影響。在“實施”部分下,知識庫文章這樣說:

每個子查詢記憶體都會創建一個臨時表,其中儲存了結果和所有參數。它對所有參數都有唯一的索引。首先,在 MEMORY 表中創建記憶體(如果無法執行此操作,則該表達式的記憶體將被禁用)。當表增長到 tmp_table_size 和 max_heap_table_size 的最小值時,會檢查命中率:

  • 如果命中率非常小(<0.2),記憶體將被禁用。
  • 如果命中率適中(<0.7),則表將被清理(刪除所有記錄)以將表保留在記憶體中
  • 如果命中率高,該表將轉換為磁碟表(對於 5.3.0,它只能轉換為磁碟表)。

我要確定的第一件事是“每個子查詢記憶體”的確切含義。由於它聲明記憶體是在臨時表中創建的,這意味著它們必須限定在目前連接範圍內。所以我的猜測是每個連接都會創建一個 subquery_cache 表。(我懷疑每個查詢都有自己的記憶體,因為這樣關於記憶體“增長”的行就沒有意義了。)但這只是一個猜測;我找不到更多細節。也許這些臨時表確實以某種方式在連接之間共享,這與正常臨時表不同。或者每個連接可能有多個記憶體。

誰能確認創建的子查詢記憶體的數量和範圍?

我的下一個問題是是否有調整記憶體的選項。由於我們正在從優化的 MySQL 應用程序遷移,我們目前沒有任何廣泛使用可記憶體子查詢的查詢(因為這樣的查詢在 MySQL 下會非常慢)。我們確實使用了大量的子查詢,只是不是以可能導致大量記憶體命中的方式使用。鑑於此,我希望啟用記憶體只會在臨時表創建和查找每個子查詢以及用於儲存記憶體表的記憶體中產生成本(顯然不能與主 tmp_table_size 和 max_heap_table_size 變數分開調整)。鑑於我希望發現我們目前存在的應用程序在不啟用記憶體的情況下效率更高。理想的情況是,如果它支持類似 '

由於在任何地方都沒有記錄此類功能,我希望它們不存在,但如果有人知道為什麼不存在,或者我們可能期望它們何時存在,那就太好了。

記憶體需要返回與執行子查詢相同的結果,因此範圍也必須受到活動事務的限制。

但是看到記憶體只能作為優化器功能啟用或禁用而不能以其他方式配置,我的猜測是它實際上是為每個特定的可記憶體子查詢實例化一次,用於優化器認為值得的查詢。

這似乎得到了證實:“它對所有參數都有一個唯一的索引。” - 如果您在同一個表中儲存多個子查詢的結果,這是不可行的。

所以在我看來,記憶體為每個可記憶體的子查詢實例化一次,其生命週期將受到外部查詢執行的限制。

編輯:我檢查了一些原始碼(免責聲明:我絕對不完全理解程式碼,因為 MariaDB 是一個相當大且複雜的軟體,而且我對 C++ 的了解遠非專家水平)。記憶體由Expression_cache_tmptable. 用於儲存記憶體結果的表是在從某些方法呼叫的init()方法Item_cache_wrapper中創建的,並且各種Item的 AFAIK 生命週期是單個(外部)查詢執行,因為不同類型的Item保留和管理查詢的不同部分(如果我理解正確的話,是一種表達式樹)。

由此我推斷,在“準備”執行查詢時,會為每個可記憶體子查詢創建一個子查詢記憶體實例。然後在查詢執行期間首次訪問它時對其進行初始化(並創建臨時表)(因此僅當子查詢實際上至少執行一次時)。然後在 200 次未命中(可能是在處理大約 200 多行外部查詢之後)檢查“<0.2”的條件(對於每個子查詢獨立) ,以查看記憶體是否有任何積極影響,並提前禁用它如果沒有幫助。然後,如果記憶體表增長過大,則根據手冊中列出的條件再次檢查。

所以子查詢記憶體是不可調整的,但似乎盡可能地不受干擾。優化器將永遠為子查詢實例化它,這些子查詢至少在理論上可以使用它,如果它沒有被證明有用,它將在查詢執行的早期被禁用。

如果您仍然擔心它會減慢查詢速度,您可以通過配置全域禁用它optimizer_switch,然後通過呼叫僅對選定查詢啟用它

SET SESSION optimizer_switch='subquery_cache=on';

在查詢執行之前,然後可以選擇將其關閉。

引用自:https://dba.stackexchange.com/questions/116919