2011-08-12 3 views
0

SQLite 쿼리를 실행하는 데 시간이 너무 오래 걸리면 충돌하는 것처럼 보이는 Android app에 SQLite 쿼리가 있습니다. 그것은 NullPointerException와 충돌하고 라인 번호를 알려줍니다 ...Android SQLite 쿼리가 너무 오래 걸리는 경우 충돌이 발생합니까?

내가 그 줄 주위에 중단 점을 넣을 때 항상 변수로 채워지는 것을 볼 때, 응용 프로그램은 충돌하지 않고 예상 한대로 동작합니다.

따라서 가상 포인터가 없기 때문에 중단 점이 실제로 쿼리 시간을 줄이기 위해 속도를 늦추는 문제가있는 것처럼 보입니다. 중단 점이 없으면 항상 중단되지 않습니다.

다른 사람들은 비슷한 문제가있는 것 같아서 작업을 완료하는 데 오랜 시간이 걸리는 SQLite에 대해 읽은 적이 있지만이 테이블에는 몇 가지 항목 만 있어야합니다. 테스트에는 3 개의 항목, 4 개의 열만 있어야 함)

크래시가 발생하지 않도록하는 방법에 대한 제안? 아마도 쿼리를 만드는 메서드 안에 스레드 대기를 넣을까요? 이 경우 NullPointerException와 충돌 곳에 지금

public void fetchItemsToRemove() throws SQLException{ 
    Cursor mCursor = 
      mapDb.query(myMain_TABLE, new String[] {myOtherId, myCustomID, myDATE}, null, null, null, null, null); 

    if(mCursor.moveToFirst()) 
    { 
      do 
      { 
       /*taking "dates" that were stored as plain text strings, and converting them to 
       *Date objects in a particular format for comparison*/ 

       String DateCompareOld = mCursor.getString(mCursor.getColumnIndex(myDATE)); 
       String DateCompareCurrent = ""; 
       Date newDate = new Date(); 
       DateCompareCurrent = newDate.toString(); 

       try { 
        DateCompareOld = (String)DateCompareOld.subSequence(0, 10); 
        DateCompareCurrent = (String)DateCompareCurrent.subSequence(0, 10); 
        SimpleDateFormat dateType = new SimpleDateFormat("EEE MMM dd"); 
        Date convertDate = dateType.parse(DateCompareOld); 

        newDate = dateType.parse(DateCompareCurrent); 

        if(convertDate.compareTo(newDate) < 0) 
        { 
         //remove unlim id 
         mapDb.delete(myMain_TABLE, myDATE + "=" + mCursor.getString(mCursor.getColumnIndex(myDATE)), null); 

        } 

       } catch (ParseException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      }while(mCursor.moveToNext()); 
      mCursor.close(); 
    } 
    else 
    { 
     mCursor.close();  
    } 


} 

"342"는 문자열의 서브 순서를 얻을 수 DateCompareOld = (String)DateCompareOld.subSequence(0, 10);입니다. 여기에 도착하고 null 인 경우 이는 문자열이 결코 채워지지 않았다는 것을 의미합니다. String DateCompareOld = mCursor.getString(mCursor.getColumnIndex(myDATE));

너무 오래 걸린 것처럼 쿼리가 그냥 건너 뛴 것처럼 말입니다. 이것은 while 루프에 있음을 유의하십시오. mCursor가 절대로 경계를 벗어나지 않도록 테스트를 수행했습니다.

+0

충돌이 발생한 줄이 포함 된 코드를 게시하십시오. –

+0

SQLite 연결에 제한 시간을 설정 했습니까? 그렇다면 실행이 시작된 후/특정 시간 또는 이후에 임의의 시간이 지나면 일관되게 발생합니까? – jefflunt

+0

"코드와 관련이 있다고 생각하지 않았습니다 ..."- 코드와 logcat 출력은 항상 관련이 있습니다. 독자들을 신경 쓰지 않아도됩니다. ;) – Squonk

답변

2

DB 테이블에서 해당 테이블의 쿼리 결과를 반복하는 동안 삭제합니다. 조금 위험 해.

루프 내에서 삭제할 항목 목록을 작성한 다음 루프가 완료된 후 한 번에 삭제하십시오.

또한 전체 내용을 DB 트랜잭션으로 래핑하십시오. 루프에서 DB를 수정할 때 성능에 큰 차이가 발생할 수 있습니다.

편집 : 거래의 빠른 설명 :

트랜잭션은 당신이 DB 쿼리의 무리를 결합 할 수 있습니다/성공하거나 실패하거나 단일 원자 작업으로 수정. 그것은 주로 안전 메커니즘이므로 DB가 불완전한 상태로 잘못 움직이지 않으면 DB가 멈추지 않지만 한 번에 하나씩 한 번에 DB의 파일 저장소에 수정 사항이 적용된다는 것을 의미합니다. 훨씬 빠릅니다.

당신은 함수의 시작 부분에 거래를 시작

public void fetchItemsToRemove() throws SQLException{ 
    db.beginTransaction(); 
    Cursor mCursor = .... 

전체 기능이 오류없이 완료 될 경우 그것이 성공으로 설정합니다. 이것은 아마도 내측 try/catch을 제거하고 바깥 쪽 루프가 try/catch 인 것을 의미합니다.그런 다음 try{ }의 끝에서, 당신은 아무것도 잘못 됐을없는 것 가정 할 수있다, 그래서 당신은 전화 :

:

db.setTransactionSuccessful(); 

다음, finally 절에, 그것은 그렇지 않으면 성공의 여부를 항상 트랜잭션을 종료 확인

db.endTransaction(); 
+0

"DB 트랜잭션에서 전체를 랩핑"합니까? 당신은 이것에 대해 자세히 설명 할 수 있습니까, 나는 그 용어에 익숙하지 않습니다. – CQM

+0

@RD는 트랜잭션에 대한 참고 사항을 추가했습니다. –

+0

고마워, 내 새로운 문제는 내가 원하는 것을 효과적으로 얻을 수있는 WHERE 구문을 할 수 없다는 것이다. 오늘 날짜보다 "작다"면 평문 날짜를 꺼내려면 where 문이 필요합니다. SQLite는 날짜 함수가 없기 때문에 단일 명령문 비교가 덜 직관적이고 제안이됩니까? – CQM

관련 문제