Android SQLite 데이터베이스 : 느린 삽입
상당히 큰 XML 파일 (약 100 킬로바이트에서 100 킬로바이트 사이에서 다름)을 구문 분석해야합니다 Xml#parse(String, ContentHandler)
. 현재 152KB 파일로 관리자를 테스트하고 있습니다.
구문 분석 중에 다음과 같은 경우에 SQLite 호출 데이터를 사용하여 삽입합니다 getWritableDatabase().insert(TABLE_NAME, "_id", values)
.. 이 것이 152KB 테스트 파일의 약 80 초 소요 (대략 200 행을 삽입하는 데 소요됨).
모든 삽입 문을 주석 처리 할 때 (만들기 ContentValues
등 다른 모든 것 ) 같은 파일이 23 초 밖에 걸리지.
데이터베이스 작업에 그렇게 큰 오버 헤드가 발생하는 것이 정상입니까? 무엇에 대해 무엇을 할 수 있습니까?
일괄 삽입해야합니다.
의사 코드 :
db.beginTransaction();
for (entry : listOfEntries) {
db.insert(entry);
}
db.setTransactionSuccessful();
db.endTransaction();
그것은 내 앱의 삽입 속도를 극도로 증가 정당습니다.
업데이트 :
@Yuku는 매우 흥미로운 블로그 게시물을 제공했습니다. Android는 sqlite 데이터베이스에 더 빠른 삽입하기 위해 inserthelper를 사용합니다.
신용장와 브렛이 언급 한 InsertHelper는 현재 사용되지 않으므로 (API 레벨 17) 구글에서 권장하는 올바른 대안은 SQLiteStatement를 사용하는을 구석으로 같습니다 .
다음과 같은 데이터베이스 삽입 방법을 사용했습니다.
database.insert(table, null, values);
나는 또한 몇 가지 심각한 성능 문제를 경험 한 후, 다음 코드에서 제 500 개 삽입을 14.5 초 만에 270 밀리 놀라운!
SQLiteStatement를 사용 방법은 다음과 같습니다.
private void insertTestData() {
String sql = "insert into producttable (name, description, price, stock_available) values (?, ?, ?, ?);";
dbHandler.getWritableDatabase();
database.beginTransaction();
SQLiteStatement stmt = database.compileStatement(sql);
for (int i = 0; i < NUMBER_OF_ROWS; i++) {
//generate some values
stmt.bindString(1, randomName);
stmt.bindString(2, randomDescription);
stmt.bindDouble(3, randomPrice);
stmt.bindLong(4, randomNumber);
long entryID = stmt.executeInsert();
stmt.clearBindings();
}
database.setTransactionSuccessful();
database.endTransaction();
dbHandler.close();
}
SQL 삽입 문을 사용하면 작업 속도를 사용할 수 있습니다. 이제 모든 것이 어깨 위에 있기 때문에 모든 것을 예방하고 가능한 주사를 예방하기 위해 더 많은 노력이 필요합니다.
속도를 높일 수있는 또 다른 접근 방식은 문서화되지 않은 android.database.DatabaseUtils.InsertHelper 클래스입니다. 내 이해는 실제로 컴파일 된 삽입 문을 래핑한다는 것입니다. 컴파일되지 않은 트랜잭션 삽입에서 컴파일 된 트랜잭션 삽입으로 이동하는 것은 제 대규모 (200,000 개 이상의 항목)이지만 간단한 SQLite 삽입의 경우 속도가 약 3 배 향상되었습니다 (삽입 당 2ms에서 삽입 당 .6ms).
샘플 코드 :
SQLiteDatabse db = getWriteableDatabase();
//use the db you would normally use for db.insert, and the "table_name"
//is the same one you would use in db.insert()
InsertHelper iHelp = new InsertHelper(db, "table_name");
//Get the indices you need to bind data to
//Similar to Cursor.getColumnIndex("col_name");
int first_index = iHelp.getColumnIndex("first");
int last_index = iHelp.getColumnIndex("last");
try
{
db.beginTransaction();
for(int i=0 ; i<num_things ; ++i)
{
//need to tell the helper you are inserting (rather than replacing)
iHelp.prepareForInsert();
//do the equivalent of ContentValues.put("field","value") here
iHelp.bind(first_index, thing_1);
iHelp.bind(last_index, thing_2);
//the db.insert() equilvalent
iHelp.execute();
}
db.setTransactionSuccessful();
}
finally
{
db.endTransaction();
}
db.close();
테이블에 인덱스가있는 경우 레코드를 삽입하기 전에 삭제 한 다음 레코드를 커밋 한 후 다시 추가하는 것이 좋습니다.
ContentProvider를 사용하는 경우 :
@Override
public int bulkInsert(Uri uri, ContentValues[] bulkinsertvalues) {
int QueryType = sUriMatcher.match(uri);
int returnValue=0;
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
switch (QueryType) {
case SOME_URI_IM_LOOKING_FOR: //replace this with your real URI
db.beginTransaction();
for (int i = 0; i < bulkinsertvalues.length; i++) {
//get an individual result from the array of ContentValues
ContentValues values = bulkinsertvalues[i];
//insert this record into the local SQLite database using a private function you create, "insertIndividualRecord" (replace with a better function name)
insertIndividualRecord(uri, values);
}
db.setTransactionSuccessful();
db.endTransaction();
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
return returnValue;
}
그런 다음 삽입을 수행하는 개인 함수 (여전히 콘텐츠 제공 업체 내부) :
private Uri insertIndividualRecord(Uri uri, ContentValues values){
//see content provider documentation if this is confusing
if (sUriMatcher.match(uri) != THE_CONSTANT_IM_LOOKING_FOR) {
throw new IllegalArgumentException("Unknown URI " + uri);
}
//example validation if you have a field called "name" in your database
if (values.containsKey(YOUR_CONSTANT_FOR_NAME) == false) {
values.put(YOUR_CONSTANT_FOR_NAME, "");
}
//******add all your other validations
//**********
//time to insert records into your local SQLite database
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
long rowId = db.insert(YOUR_TABLE_NAME, null, values);
if (rowId > 0) {
Uri myUri = ContentUris.withAppendedId(MY_INSERT_URI, rowId);
getContext().getContentResolver().notifyChange(myUri, null);
return myUri;
}
throw new SQLException("Failed to insert row into " + uri);
}
참고 URL : https://stackoverflow.com/questions/3501516/android-sqlite-database-slow-insertion
'IT' 카테고리의 다른 글
Mac OS X Lion에서 localhost / virtualhost의 느린 확인 /로드 (2 ~ 3 초 지연)를 제거해야합니까? (0) | 2020.09.04 |
---|---|
레이아웃 제약은 언제 활성화 / 비활성화 할 수 있습니까? (0) | 2020.09.04 |
Android : 여러 선택 옵션이있는 팝업 만들기 (0) | 2020.09.04 |
PHP의 다이와 동등한 JavaScript (0) | 2020.09.04 |
Ubuntu에 새로 설치 한 후 사용자 'root'@ 'localhost'(암호 : YES 사용)에 대한 액세스가 거부되었습니다. (0) | 2020.09.04 |