我有一个需要在数据库中插入大量行的应用程序,但目前插入速度太慢,我想知道什么是加快插入速度的最佳技术。
情况是在每次插入时,我需要发现令牌的id,为此,我将SELECT放在插入内。
对于加速textBlockHasToken
表(包括SQL和Java)的最大插入,哪个可以是最佳解决方案?
编辑:目前有效,但我的数据流量很大。一些数字,令牌表中有100,000个不同的行,textBlockHasToken中有200万行。
我有这三个表和两个插入SQL:
-- Text blocks of the pages
CREATE TABLE textBlock(
id INTEGER PRIMARY KEY,
pageId INTEGER REFERENCES page,
text VARCHAR NOT NULL,
position INTEGER NOT NULL
);
-- Tokens in the text blocks
CREATE TABLE token(
id INTEGER PRIMARY KEY,
text VARCHAR NOT NULL,
charType VARCHAR NOT NULL,
grammar VARCHAR NOT NULL,
category VARCHAR[] NOT NULL,
stopWord BOOLEAN NOT NULL DEFAULT false,
UNIQUE(text)
);
-- N:N relationship between textblock and token
CREATE TABLE textBlockHasToken(
textBlockId INTEGER REFERENCES textBlock NOT NULL,
tokenId INTEGER REFERENCES token NOT NULL,
sentence INTEGER NOT NULL,
position INTEGER NOT NULL
);
-- Insert the token
INSERT INTO token(id,text,charType,grammar,category)
VALUES(nextval('tokenIdSqc'),?,?,?,?);
-- Insert in relationship in N:M
INSERT INTO textBlockHasToken(textblockId,tokenId,sentence,position)
VALUES(?,(SELECT id FROM token WHERE text = ?),?,?);
答案 0 :(得分:5)
您可以做的最好的事情是确保所有WHERE变量都有与之关联的索引。它们是为主键自动创建的;确保外键列也有索引。
另一个考虑因素是批处理请求。不要为每个INSERT进行网络往返;将它们一起批处理并提交每个块。这意味着更少的网络往返次数和可管理的交易日志。
答案 1 :(得分:3)
-- Text blocks of the pages
DROP TABLE tmp.textblock CASCADE;
CREATE TABLE tmp.textblock
( id INTEGER PRIMARY KEY
, pageid INTEGER -- REFERENCES page
, ztext VARCHAR NOT NULL
, position INTEGER NOT NULL
);
-- Tokens in the text blocks
DROP TABLE tmp.token CASCADE;
DROP SEQUENCE tmp.tokenidsqc;
CREATE SEQUENCE tmp.tokenidsqc;
CREATE TABLE tmp.token
( id INTEGER PRIMARY KEY DEFAULT nextval('tmp.tokenidsqc')
, ztext VARCHAR NOT NULL
, chartype VARCHAR NOT NULL
, grammar VARCHAR NOT NULL
, category VARCHAR NOT NULL
, stopword BOOLEAN NOT NULL DEFAULT false
, UNIQUE(ztext)
);
-- N:N relationship between textblock and token
DROP TABLE tmp.textblockhastoken CASCADE;
CREATE TABLE tmp.textblockhastoken
( textblockid INTEGER NOT NULL REFERENCES tmp.textblock(id)
, tokenid INTEGER NOT NULL REFERENCES tmp.token(id)
, sentence INTEGER NOT NULL
, position INTEGER NOT NULL
);
-- Insert the token
INSERT INTO tmp.token(ztext,chartype,grammar,category)
VALUES('foo' , 'T' , 'a', 'a' ), ('bar' , 'T' , 'a', 'a' );
SELECT * FROM tmp.token;
答案 2 :(得分:1)
我完全同意duffymo,但我还要补充一点,Postgres's COPY feature是导入数据的方式..
当然,这样做并不总是可行的,特别是在代码中。这就是为什么我也同意duffymo,如果你需要在一台单独的机器上用代码来做,那就去做duffymo说的。
答案 3 :(得分:1)
duffymo已经提到了批量更新。只是为了确保我会添加:
但是在不了解现有代码的情况下,这完全是水晶球猜测。