****欧欧美毛片4,国产午夜精品视频,97视频在线观看免费视频,久久七国产精品

數據恢復咨詢熱線:400-666-3702??

歡迎訪問南京兆柏數據恢復公司,專業數據恢復15年

兆柏數據恢復公司

?行業新聞

?當前位置: 主頁 > 行業新聞

SQL Server 2019 修復函數內聯 bug,速度提高 1000 倍

瀏覽量: 次 發布日期:2023-08-17 21:48:47

sql server 2019 修復函數內聯 bug,速度提高 1000 倍

作者 | Jonathan Allen 譯者 | 無明

與過去幾十年出現的大多數數據庫一樣,SQL Server 允許開發人員通過創建函數來擴展數據庫。但在即將發布的 SQL Server 2019 之前,SQL Server 對標量函數的支持存在很多問題。

在 SQL Server 中,返回單個值的函數被稱為“標量 UDF”或“標量用戶定義函數”。這些標量 UDF 由數據庫自動歸類為確定性或非確定性的。例如,非確定性函數用于讀取當前時間或從表中獲取數據。確定性函數始終為給定的參數集返回相同的值。理論上,數據庫如果知道正在使用的是確定性 UDF,那么就可以針對這些函數進行優化。

遺憾的是,SQL Server 從未將標量 UDF 支持完全集成到執行計劃生成器中。因此,它經常會做一些不必要的工作,例如會在每一行上執行確定性函數,但其實如果只針對每個唯一值執行一次函數會更快。

重復使用之前的值多少次以上才會帶來實際的好處?這個很難說。除非數據是預先排序的,或者它知道可能的輸入數量是有限的,否則緩存函數參數和結果的成本可能會超過收益。而這并不是標量 UDF 存在的唯一問題。

SQL Server 標量 UDF 的另一個問題是它們給并行化帶來了阻礙。跨多個 CPU 分發復雜查詢的能力是 SQL Server 的主要賣點。(很多開源替代品幾乎沒有并行支持或者只能依賴分布式數據庫)。如果沒有并行化,就很難證明 SQL Server 對得起它的價格。

說到價格,我們根本無法估計一個 SQL Server 標量函數究竟有多貴。所有的標量函數,不管是簡單的還是復雜的,在執行計劃中都會被賦予一個默認的成本。

標量 UDF 與調用它們的查詢之間是單獨進行解釋的。根據微軟的說法,對于每一行數據,都涉及到查詢與函數之間的上下文切換。我們可以假設上下文切換的成本可能會超過函數本身的成本。

出于這些原因,很多開發人員和 DBA 建議不要在對性能要求較高的代碼中使用標量函數,盡管將標量函數的內容粘貼到需要它的每個查詢、視圖和存儲過程中會導致大量代碼重復。于是,我們經常會聽到諸如“除了視圖之外的代碼重用不適合數據庫”這樣的說法。

標量函數的性能損失不容小覷,例如這個簡單的函數:

CREATE FUNCTION dbo.discount_price(@price DECIMAL(12,2), @discount DECIMAL(12,2))RETURNS DECIMAL (12,2) ASBEGIN RETURN @price * (1 - @discount);END

微軟研究員 Karthik Ramachandra 表示,這個標量函數可能會導致一個通常只需要 1.6 秒的查詢變成 29 分 11 秒那么久。雖然沒有語義差異,速度卻慢了 1000 倍。

解決方法是使用“內聯表值函數”或“內聯 TVF”代替標量函數。表值函數通常會返回一組行,但也可以將它們改寫成只返回一行。這個時候,可以使用 CROSS APPLY 運算符模擬正常的標量函數調用。 SQL Server 2019 中的函數內聯

從 SQL Server 2019 開始,可以內聯用使用 T-SQL 編寫的標量函數。這意味著它們可以被嵌入到查詢中,并且不會有 UDF 那樣的開銷。在查看執行計劃時,包含邏輯代碼的查詢與使用內聯標量函數的查詢之間是沒有區別的。

這個新功能不僅限于簡單的表達式。一些多語句 UDF 也可以被內聯,甚至可以內聯涉及從表中讀取數據的非確定性 UDF。它還以推斷出是否需要添加 JOIN 或 GROUP BY 運算符,以便將查詢中的表與函數中的表組合在一起。

當然,并非所有函數都可以被內聯。要進行內聯,UDF 需要滿足以下要求:

滿足以下所有條件的標量 T-SQL UDF 可以被內聯:

使用以下構造編寫的 UDF:

DECLARE、SET:變量聲明和賦值。

SELECT:具有單 / 多變量賦值的 SQL 查詢。

IF/ELSE:具有任意級別的嵌套分支。

RETURN:單個或多個返回語句。

UDF:嵌套 / 遞歸函數調用。

其他:關系操作,如 EXISTS、ISNULL。

不調用任何與時間相關的內部函數(例如 GETDATE())或具有副作用的函數(例如 NEWSEQUENTIALID())的 UFD。

使用 EXECUTE AS CALLER 子句(如果未指定 EXECUTE AS 子句,則這個為默認行為)的 UDF。

不引用表變量或表值參數的 UDF。

調用了標量 UDF,但其 GROUP BY 子句中不引用標量 UDF 調用的查詢。

不是原生編譯的 UDF。

不是被用在計算列或檢查約束定義中的 UDF。

不引用用戶定義類型的 UDF。

沒有添加任何簽名的 UDF。

不是用于分區的 UDF。

對于每個 T-SQL 標量 UDF,sys.sql_modules 視圖中都有對應的 is_inlineable 屬性,這個屬性用于指示 UDF 是否可以內聯。值為 1 表示它是可內聯的,0 表示不可以內聯。對于所有內聯 TVF,這個屬性的值均為 1。對于所有其他模塊,該值為 0。

可以通過將數據庫兼容級別設置為小于 150 或者將 TSQL_SCALAR_UDF_INLINING 的作用域配置設置為 OFF 來禁用 UDF 內聯。

也可以通過 OPTION (USE HINT(‘DISABLE_TSQL_SCALAR_UDF_INLINING’)) 在給定查詢上禁用內聯。

你也可以在聲明函數時使用 WITH INLINE = OFF 來表示永久禁用內聯。 Froid 項目和未來的機會

如果沒有 Froid 研究項目,可能就無法將該功能添加到 SQL Server。Froid 項目被描述為:

用于優化關系數據庫命令式程序的可擴展框架。Froid 自動將整個用戶定義函數(UDF)轉換為關系代數表達式,并將它們嵌入到 SQL 查詢中。這種形式可以進行基于成本的優化,并且可以生成有效的、面向集合的并行計劃,而不是 UDF 那種低效、迭代、串行的執行過程。Froid 還為 UDF 帶來了很多編譯器優化,而不需要進行額外的實現。我們介紹了 Froid 的設計,并展示了我們的實驗評估,它在實際工作負載上帶來了多達數個數量級的性能改進。

目前只知道 Froid 框架支持 T-SQL,但論文中也提到了 C#、Java、Python 和 R 語言。由于 SQL Server 現在支持這四門語言中的三門,因此將函數內聯擴展到其他語言會帶來很大好處。 英文原文

https://www.infoq.com/news/2019/01/SQL-Server-Scalar-UDF-Inlining


南京兆柏數據恢復中心 南京兆柏數據恢復中心
相關推薦