【问题标题】:Splitting Long running SQL query into multiple smaller queries将长时间运行的 SQL 查询拆分为多个较小的查询
【发布时间】:2011-05-09 06:22:06
【问题描述】:

我正在使用 SQL Server 2008 和 Java 6 / Spring jdbc。

我们有一个记录数约为 6000 万的表。

我们需要将整个表加载到内存中,但是在这个表上触发 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));
        }

基本上,我通过在主键列上添加 where 条件来拆分查询,

上面的代码 sn-p 将查询拆分为 10 个并行运行的查询。这使用了 java 的 ExecutorCompletionService

我不是 SQL 专家,但我猜上述查询需要先在内存中加载相同的数据,然后再在主列上应用模数运算符。

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

提前致谢!!!

【问题讨论】:

  • 我认为将整个数据加载到内存是个坏主意。您应该考虑使用存储过程!
  • @Sandy 我同意,但是程序将如何帮助减少时间,请您指导一下?
  • 为什么需要加载所有记录?为什么需要几个小时?我会检查获取大小,并检查查询是如何执行的。
  • 这个查询是用来获取记录缓存的吗?
  • @Kaj 我们正在内存数据库中构建,所以我需要内存中的整个表,根据数据库上的负载,加载需要 1.25-1.5 小时,您指的是 java / sql server 的获取大小

标签: java sql sql-server-2008 jdbc


【解决方案1】:

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

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

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

【讨论】:

  • 谢谢,但我确实观察到通过并行运行查询(如帖子中所列)将加载时间减少到 40-50%,但我不明白为什么?
  • 加速对我来说是一个相当奇怪的效果。也许是由于网络往返时间?无论如何,你可以使用它!我会试验线程的数量,看看哪个数字能带来最大的收益。此外,您可以尝试在存储过程中的数组中收集一堆记录并一次性获取这些记录,即使您只是将所有内容作为一个大字符串粘合在一起,然后在 C# 代码中拆分。还要看看bcp utility 及其批量导出模式;也许通过临时文件仍然更快。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-20
  • 2021-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-21
相关资源
最近更新 更多