2011-05-09 67 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