从多个连接表的子集加载数据集的最有效方法
本文关键字:数据集 有效 方法 加载 子集 连接 | 更新日期: 2023-09-27 18:17:11
我有一个很大的库存系统,我不得不重写其中的一部分I/O部分。在它的核心,有一个产品表和一组相关的表。我需要尽可能高效地阅读其中的部分内容。我在c#中构造了这个查询:
select * -- includes productid
into #tt
from products where productClass = 547 -- possibly more conditions
select * from #tt;
select * from productHistory where productid in (select productid from #tt);
select * from productSuppliers where productid in (select productid from #tt);
select * from productSafetyInfo where productid in (select productid from #tt);
select * from productMiscInfo where productid in (select productid from #tt);
drop table #tt;
这个查询给了我所需要的结果:5个结果集,每个结果集有0个、一个或多个记录(如果第一个返回0行,其他的当然也会返回0行)。然后程序将这些结果集塞入合适的DataSet
。(然后将其传递给只需要这些记录的构造函数。)这个查询(有不同的条件)以批次运行。
我的问题是,是否有更有效的方法来检索这些数据?
将其作为单个连接重新工作将无法工作,因为每个子节点可能返回可变数量的行。
如果您有产品索引。
select * from products where productClass = 547 -- includes productid
select productHistory.*
from productHistory
join products
on products.productid = productHistory.productid
and products,productClass = 547;
...
如果productID是一个聚集索引,那么使用
可能会获得更好的持久性。 CREATE TABLE #Temp (productid INT PRIMARY KEY CLUSTERED);
insert into #temp
select productid from products where productClass = 547
order by productid;
go
select productHistory.*
from productHistory
join #Temp
on #Temp.productid = productHistory.productid;
在聚集索引上的连接似乎提供了最好的性能。想想看——SQL可以匹配第一个,并且知道它可以忘记其余的,然后移动到第二个,知道它可以向前移动(而不是回到顶部)。使用where (select…)SQL不能利用顺序。需要连接的表越多,使用#temp的理由就越多,因为创建#temp大约需要1/2秒的时间。如果你要使用#temp,你最好将它设置为一个结构化的temp
请确保在索引上连接JOIN
表。否则,你将以表扫描和索引扫描告终,你的代码将非常缓慢,特别是在连接大型表时。
最佳实践是优化SQL查询以避免表扫描。
如果还没有,我强烈建议将其作为一个存储过程。
此外,我怀疑(但不能在没有测试的情况下证明),如果对每个子表执行产品表上的连接,而不是复制到本地表,您将获得更好的性能。
最后,除非你能把这些数据组合起来,否则我认为没有比这更有效的方法了
如果不了解模式并对数据和表大小有更多的了解,就很难对查询端提出明确的改进建议。
但是,由于您使用的是批处理命令来返回多个结果集,因此您可以使用SqlDataAdapter来完成这部分工作,而不是"将结果塞进适当的数据集":
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataSet results = new DataSet();
adapter.Fill(results);
之后,第一个结果集将在results中。表[0],第二个结果。表[1]等。