[英]Best way to select out of millions of rows in an Oracle DB
天儿真好!
我有一百万个不同的单词,我想在一个有1500万行的表中查询。 同义词和单词的结果将在每次查询后得到处理。
表看起来像这样:
synonym word
---------------------
ancient old
anile old
centenarian old
darkened old
distant far
remote far
calm gentle
quite gentle
这就是目前在Java中完成的方式:
....
PreparedStatement stmt;
ResultSet wordList;
ResultSet syns;
...
stmt = conn.prepareStatement("select distinct word from table");
wordList = stmt.executeQuery();
while (wordList.next()) {
stmt = conn.prepareStatement("select synonym from table where word=?");
stmt.setString(1, wordList.getString(1));
syns = stmt.executeQuery();
process(syns, wordList.getString(1));
}
...
这令人难以置信的缓慢。 做这样的事情的最快方法是什么?
干杯,克里斯
确保'word'列上有索引。
将第二个prepareStatement移到word循环之外。 每次创建新语句时,数据库都会编译并优化查询 - 但在这种情况下查询是相同的,因此这是不必要的。
结合上面的sblundy所做的陈述。
两个想法:
a)如何使它成为一个查询:
select synonym from table where word in (select distinct word from table)
b)或者,如果您process
方法需要将它们作为一个单词的一组同义词来处理,为什么不word
对它们进行排序并在每次word
不同时重新开始process
? 该查询将是:
select word, synonym
from table
order by word
如果你要查询所有这些同义词,为什么要查询循环内的同义词? 您应该使用单个select word, synonym from table order by word
,然后在Java代码中select word, synonym from table order by word
分割。
PreparedStatement stmt;
ResultSet syns;
...
stmt = conn.prepareStatement("select distinct " +
" sy.synonm " +
"from " +
" table sy " +
" table wd " +
"where sy.word = wd.word");
syns = stmt.executeQuery();
process(syns);
相关但不相关:
while (wordList.next()) {
stmt = conn.prepareStatement("select synonym from table where word=?");
stmt.setString(1, wordList.getString(1));
syns = stmt.executeQuery();
process(syns, wordList.getString(1));
}
您应该在循环外移动该preparestatement调用:
stmt = conn.prepareStatement("select synonym from table where word=?");
while (wordList.next()) {
stmt.setString(1, wordList.getString(1));
syns = stmt.executeQuery();
process(syns, wordList.getString(1));
}
准备语句的全部意义在于db编译/缓存/等等,因为您将重复使用该语句。 如果要执行那么多查询,还可能需要显式清理结果集,以确保不会用尽游标。
您还应该考虑使用语句对象的setFetchSize方法来减少应用程序和数据库之间的上下文切换。 如果您知道要处理一百万条记录,则应使用setFetchSize(someRelativelyHighNumberLike1000)。 这告诉java每次从Oracle需要更多记录时最多可以抓取1000条记录[而不是一次抓取一条记录,这是这种批处理操作的最坏情况]。 这将提高您的程序的速度。 您还应该考虑重构和批处理您的单词/同义词,如
比...慢
只需在某个数组结构中保持50/100/1000 [或者一次检索多少],直到您处理它们为止。
问题已经解决了。 重要的是,表可以按字排序。 因此,我可以轻松地遍历整个表格。 像这样:
....
Statement stmt;
ResultSet rs;
String currentWord;
HashSet<String> syns = new HashSet<String>();
...
stmt = conn.createStatement();
rs = stmt.executeQuery(select word, synonym from table order by word);
rs.next();
currentWord = rs.getString(1);
syns.add(rs.getString(2));
while (rs.next()) {
if (rs.getString(1) != currentWord) {
process(syns, currentWord);
syns.clear();
currentWord = rs.getString(1);
}
syns.add(rs.getString(2));
}
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.