【问题标题】:How to avoid OOM in hsqldb while doing a merge?合并时如何避免hsqldb中的OOM?
【发布时间】:2013-02-25 22:48:10
【问题描述】:

我有两个表,其中第一个非常大(>50M 行):

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

第二个也可以很大(>5M 行):

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 表中的数据,然后将表合并到所有距离:

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?

【问题讨论】:

  • 50kk 是 50,000 (50K) 还是 50,000,000 (50M) ?
  • 您使用的是 Oracle 还是 SQL-Server?您是否打算将 sql 表示为 sql-server?
  • OP 正在使用 HSQLDB,它是一个 RDBMS

标签: java sql merge hsqldb


【解决方案1】:

可以在 SQL 中以块(批次)的形式进行合并。你需要

  • 限制每个块中临时表的行数
  • 删除那些相同的行
  • 重复

SELECT 语句应该使用 ORDER BY 和 LIMIT

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

) AS src (

合并后,delete语句会选择相同的行进行删除

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)

【讨论】:

    【解决方案2】:

    首先,就因为这种事情让我很烦,你为什么要在一个子选择中选择临时表的所有字段?为什么不使用更简单的 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);
    

    【讨论】:

    • 感谢您的改进。由于这是我第一个使用数据库的程序,我很高兴这个合并命令可以满足我的需求,而美学只是次要问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 2017-11-19
    • 1970-01-01
    相关资源
    最近更新 更多