【问题标题】:SAX Parser parsing takes long time to insert in databaseSAX Parser 解析需要很长时间才能插入数据库
【发布时间】:2012-01-17 18:43:56
【问题描述】:

我正在使用 SAX Parser 通过网络解析 XML 文件。 在解析时,我想将数据添加到数据库中,因此我使用 INSERT 查询来添加数据。但每次插入需要:10 - 15 毫秒,我有近 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();
    }
 }

【问题讨论】:

    标签: android sqlite sax


    【解决方案1】:

    您每次都插入一行,并且可能每次都在执行 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();
    }
    



    【讨论】:

    • 但是在 ArrayList 中解析时单独添加字符串也需要时间吧?
    • 是的,但是这种方法肯定会为您节省一些时间,因为它会同时在数据库中插入多个记录。此外,如果您可以使用 JSON 格式的响应,则可以使用 GSON 或 JACKSON 解析器(我更喜欢 jackson)加快解析速度。
    • 是否可以向我解释一下如何添加 ih.bind(idIndex, Integer.parseInt(source.getId()));意思是什么是 getId() 函数,它有什么作用?
    【解决方案2】:

    您的插入语句看起来正确。您的数据库是否有适当的索引?因为每个 INSERT 语句都有一个对现有行的隐式查询,因为它必须确定一行是否已经存在。如果你的代码中的“key”确实是主键,那么它有一个隐式索引,但如果不是这样......那么这可能会给你带来麻烦。

    此外,您应该知道数据库操作本质上是缓慢的。我不明白的一件事是,如果每个 INSERT 需要 15 毫秒,为什么 150 个 INSERT 需要 130 秒?

    此外,请务必查看下面的 akkilis 的回复(关于 InsertHelper),它允许您一次将多行插入到您的数据库中 [如果这对您有用,请务必点赞]。这将要求您在将行输入数据库之前将它们累积在一个临时缓冲区中,这应该不是很困难。

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

    【讨论】:

    • 现在肯定会尝试那个部分!因为我现在插入的方式很疯狂。这需要很多时间!
    【解决方案3】:

    不要在每个 INSERT 中执行一项事务。为整个 INSERT 集执行一个事务。每个事务都涉及闪存 I/O,速度很慢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-22
      • 2022-01-20
      • 1970-01-01
      • 1970-01-01
      • 2017-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多