我正在使用SAX Parser通过网络解析XML文件。 解析时我想将数据添加到数据库中,因此我使用INSERT查询来添加数据。但每个插入需要:10 - 15 ms,我有近150条记录,几乎需要130秒才能解析和插入。 我试图在事务中包装插入查询,但它仍然给我同样的时间。我附上了我的代码。我不确定我是正确解析它还是我的插入事务是错误的?
XMLHandler.java
public class XMLHandler extends DefaultHandler {
private static boolean inKey = false;
private static boolean inCode = false;
private static boolean inTitle = false;
private static boolean inType = false;
private static boolean inRoom = false;
private static boolean inDescription = false;
private static boolean inStart = false;
private List List = new List();
public void startElement(String uri, String name, String qName,
Attributes atts) {
if (name.trim().equals("key"))
inKey = true;
else if (name.trim().equals("code"))
inCode = true;
else if (name.trim().equals("title"))
inTitle = true;
else if (name.trim().equals("type"))
inType = true;
else if (name.trim().equals("room"))
inRoom = true;
else if (name.trim().equals("description"))
inDescription = true;
else if (name.trim().equals("start"))
inClassStart = true;
}
public void endElement(String uri, String name, String qName)
throws SAXException {
if (name.trim().equals("key"))
inKey = false;
else if (name.trim().equals("code"))
inCode = false;
else if (name.trim().equals("title"))
inTitle = false;
else if (name.trim().equals("type"))
inType = false;
else if (name.trim().equals("room"))
inRoom = false;
else if (name.trim().equals("description"))
inDescription = false;
else if (name.trim().equals("start"))
inClassStart = false;
}
public void characters(char ch[], int start, int length) {
String chars = (new String(ch).substring(start, start + length));
try {
if(inKey)
List.key = chars;
if(inCode)
List.code = chars;
if(inTitle)
List.title = chars;
if(inType)
List.type = chars;
if(inRoom)
List.room = chars;
if(inDescription)
List.description = chars;
if(inStart)
List.start = chars;
DB.insertFeed(List.key, List.code, List.title, List.type, List.room, List.description, List.start);
} catch (Exception e) {
Log.e("NewsDroid", e.toString());
}
}
DatabaseManager.java
public void insertFeed( String key, String code, String title, String type, String room, String desc,String start) {
db.beginTransaction();
try{
String sql = "INSERT OR REPLACE INTO " + TEST+ "(KEY,CODE,TITLE, TYPE ,ROOM , DESCRIPTION, START) VALUES" + "(?,?,?,?,?,?,?);";
Object [] bindArgs = new Object[]{key,code,title,type,room, desc,start};
db.execSQL(sql, bindArgs);
db.setTransactionSuccessful();
}
catch (SQLException e){}
finally{
db.endTransaction();
}
}
答案 0 :(得分:3)
每次都插入一行,每次都可能正在执行db.open()和db.close()。而不是尝试使用“InsertHelper”。
一个粗略的例子使用如下所示:
private void insertTweetSourcesInBulk(ArrayList tweetSources, boolean replace) {
InsertHelper ih = new InsertHelper(db, TABLE_NAME_TWEET_SOURCE);
final int idIndex = ih.getColumnIndex(Audio._ID);
final int sequenceNumIndex = ih.getColumnIndex(TweetSource.SEQUENCE_NUM);
final int thumbnailUrlIndex = ih.getColumnIndex(TweetSource.THUMBNAIL_URL);
final int titleIndex = ih.getColumnIndex(TweetSource.TITLE);
for (TweetSource source : tweetSources) {
Logger.log(TAG, "Inserting id: " + source.getId());
if (replace) {
ih.prepareForReplace();
} else {
ih.prepareForInsert();
}
ih.bind(idIndex, Integer.parseInt(source.getId()));
ih.bind(sequenceNumIndex, Float.parseFloat(source.getSequenceNum()));
ih.bind(thumbnailUrlIndex, source.getThumbnailUrl());
ih.bind(titleIndex, source.getTitle());
ih.execute();
}
ih.close();
}
final int idIndex = ih.getColumnIndex(Audio._ID);
final int sequenceNumIndex = ih.getColumnIndex(TweetSource.SEQUENCE_NUM);
final int thumbnailUrlIndex = ih.getColumnIndex(TweetSource.THUMBNAIL_URL);
final int titleIndex = ih.getColumnIndex(TweetSource.TITLE);
for (TweetSource source : tweetSources) {
Logger.log(TAG, "Inserting id: " + source.getId());
if (replace) {
ih.prepareForReplace();
} else {
ih.prepareForInsert();
}
ih.bind(idIndex, Integer.parseInt(source.getId()));
ih.bind(sequenceNumIndex, Float.parseFloat(source.getSequenceNum()));
ih.bind(thumbnailUrlIndex, source.getThumbnailUrl());
ih.bind(titleIndex, source.getTitle());
ih.execute();
}
ih.close();
}
答案 1 :(得分:1)
您的插入语句看起来正确。您的数据库是否有适当的索引?因为每个INSERT语句都有对现有行的隐式查询,因为它必须确定行是否已存在。如果您的代码上的“密钥”确实是主键,那么它有一个隐式索引,但如果情况并非如此......那么这可能会给您带来麻烦。
此外,您应该知道数据库操作本质上很慢。我没有得到的一件事是,如果每个INSERT花费你15ms,那么150个INSERT如何花费130秒?
另外,请务必查看下面的akkilis响应(关于InsertHelper),它允许您一次向数据库中插入多行[如果这对您有用,请确保upvote]。这将要求您在将行提供到数据库之前将其累积在临时缓冲区中,这应该不是很困难。
有关InsertHelper的更多信息: http://developer.android.com/reference/android/database/DatabaseUtils.InsertHelper.html
答案 2 :(得分:0)
每个INSERT不要执行一个事务。为整组INSERT执行一个事务。每个事务都涉及闪存I / O,这很慢。