2012-01-17 87 views
0

我正在使用SAX解析器解析網絡上的XML文件。 解析時我想將數據添加到數據庫中,因此我使用INSERT查詢來添加數據。但每個插入需要:10 - 15毫秒,我有近150個記錄,幾乎需要130秒來解析和插入。 我已經嘗試過在事務中插入查詢,但它仍然給我同一時間。我附上我的代碼。我不知道我是否正確解析它,或者我的插入事務是錯誤的?SAX解析器解析需要很長時間才能插入數據庫中

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(); 
    } 
} 

回答

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(); 
} 



+0

但是,然後在ArrayList解析時單獨添加字符串也需要時間嗎? – Change 2012-01-17 19:02:03

+0

是的,但這種方法肯定會爲你節省一些時間,因爲它同時在db中插入多條記錄。此外,如果您可以使用JSON格式進行回覆,則可以使用GSON或JACKSON解析器加速解析(我更喜歡傑克遜)。 – akkilis 2012-01-17 19:09:05

+0

是否有可能,如果你可以更多地解釋我如何添加ih.bind(idIndex,Integer.parseInt(source.getId()));這意味着什麼是getId()函數,它有什麼作用? – Change 2012-01-17 21:51:28

1

你插入語句看的權利。你的數據庫是否有適當的索引?因爲每個INSERT語句都有一個對現有行的隱式查詢,因爲它必須確定行是否已經存在。如果你的代碼中的「key」確實是主鍵,那麼它有一個隱式索引,但如果情況並非如此......那麼這可能會給你帶來麻煩。

另外,您應該知道數據庫操作本質上是緩慢的。有一件事我不明白,如果每個INSERT都花費15ms,那麼150個INSERT如何花費130秒?

另外,一定要看看下面的akkilis'響應(關於InsertHelper),它允許你一次插入多行到你的數據庫[並且如果這對你有用,一定要註冊]。這將要求你在將數據提供給數據庫之前將其存儲在臨時緩衝區中,這應該不是很困難。

上InsertHelper更多信息: http://developer.android.com/reference/android/database/DatabaseUtils.InsertHelper.html

+0

現在肯定會嘗試這部分!因爲我現在插入的方式很瘋狂。這需要很多時間! – Change 2012-01-17 19:08:04

0

不要做每插入一個交易。爲整個INSERT集執行一個事務。每筆交易都涉及閃存I/O,速度很慢。