2012-05-24 3 views
3

데이터베이스에 10,00,000 개의 행을 삽입하려고하지만 삽입하는 데 시간이 너무 오래 걸립니다.sqlite3 데이터베이스에 1000000 행 삽입

이제 나는 2055 개의 행을 가지고이 데이터를 시도하고 있는데,이 데이터를 데이터베이스에 업로드하는 데 3 분이 걸린다. 그리고 이번에는 2055 개의 항목이 너무 많다.

 public void insert_database(Context context,String field1,String field2,String field3,String field4,String field5,String field6 ,String field7,String field8,String field9,String field10) 
{ 

    try 
    { 
     //RayAllen_Database.beginTransaction(); 
     RayAllen_Database.execSQL(" insert or replace into "+ TableName_csv+" values('"+field1+"' ,'"+field2+"','"+field3+"','"+field4+"','"+field5+"','"+field6+"','"+field7+"','"+field8+"','"+field9+"','"+field10+"');"); 


    } 
    catch(Exception e) 
    { 
     //Log.i("Database Exception", "Exception"); 
     e.printStackTrace(); 
    } 

} 

와라는 다른 클래스 : 구문 분석 데이터 :

다음

는 데이터베이스에 데이터를 삽입하는 나의 방법이다 여기에 내가 CSV 파일을 구문 분석하고하는 동안 구문 분석 :

시도 그래서 여기에 그것은 하나의 행을 구문 분석하고 데이터베이스에 항목을 삽입 할 삽입 메소드를 호출한다 {

CSVReader reader=new CSVReader(new FileReader(filename)); 
String [] nextLine; 

//create database 
obj.create_database(context); 
obj.OpenDatabase(context); 
//reader.readNext(); 

while ((nextLine=reader.readNext())!=null) 
{ 
      //here I am calling the insert_database function 
    } 
} 

..

하지만 시간이 너무 많이 걸립니다.이 성능을 어떻게 향상시킬 수 있습니까 ??

+0

문장을 한 번 준비하고 세션의 모든 삽입에 사용합니다. 이렇게하면 더 빨라질 것입니다. http://developer.android.com/reference/java/sql/PreparedStatement.html –

+0

CSV를 구문 분석하고 기기에서 DB를 채우는 이유가 있습니까? 오프라인으로 할 수 있습니까? – Rajesh

+0

하지만 데이터베이스에 저장하기 위해 행별로 읽을 필요가 있으므로 CSV 파일을 가져오고 있습니다. – Kanika

답변

7

"잘못된"대신 올바로 처리해야하는 간단한 예제. 이것은 끔찍한 INSERT 성능을 가진 ICS 4.0.4에서 테스트되었습니다.

먼저 제약 조건이있는 테이블을 만들어 열을 충돌시키는 간단한 SQLiteOpenHelper입니다.

class SimpleHelper extends SQLiteOpenHelper { 
    // InsertHelpers are a really good idea - they format a prepared statement 
    // for you automatically. 
    InsertHelper mInsert; 
    public SimpleHelper(Context context) { 
     super(context, "tanika.db", null, 1); 
    } 
    @Override 
    public void onOpen(SQLiteDatabase db) { 
     super.onOpen(db); 
     mInsert = new InsertHelper(db, "target"); 
    } 
    @Override 
    public void onCreate(SQLiteDatabase db) { 
     db.execSQL("CREATE TABLE target (\n" + 
       "_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" + 
       "val1 TEXT NOT NULL,\n" + 
       "val2 TEXT NOT NULL,\n" + 
       "val3 TEXT NOT NULL,\n" + 
       // Let's make one unique so we can get some juicy conflicts 
       "val4 TEXT NOT NULL UNIQUE\n" + 
       ")"); 
    } 
    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
    } 
} 

우리는 다음과 같은 간단한 시험 방법을 추가 오래된 Activity에 번들 : 당신이 볼 수 있듯이

long test(final int n) { 
    long started = System.currentTimeMillis(); 
    ContentValues values = new ContentValues(); 

    for (int i = 0; i < n; i++) { 
     values.clear(); 
     // Every 20th insert, generate a conflict in val4 
     String val4 = String.valueOf(started + i); 
     if (i % 20 == 0) { 
      val4 = "conflict"; 
     } 
     values.put("val1", "Value1"); 
     values.put("val2", "Value2"); 
     values.put("val3", "Value3"); 
     values.put("val4", val4); 
     mHelper.mInsert.replace(values); 
    } 
    return System.currentTimeMillis() - started; 
} 

, 이것은 충돌 각 20 INSERT 정도를 일으킬 것입니다. InsertHelper#replace(..)을 호출하면 도우미가 충돌시 INSERT OR REPLACE을 사용하게됩니다.

