2013-03-10 42 views
1

我有兩個表,其中第一非常大(> 50M行):如何在合併時避免hsqldb中的OOM?

CREATE CACHED TABLE Alldistances (
    word1 VARCHAR(70), 
    word2 VARCHAR(70), 
    distance INTEGER, 
    distcount INTEGER 
); 

和第二,可以是也相當大(> 500萬行):

CREATE CACHED TABLE tempcach (
    word1 VARCHAR(70), 
    word2 VARCHAR(70), 
    distance INTEGER, 
    distcount INTEGER 
); 

兩個表都有指標:

CREATE INDEX mulalldis ON Alldistances (word1, word2, distance); 
CREATE INDEX multem ON tempcach (word1, word2, distance); 

在我的Java程序我使用準備好的發言填充/在tempcach表preorganize數據,然後我合併表進行alldistances:

MERGE INTO Alldistances alld USING ( 

    SELECT word1, 
      word2, 
      distance, 
      distcount FROM tempcach 

    ) AS src (

     newword1, 
     newword2, 
     newdistance, 
     newcount 

    ) ON (

      alld.word1 = src.newword1 
     AND alld.word2 = src.newword2 
     AND alld.distance = src.newdistance 

    ) WHEN MATCHED THEN 

     UPDATE SET alld.distcount = alld.distcount+src.newcount 

    WHEN NOT MATCHED THEN 

     INSERT (

      word1, 
      word2, 
      distance, 
      distcount 

     ) VALUES (

      newword1, 
      newword2, 
      newdistance, 
      newcount 
     ); 

然後刪除或截斷tempchach表並填充新數據。 合併期間,我得到了OOM,這是我猜測,因爲整個表在合併期間被加載到內存中。所以我將不得不批量合併,但是我可以在SQL中執行此操作,還是可以在我的Java程序中執行此操作。還是有一種巧妙的方式來避免合併時的OOM?

+0

是50kk 50,000(50K)還是50,000,000(50M)? – 2013-03-10 20:43:06

+0

您使用的是Oracle還是SQL-Server?你打算sql來表示sql-server嗎? – 2013-03-10 20:50:21

+0

OP正在使用HSQLDB,這是一個RDBMS – fredt 2013-03-10 20:51:54

回答

0

可以在SQL中以塊(批)進行合併。您需要

  • 限制從臨時表中的行數在每塊
  • 刪除這些相同的行
  • 重複

SELECT語句應該使用ORDER BY和LIMIT

SELECT word1, 
     word2, 
     distance, 
     distcount FROM tempcach 
     ORDER BY primary key or unique columns 
     LIMIT 1000 

) AS src (

合併後,刪除語句將選擇相同的行刪除

DELETE FROM tempcach WHERE primary key or unique columns IN 
     (SELECT primary key or unique columns FROM tempcach 
     ORDER BY primary key or unique columns LIMIT 1000) 
0

首先,僅僅因爲這種事情讓我很煩惱,爲什麼你要在一個子選擇中選擇臨時表的所有字段呢?爲什麼不是更簡單的SQL:

MERGE INTO Alldistances alld USING tempcach AS src (
    newword1, 
    newword2, 
    newdistance, 
    newcount 
) ON (
     alld.word1 = src.newword1 
    AND alld.word2 = src.newword2 
    AND alld.distance = src.newdistance 
) WHEN MATCHED THEN 
    UPDATE SET alld.distcount = alld.distcount+src.newcount 
WHEN NOT MATCHED THEN 
    INSERT (
     word1, 
     word2, 
     distance, 
     distcount 
    ) VALUES (
     newword1, 
     newword2, 
     newdistance, 
     newcount 
    ); 

什麼你需要有數據庫避免加載整個表到內存是兩個表上的索引。

CREATE INDEX all_data ON Alldistances (word1, word2, distance); 
CREATE INDEX tempcach_data ON tempcach (word1, word2, distance); 
+0

感謝您的改進。由於這是我使用數據庫的第一個程序,我很高興這個合併命令能夠完成我想要的功能,而美學只是次要的問題。 – user2154610 2013-03-11 19:04:24