2011-05-09 64 views
3

我正在使用SQL Server 2008和Java 6/Spring jdbc。将长时间运行的SQL查询拆分为多个较小的查询

我们有一张表,记录数约为60mn。我们需要将这整个表加载到内存中,但是在这个表上触发select *需要几小时才能完成。

因此,我将查询如下

String query = " select * from TABLE where " ; 
     for(int i =0;i<10;i++){ 
      StringBuilder builder = new StringBuilder(query).append(" (sk_table_id % 10) =").append(i); 
      service.submit(new ParallelCacheBuilder(builder.toString(),namedParameters,jdbcTemplate)); 
     } 

基本上,我通过添加对主键列a,其中条件分裂查询,

上面的代码片断拆分查询分成10个查询运行在parallel.this使用java的ExecutorCompletionService

我不是SQL专家,但我想上面的查询将需要加载之前在主列上applyinh模运算符加载相同的数据。

这是好/坏/最好/最坏的方式?有没有其他的方式,请发布。

在此先感谢!

+0

我认为将整个数据加载到内存是一个糟糕的主意。你应该考虑使用存储过程! – CoderHawk 2011-05-09 06:27:28

+0

@Sandy我同意,但程序如何帮助减少时间,请你指导一下? – blob 2011-05-09 06:37:35

+0

为什么你需要加载所有记录?为什么需要几个小时?我会检查获取大小,并检查查询是如何执行的。 – Kaj 2011-05-09 06:37:38

回答

1

如果你确实需要内存中的所有60M记录,select * from ...是最快的方法。是的,这是一个完整的扫描;没有办法。它是磁盘绑定的,所以多线程不会对你有任何帮助。没有足够的可用内存(交换)会立即导致性能下降。需要大量时间进行扩展的数据结构也会影响性能。

打开任务管理器,看看CPU花了多少钱;可能很少;如果没有,请分析您的代码或只是注释掉除阅读循环以外的所有内容。或者也许这是SQL服务器和你的机器之间的网络瓶颈。

也许SQL Server可以使用一些内部路径(例如Oracle可以)更快地将数据卸载到已知格式的外部转储文件。我会探讨将表转储到文件中然后用C#解析该文件的可能性;它可能会更快,例如因为它不会干扰SQL服务器同时提供的其他查询。

+0

谢谢,但我确实观察通过并行运行查询(如后所列)将加载时间减少到40-50%,尽管我无法理解为什么? – blob 2011-05-09 14:04:07

+0

加速对我来说是一个相当奇怪的效果。也许这是由于网络往返时间?无论如何,你可以使用它!我会尝试一下线程的数量,看看哪个数字可以带来最大的收益。此外,您可以尝试在存储过程中收集数组中的一堆记录,并一次性获取该数组,即使您只是将所有内容粘合为一个大字符串,然后再将它们拆分为C#代码。另请参阅[bcp实用程序](http://msdn.microsoft.com/zh-cn/library/aa337544.aspx)及其批量导出模式;也许它通过临时文件仍然更快。 – 9000 2011-05-09 14:51:56