2012-03-01 58 views
0

我正在使用存储过程从数据库中获取信息。首先,我获取所有的父元素,并将它们保存在数组中,然后使用父ID来获取所有相关的子元素。每个家长可以有150个孩子。大约有100个父元素。提高抓取操作性能的最佳方法是什么?目前需要13秒才能检索。提高数据库提取操作的性能

这是基本的算法:

while(reader.read()) 
{ 
    Parent p = new Parent(); 
    // assign properties to the parent 

    p.Children = GetChildrenByParentId(parent.Id);  
} 
+1

不GetChildrenByParentId()创建另一个连接,并调用另一个存储过程? – Jason 2012-03-01 15:45:05

+0

是的,它创建一个单独的连接并调用一个单独的存储过程 – azamsharp 2012-03-01 15:45:39

+0

您正在使用哪个版本的SQL Server? – Jason 2012-03-01 15:48:28

回答

4

你应该得到一个SQL选择/存储过程的所有数据(做一些参加儿童的数据),然后填充家长和孩子的对象。现在你在DB和I上有100 * 150 = 15000个请求,如果你可以用一个请求来做到这一点,我会期望有戏剧性的效果。

布赖恩在评论中提到它,被称为RBAR,RowByAgonizingRow :) 像achronime很多,这里是更多:

https://www.simple-talk.com/sql/t-sql-programming/rbar--row-by-agonizing-row/

+0

我想我可以试试!谢谢 – azamsharp 2012-03-01 15:52:26

+1

+1 Antonio。这就是所谓的RBAR(谷歌它)。关系数据库被设计来检索集合。这个代码可以比较去银行并且提取1000美元(1000次交易!),而不是用1次交易提取1000美元。 – brian 2012-03-01 15:56:28

1

第一个也是最重要的一步是测量性能。 SQL Server是瓶颈还是.NET?另外,您需要尽量减少返回到数据库的时间,因此如果您可以在单个存储过程中检索所需的所有数据,那将是最佳选择。

从你的问题,这听起来像它是SQL Server是问题。为了测试这个,从SQL Query Anylizer运行你的存储过程,并且看看一个已知的父ID需要多长时间。我敢打赌,您只需将一些索引添加到基础表中即可使SQL更快地获取数据。如果可能,请查看存储过程的执行计划。你可以找到一篇关于阅读执行计划here的好文章。

1

SQL Server 2008非常简单,可以创建一个用户定义的表类型并将父类型ID列表传递给该类型,或者您可以使用您首先获得这些父类型ID的逻辑并加入到表中拥有儿童数据。

要创建的表类型,你让这样的事情:

CREATE TYPE [dbo].[Int32List] 
AS TABLE (
[ID] int NOT NULL 
); 
GO 

而且你的存储过程是这样的:

CREATE PROCEDURE [dbo].[MyStoredProc] 
@ParentIDTable [dbo].[Int32List] READONLY 
AS 
--logic goes here 
GO 

你从这样的C#代码调用程序:

DataTable ParentIDs = new DataTable(); 
ParentIDs.Columns.Add("ID", typeof(int)); 

SqlConnection connection = new SqlConnection(yourConnectionInfo); 
SqlCommand command = new SqlCommand("MyStoredProc", connection); 
command.CommandType = CommandType.StoredProcedure; 
command.Parameters.Add("@ParentIDTable", SqlDbType.Structured).Value = ParentIDs; 
command.Parameters["@ParentIDTable"].TypeName = "Int32List"; 

这种方式很好,因为这是一个很好的方式来有效地传递一个列表v到SQL Server的线索并将其视为一张表。我使用的表格类型遍及我的应用程序,我想将一个值的数组传递给存储过程。请记住,C#DataTable中的列名需要与您创建的表类型中的列名匹配,并且TypeName属性需要与表类型的名称匹配。

使用此方法,您只会对数据库进行1次调用,并且在遍历结果时,还应确保将ParentID包括在选择列表中,以便您可以将每个子对象与适当的父对象进行匹配。

这里有一个很好的资源,更详细地解释表类型:http://www.sommarskog.se/arrays-in-sql-2008.html