简体   繁体   English

一次往返执行多个SQL命令

[英]Execute multiple SQL commands in one round trip

I am building an application and I want to batch multiple queries into a single round-trip to the database. 我正在构建一个应用程序,我想将多个查询批处理到一个数据库的往返。 For example, lets say a single page needs to display a list of users, a list of groups and a list of permissions. 例如,假设单个页面需要显示用户列表,组列表和权限列表。

So I have stored procs (or just simple sql commands like "select * from Users"), and I want to execute three of them. 所以我存储了procs(或者只是简单的sql命令,比如“select * from Users”),我想执行其中的三个。 However, to populate this one page I have to make 3 round trips. 但是,为了填充这一页,我必须进行3次往返。

Now I could write a single stored proc ("getUsersTeamsAndPermissions") or execute a single SQL command "select * from Users;exec getTeams;select * from Permissions". 现在我可以编写单个存储过程(“getUsersTeamsAndPermissions”)或执行单个SQL命令“select * from Users; exec getTeams; select * from Permissions”。

But I was wondering if there was a better way to specify to do 3 operations in a single round trip. 但我想知道是否有更好的方法来指定在一次往返中进行3次操作。 Benefits include being easier to unit test, and allowing the database engine to parrallelize the queries. 好处包括更容易进行单元测试,并允许数据库引擎将查询并行化。

I'm using C# 3.5 and SQL Server 2008. 我正在使用C#3.5和SQL Server 2008。

Something like this . 这样的东西。 The example is probably not very good as it doesn't properly dispose objects but you get the idea. 这个例子可能不是很好,因为它没有正确处理对象,但你明白了。 Here's a cleaned up version: 这是一个清理版本:

using (var connection = new SqlConnection(ConnectionString))
using (var command = connection.CreateCommand())
{
    connection.Open();
    command.CommandText = "select id from test1; select id from test2";
    using (var reader = command.ExecuteReader())
    {
        do
        {
            while (reader.Read())
            {
                Console.WriteLine(reader.GetInt32(0));
            }
            Console.WriteLine("--next command--");
        } while (reader.NextResult());

    }
}

The single multi-part command and the stored procedure options that you mention are the two options. 您提到的单个多部分命令和存储过程选项是两个选项。 You can't do them in such a way that they are "parallelized" on the db. 您无法以这样的方式执行它们,即它们在数据库上“并行化”。 However, both of those options does result in a single round trip , so you're good there. 但是,这两个选项都会导致单次往返 ,所以你在那里很好。 There's no way to send them more efficiently. 没有办法更有效地发送它们。 In sql server 2005 onwards, a multi-part command that is fully parameterized is very efficient. 在sql server 2005及更高版本中,完全参数化的多部分命令非常有效。

Edit : adding information on why cram into a single call. 编辑 :添加有关为什么填写单个呼叫的信息。

Although you don't want to care too much about reducing calls, there can be legitimate reasons for this. 虽然你不想太在意减少通话,但可能有正当理由。

  • I once was limited to a crummy ODBC driver against a mainframe, and there was a 1.2 second overhead on each call! 我曾经被限制在针对大型机的一个糟糕的ODBC驱动程序,并且每次调用都有1.2秒的开销! I'm serious. 我是认真的。 There were times when I crammed a little extra into my db calls. 有时候我把一些额外的东西塞进我的db调用中。 Not pretty. 不漂亮。
  • You also might find yourself in a situation where you have to configure your sql queries somewhere, and you can't just make 3 calls: it has to be one. 您也可能发现自己处于必须在某处配置sql查询的情况,并且您不能只进行3次调用:它必须是一个。 It shouldn't be that way, bad design, but it is. 不应该那样,糟糕的设计,但确实如此。 You do what you gotta do! 你做你要做的!
  • Sometimes of course it can be very good to encapsulate multiple steps in a stored procedure. 有时,将多个步骤封装在存储过程中当然是非常好的。 Usually not for saving round trips though, but for tighter transactions, getting ID for new records, constraining for permissions, providing encapsulation, blah blah blah. 通常不是为了保存往返,而是为了更紧密的交易,获取新记录的ID,限制权限,提供封装,等等等等。

Making one round-trip vs three will be more eficient indeed. 进行一次往返对比三次确实会更有效。 The question is wether it is worth the trouble. 问题是值得麻烦的。 The entire ADO.Net and C# 3.5 toolset and framework opposes what you try to do. 整个ADO.Net和C#3.5工具集和框架都反对您尝试的操作。 TableAdapters, Linq2SQL, EF, all these like to deal with simple one-call==one-resultset semantics. TableAdapters,Linq2SQL,EF,所有这些都喜欢处理简单的one-call == one-resultset语义。 So you may loose some serious productivity by trying to beat the Framework into submission. 因此,通过尝试击败框架提交,您可能会失去一些严重的生产力。

I would say that unless you have some serious measurements showing that you need to reduce the number of roundtrips, abstain. 我会说,除非你有一些严肃的测量表明你需要减少往返次数,否则弃权。 If you do end up requiring this, then use a stored procedure to at least give an API kind of semantics. 如果你最终要求这样 ,那么使用存储过程至少给出API类型的语义。

But if your query really is what you posted (ie. select all users, all teams and all permissions) then you obviosuly have much bigger fish to fry before reducing the round-trips... reduce the resultsets first. 但是如果您的查询确实是您发布的内容(即选择所有用户, 所有团队和所有权限),那么在减少往返之前,您可能会有更大的鱼来进行煎炸...首先减少结果集。

I this this link might be helpful. 我本链接可能会有所帮助。

Consider using at least the same connection-openning; 考虑至少使用相同的连接 - 打开; according to what it says here , openning a connection is almost the top-leader of performance cost in Entity-Framework. 根据它在这里所说的,开放连接几乎是实体框架中性能成本的最高领导者。

Build a temp-table? 建一个临时表? Insert all results into the temp table and then select * from @temp-table 将所有结果插入临时表,然后select * from @temp-table

as in, 如,

@temptable=....
select @temptable.field=mytable.field from mytable
select @temptable.field2=mytable2.field2 from mytable2

etc... Only one trip to the database, though I'm not sure it is actually more efficient. 等...只有一次数据库之旅,但我不确定它实际上更有效率。

Firstly, 3 round trips isn't really a big deal. 首先,3次往返并不是什么大问题。 If you were talking about 300 round trips then that would be another matter, but for just 3 round trips I would conderer this to definitley be a case of premature optimisation. 如果你正在谈论300次往返那么这将是另一回事,但是对于仅仅3次往返我会认为这是definitley是一个过早优化的情况。

That said, the way I'd do this would probably be to executed the 3 stored procuedres using SQL: 也就是说,我这样做的方式可能是使用SQL执行3个存储的procuedres:

exec dbo.p_myproc_1 @param_1 = @in_param_1, @param_2 = @in_param_2
exec dbo.p_myproc_2
exec dbo.p_myproc_3

You can then iterate through the returned results sets as you would if you directly executed multiple rowsets. 然后,您可以像直接执行多个行集一样遍历返回的结果集。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM