Разбор SAX Parser занимает много времени для вставки в базу данных - PullRequest
0 голосов
/ 17 января 2012

Я использую 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();
    }
 }

Ответы [ 3 ]

3 голосов
/ 17 января 2012

Вы вставляете одну строку каждый раз и, возможно, каждый раз выполняете db.open () и db.close ().
Вместо этого попробуйте использовать «InsertHelper».
Необработанный пример использованияэто показано ниже:

private void insertTweetSourcesInBulk(ArrayList tweetSources, boolean replace) { InsertHelper ih = new InsertHelper(db, TABLE_NAME_TWEET_SOURCE);</p> <pre><code> 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 голос
/ 17 января 2012

Ваши операторы вставки выглядят правильно. Ваша база данных имеет правильный индекс? Потому что каждый оператор INSERT имеет неявный запрос для существующих строк, так как он должен определить, существует ли строка или нет. Если «ключ» в вашем коде действительно является первичным ключом, то он имеет неявный индекс, но если это не так ... тогда это может вызвать проблемы.

Кроме того, вы должны знать, что операции с базами данных медленны по своей природе. Одна вещь, которую я не понимаю, это то, что если каждая ВСТАВКА занимает у вас 15 мс, почему 150 ВСТАВЛЕНИЙ занимают 130 секунд?

Кроме того, обязательно посмотрите ответ akkilis ниже (о InsertHelper), который позволяет вам вставлять несколько строк в вашу БД одновременно [и если это полезно для вас, обязательно поднимите голосование]. Это потребует от вас накопления ваших строк во временном буфере до подачи их в базу данных, что не должно быть очень сложным.

Дополнительная информация о InsertHelper: http://developer.android.com/reference/android/database/DatabaseUtils.InsertHelper.html

0 голосов
/ 17 января 2012

Не делайте одну транзакцию на одну вставку.Сделайте одну транзакцию для всего набора INSERT.Каждая транзакция включает в себя флэш-ввод-вывод, который выполняется медленно.

...