SQLite 데이터베이스를 쿼리하기 위해 기존 코드를 개선해 달라는 요청을 받았습니다. 원래 코드는 데이터베이스에 대해 여러 차례 별도의 호출을 수행하고 Python에서 결과를 필터링했습니다. 대신 데이터베이스 생성을 다시 작성하고 필터링 논리를 SQL 쿼리에 넣기로 결정했습니다.
다양한 크기의 데이터베이스에서 벤치마크를 실행한 후. 원래 구현과 비교하여 n=3
새 구현의 쿼리에 대한 평균 쿼리 시간이 훨씬 더 빠르다는 것을 알았습니다(3초 대 46초).분). 캐시 문제인 것 같은데 출처가 무엇인지 잘 모르겠습니다. 각 쿼리 사이에 데이터베이스 연결을 닫고 나머지 Python 변수를 삭제하고 실행했지만 gc
이 세상 밖에서는 상황이 지속되었습니다. 그런 다음 아마도 시스템이 무언가를 캐싱하고 있다는 것을 알았습니다. 실제로 각 반복 후에 시스템 캐시를 지울 때 echo 3 > /proc/sys/vm/drop_caches
성능은 내 기대에 더 부합합니다(80,000배 속도 향상에 비해 2~5배 속도 향상).
지금 제가 가지고 있는 가장 철학적인 질문은 캐시 성능(있는 그대로) 또는 비캐시 성능(쿼리하기 전에 명시적으로 캐시 제거)이라는 개선 사항을 보고해야 한다는 것입니다. (아마 둘 다 보고하겠지만, 그래도 무엇이 캐시되는지 궁금합니다.) 이는 실제로 무엇이 캐시되는지에 대한 질문으로 귀결된다고 생각합니다. 즉, 캐시가 실제 시나리오를 나타내는가, 아니면 전혀 나타내지 않는가?
데이터베이스나 해당 인덱스가 캐시되는 경우 빠른 기본 성능은 보이지 않는 새로운 쿼리에 작동하므로 실제 세계를 잘 표현한다고 생각합니다. 그러나 특정 쿼리를 캐시하는 경우, 아직 확인되지 않은 쿼리에는 캐시 성능이 반영되지 않습니다.
참고: 이는 중요하지 않은 세부 사항일 수 있지만 이 캐시의 영향은 fts5 가상 테이블을 사용할 때 특히 두드러집니다!
요약: 시스템이 SQLite에 쿼리를 캐시할 때 정확히 무엇이 캐시되며, 이것이 보이지 않는 새로운 쿼리에 긍정적인 영향을 미칠까요?
중요한 경우: sqlite3이 포함된 Ubuntu 20.04.
답변1
아니요, 캐시되지 않습니다.문의. 캐시한다페이지.
데이터베이스는 테이블(및 인덱스)을 페이지에 저장합니다. 각 페이지에는 하나 이상의 테이블 행이 포함되어 있습니다. 페이지가 캐시에 있으면 해당 페이지의 행이 필요한 모든 쿼리에서 사용할 수 있습니다.
인덱스에도 마찬가지입니다. 새 쿼리에 제한이 있는 경우 somefield between 20 and 40
(데이터베이스 엔진이 먼저 캐시를 확인함) 캐시에 해당 값 범위를 설명하는 해당 인덱스의 페이지가 포함되어 있습니까?
페이지 크기는 새 데이터베이스를 생성할 때 정의됩니다. pragma 문서 보기페이지 크기제한 사항 및 사용 방법에 대해 설명합니다.
이 접근 방식을 사용하면 관련되지 않은 쿼리뿐만 아니라 서로 다른 연결 간에도 페이지를 공유할 수 있습니다. 작동 방식에 대한 문서는 다음과 같습니다.https://www.sqlite.org/sharedcache.html