2016-09-13 63 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的完整性,同时将其编译到您的应用程序中。