이제이 트랜잭션을 둘러싼 트랜잭션없이이 테스트 코드를 &으로 실행 해 봅시다.

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    mHelper = new SimpleHelper(this); 
    mHelper.getWritableDatabase(); // Forces the helper to initialize. 
    new Test1().execute(2055); 
    new Test2().execute(2055); 
} 

을 그리고 결과 :

class Test1 extends AsyncTask<Integer, Void, Long> { 
    @Override 
    protected Long doInBackground(Integer... params) { 
     return test(params[0]); 
    } 
    @Override 
    protected void onPostExecute(Long result) { 
     System.out.println(getClass().getSimpleName() + " finished in " + result + "ms"); 
    } 
} 

class Test2 extends AsyncTask<Integer, Void, Long> { 
    protected Long doInBackground(Integer... params) { 
     SQLiteDatabase db = mHelper.getWritableDatabase(); 
     db.beginTransaction(); 
     long started = System.currentTimeMillis(); 
     try { 
      test(params[0]); 
      db.setTransactionSuccessful(); 
     } finally { 
      db.endTransaction(); 
     } 
     return System.currentTimeMillis() - started; 
    } 
    @Override 
    protected void onPostExecute(Long result) { 
     System.out.println(getClass().getSimpleName() + " finished in " + result + "ms"); 
    } 
} 

모두는 다음과 같이 시작된다? 거래가 없다면 INSERT41072ms입니다. 거래의 경우 그들은 940ms입니다. 간단히 말해서 FFS는 InsertHelper과 트랜잭션을 사용하기 시작합니다.

+0

InsertHelper는 더 이상 안드로이드에 빠른 db 삽입을 수행하는 다른 방법이 없어졌습니다. – YLS

3

오프라인 도구를 사용하여 데이터베이스를 채운 다음 패키지를 설치할 때 가져올 수 있습니다. 데이터베이스를 외부 sd 카드 또는 응용 프로그램의 자산 폴더에 저장할 수 있습니다.

이 내가 그것을 할 방법은 다음과 같습니다

  1. 복사 같은 안드로이드 Debuger 브리지 (ADB)를 사용하여 로컬 폴더에 응용 프로그램 데이터베이스 : adb pull /data/data/<your application provider>/databases/yourdatbase.db C:/users/databases/yourdatbase.db합니다.

  2. 좋아하는 GUI/CLI 도구로 C:/users/databases/yourdatbase.db SQLite 데이터베이스에 연결하고 1 000 000 개의 레코드 채우기를 완료하십시오.

  3. 입력 한 데이터베이스를 Android 개발 환경 asset 폴더로 복사하십시오.

  4. 이제 응용 프로그램을 장치에서 제거하여 처음 설치할 때 데이터베이스가 생성되지 않도록하십시오.

  5. SQLiteHepler 클래스를 수정하여 데이터베이스가 있는지 여부와 존재하는 데이터베이스가 있는지 확인합니다. 데이터베이스가 존재하지 않으면 Helper는 귀하의 자산 폴더에있는 것을 1 000 000 개의 레코드와 함께 복사합니다. 이것은 내가 그것을했을 방법입니다

    public class MyDatabaseHelper extends SQLiteOpenHelper { 
    
        /* 
         Other SQLiteOpenHelper declarations here ... 
        */ 
    
        private static final String DATABASE_NAME = "application.db"; 
        private static final String DB_PATH   = "/data/data/" + context.getPackageName() + "/databases/"; 
    
    
        /* 
         Your SQLiteOpenHelper functions/procedures here ... 
        */ 
    
        public boolean isDataBaseExist() { 
    
         File dbFile  = new File(DB_PATH + DATABASE_NAME); 
         return dbFile.exists(); 
        } 
    
        public void copyDataBase(Context context) throws IOException { 
    
         this.getReadableDatabase(); 
    
         InputStream inFile  = context.getResources().getAssets().open(DATABASE_NAME); 
    
         // Path to the just created empty db 
         String outFileName  = DB_PATH + DATABASE_NAME; 
         OutputStream outFile = new FileOutputStream(outFileName); 
    
         // transfer bytes from the inputfile to the outputfile 
         byte[] buffer = new byte[1024]; 
    
         int length; 
    
         while ((length = inFile.read(buffer)) > 0) { 
    
          outFile.write(buffer, 0, length); 
    
         } 
    
         // Close the streams 
         outFile.flush(); 
         outFile.close(); 
         inFile.close(); 
        } 
    

이 데이터베이스 앱 당신과 함께 compliled되며 처음 실행에 모든 데이터가있을 것입니다. 더 간단한 방법이있을 수 있지만, 이것이 누군가를 돕기를 바랍니다.

관련 문제