2017-01-02 1 views
0

2 개의 테이블이 있으며 필요한 쿼리가 매우 느리게 실행됩니다. 예를 들어, 관련 필드가있는 두 개의 샘플 표를 보여줍니다.많은 수의 행에 Android SQLITE 쿼리가 느림

Table MAIN 
     MAIN.USERID text 
     MAIN.LOGGED_USERID text 
     MAIN.other text fields not relevant to query 
Index on USERID, LOGGED_USERID 

Table LOGS 
     LOGS.CREATED int 
     LOGS.USERID text 
     LOGS.LOGGED_USERID text 
     LOGS.TYPE int 

Index on USERID,LOGGED_USERID,TYPE 

LOGS 테이블에서 USER/LOGGED_USER의 최신 날짜를 가져와야합니다. 내가 실행해야 쿼리는 유사합니다

Select m.some fields, 
    (Select l.CREATED 
    from LOGS l 
    where l.USERID=u.USERID and l.LOGGED_USERID=m.LOGGED_USERID and TYPE=1 
    order by l.CREATED desc limit 1) as LAST_DATE 
from MAIN m 
WHERE some fields not relevant and an EXIST command from other table 
ORDER BY some fields not relevant 

쿼리 행 제한된 수의 각 테이블에 150,000 행을 가진 경우, 쿼리가 실제로 종료 것 같다, 또는 적어도 나는 천국 결코를 위해 잘 실행하는 동안

그걸 오래 기다렸어. 성능 저하는 LAST_DATE 쿼리에서 비롯됩니다. 즉각적인 결과 일 것입니다. 아마도 내가 가지고있는 인덱스가 사용되지 않았습니까?

+0

'... 일부 필드는 관련이 없습니다 ...'이 '관련 없음'필드도 색인화되어야합니다. 색인 생성을위한 주요 규칙 :'모든 JOIN과 WHERE 열 색인화 '. –

+0

하위 쿼리없이 확인해야 할 수도 있습니다. 가능하다면 조인으로 바꿉니다 ('u.USERID'가 표시되지만 m.USERID 일 수 있습니다). 이는 모든 행에 대해 실행될 것이기 때문입니다. – AxelH

+0

LAST_DATE 쿼리가 없으면 모든 것이 빠르게 작동합니다. LAST_DATE 쿼리를 사용하면 기본 쿼리 나 ORDER에서 WHERE를 사용하지 않아도 쿼리가 오랜 시간 실행됩니다. 그렇기 때문에 제가 포함하지 않은 것은 바로 – Alin

답변

0

솔루션은 각 행에 대해 하위 쿼리를 실행합니다.

조인을 사용하면이 작업은 한 번 실행 된 다음 두 테이블을 조인합니다.

Select m.some fields, 
    l.CREATED as LAST_DATE 
    from MAIN m 
    inner join (Select max(CREATED), LOGGED_USERID, USERID 
     from LOGS l 
     where TYPE=1 
     group by LOGGED_USERID, USERID 
    ) l on l.USERID = M.USERID ANd l.LOGGED_USERID = M.LOGGED_USERID. 

참고 : 여기에

는 단순히 별칭을 사용 USER_ID 당 마지막으로 생성 된 로그를 얻고

Select max(CREATED), LOGGED_USERID, USERID 
     from LOGS l 
     where TYPE=1 
     group by LOGGED_USERID, USERID 

을 logger_userid 그리고 조인을 사용하는 쿼리입니다 나는 SQLite 표기법에 유의하십시오. Sybase에서 너무 오랫동안 작업했습니다.

This 여전히 장소와 주문 조건이 필요합니다. 이것은 단지 select .. from ... 부분을 수정하는 것입니다.

+0

sqlite에서 내부 조인으로 쿼리를 가질 수 있다는 것을 알지 못했습니다. 이 솔루션을 사용하면 2 ~ 3 초 후에 결과가 반환됩니다. 와우. 고마워. 반환 된 정보의 정확성을 확인해야하지만 유망 해 보입니다! 고맙습니다. – Alin

+0

@alin ** inner ** join에 문제가있을 수 있습니다. 필요에 따라 왼쪽 또는 오른쪽 조인이 필요할 수 있습니다. – AxelH

+0

각 메인에 대한 레코드가 LOGS에 있어야합니다. 하지만 로그에 항목이 없다면 어떨까요? 아마 MAIN의 행이 항상 반환되고 CREATED가 null이 될 수 있도록 RIGHT 조인을 사용해야합니까? – Alin

-1

코드를 표시하지 않으므로 UI ​​스레드에서 너무 많은 작업을 수행하고 있다고 생각합니다. 따라서이 가정을 취하면 로더를 사용해야합니다. 귀하의 경우 커서 로더. 로더는 기본적으로 별도의 스레드에서 실행되며 느린 UI를 방지합니다. 설명 된 로더 링크보기 : Loaders in Android

+0

그럴 것 같지 않습니다. 호출은 AsyncTask에서 수행됩니다. 그렇더라도 내 PC에서 쿼리를 실행 한 후 데이터베이스를 가져 와서 sqlite 용 GUI를 사용한 후에도 여전히 실행되지 않습니다. – Alin

+0

Sqlite에서 데이터를 쿼리하는 경우 Android에서 가장 좋은 패턴은 Asycktask 대신 CursorLoader를 사용하는 것입니다. – Abad