2016-09-13 64 views
0

我正在開發一項新服務,需要爲區域提供報告數據。每個區域都有自己的數據庫表,每個數據庫表都有一些與ReportDate同名的列。不同的表格會有很多不同/唯一的列,這就是爲什麼我爲每個區域創建一個單獨的表格。將會有大約10個區域表。動態sql性能和實現recs?

我正在考慮對我的sproc使用動態sql,因此我可以編寫一個簡單的查詢,然後對每個表進行一般運算。這將更快,更容易編寫和維護,然後編寫10個獨立的查詢,對所有表執行相同的SQL。

SS很適合處理這種類型的實現嗎?你是否看到任何潛在的性能問題?我應該採取什麼具體步驟來優化這種實現的性能?有沒有人在這裏認爲動態sql是「邪惡」的原因或另一個?我特指完全在SS內完成的動態SQL,而不是通過動態SQL語句傳遞的外部應用程序。

回答

0

這是有點長的評論。

動態SQL是一個非常合理的解決方案。事實上,它可以防止在第一次運行過程時對SQL語句進行優化時出現的一些性能問題。這可能導致其他參數的次優執行計劃。

我的建議是準確生成你想要的SQL。額外的開銷是編譯語句。假設你正在做複雜的查詢,運行查詢應該花費比編譯更長的時間。

至於動態SQL是邪惡的,我想這是一個意見。多年來,我在多個項目中都非常有效地使用了它。

0

SQL Server沒有動態sql的問題,問題正好與開發人員密切相關。動態SQL可能非常有用且功能強大,但爲了取得長期成功,需要了解許多細微差別。通常有人問你所問的各種基本問題,並不是一個具有深度背景的人來瀏覽陷阱。

真正突出的一件事是前提是你的區域差別很大,你需要將它們放在完全不同的數據庫中,但是你希望在它們中使用相同的存儲過程。這對我來說沒有任何意義,我擔心你會一團糟。

+0

每個區域的不同表格都很嚇人。想想這個問題。從地區(所有地區所有銷售)中選擇SUM(銷售)。如果所有區域都不在一張表中,那麼很難做基本的報告和gui utils。 –

1

動態Sql正在成爲天使不邪惡!!!。

十年前,關係數據庫中只有兩條規則: 「始終使用存儲過程」和「從不構建動態SQL(即時查詢)」。

但是,遊戲已經隨着ORM的革命和從SQL Server 2005開始到SQL server 2016發佈的新一代SQL Server而發生了變化。

這並不令人驚訝聽到這樣的忠告:

Don’t Fear Dynamic SQL. When done correctly, it can be used effectively

動態SQL肯定是有一些缺點。但是,如果使用得當,它有許多積極的屬性,包括提高性能的能力。

條件動態SQL高性能:使用sp_executesql不EXEC

  • 運行動態SQL。
  • 對於有條件的地方(不要串聯值)使用參數

sp_executesql的將使用高速緩存的計劃,以獲得更多的性能。

ADO.NET將客戶端中的查詢作爲sp_executeSQL發送。您可以在SQL事件探查器中查看生成的SQL。

ORM所做的是動態生成CRUD作爲動態SQL並將數據映射到對象中以加速開發並獲得良好性能。

SQL Server具有sp_executesql,它是一個系統存儲過程,它爲參數使用參數標記和可變數量參數的SQL字符串。

因此,無論客戶何時必須執行參數化語句,客戶端都會向sp_executesql發出RPC請求。

參數化的sp_executesql調用更有可能具有可重用的緩存計劃。

存儲的過程sp_executesql成爲標準程序,用於執行從SQL Server 2005開始

動態sql與參數替換內容是查詢作爲在ADO.NET產生偶數(更新/插入/刪除)動態sql編譯並執行一個獨立於調用sp_executesql的批處理的執行計劃的執行計劃。從MSDN sp_executesql

sp_executesql的

摘錄可以用來代替的存儲過程來執行Transact-SQL語句多次在參數值在語句的變化是唯一的變化。由於Transact-SQL語句本身保持不變並且只有參數值發生更改,因此SQL Server查詢優化器可能會重用它爲第一次執行生成的執行計劃。

動態sql被執行爲: EXECUTE sp_executesql @SQLString,@ParmDefinition,@SalesID = @IntVariable;

誰有動力生成動態sql並運行良好的性能?

在客戶端,如果我們運行查詢:

var ID=1; 
    string commandText = "select * from products WHERE productid = @ID;"; 

使用ADO。NET:

生成的查詢是:

exec sp_executesql N'select * from products WHERE productid = @ID;',N'@ID int',@ID=11 

小巧玲瓏的(高性能ORM)

小巧玲瓏是微ORM用於.NET開發和由堆棧溢出小組使用,聚焦以原始表現爲主要目標。

生成的查詢是:

exec sp_executesql N'select * from products WHERE productid = @ID;',N'@ID int',@ID=12 

的EntityFramework EF 6.3

查詢:

var id=1; 
Product p = db.Products.FirstOrDefault(t => t.ProductID == id); 

的生成動態SQL:

exec sp_executesql N'SELECT TOP (1) 
    [Extent1].[ProductID] AS [ProductID], 
    [Extent1].[ProductName] AS [ProductName], 
    [Extent1].[SupplierID] AS [SupplierID], 
    [Extent1].[CategoryID] AS [CategoryID], 
    [Extent1].[QuantityPerUnit] AS [QuantityPerUnit], 
    [Extent1].[UnitPrice] AS [UnitPrice], 
    [Extent1].[UnitsInStock] AS [UnitsInStock], 
    [Extent1].[UnitsOnOrder] AS [UnitsOnOrder], 
    [Extent1].[ReorderLevel] AS [ReorderLevel], 
    [Extent1].[Discontinued] AS [Discontinued] 
    FROM [dbo].[Products] AS [Extent1] 
    WHERE [Extent1].[ProductID] = @p__linq__0',N'@p__linq__0 int',@p__linq__0=1 

等工具使用高性能動態sql。

結論: 動態SQL可以用出色的表現來使用,如果它的參數,並與sp_executesql的

0

在關係數據庫存儲類似,但並非最相同對象的問題,執行的是很常見的一。搜索規範化+繼承,或參見here。我會避免在不同的表中重新創建相同的列。你已經開始發現問題了。你也正在走條件邏輯在SQL中的道路。我不會去那裏。

動態SQL是沒有問題的。 SQL字符串文字。如果你願意的話,把你的SQL放在存儲過程中,但對我來說,SQL請求屬於應用程序,應該與應用程序一起打包和版本化。 QueryFirst將幫助您保持SQL的完整性,同時將其編譯到您的應用程序中。