2013-07-27 45 views
1

我正在處理一個包含3個表的大型(〜10GB)SQLite數據庫:文檔,其中包含一個ID和一個「標題」TEXT列,術語,其中包含一個id和一個「term」TEXT列,最後是DocumentTerms,其中包含一個id,一個「documentId」INT和一個「termId」INT,將來自Term表的行映射到Document表中的行。如果文檔多次包含相同的術語,則DocumentTerms表中有多個條目。加快SQLite查詢

不管怎麼說,我的問題是,我需要運行在每學期一個學期TFIDF重量,這涉及以下步驟(我包括我認爲我需要得到每一步查詢):

  1. 查找多少次,在所有文檔中的詞出現 - SELECT COUNT(*) FROM DocumentTerms WHERE termId=id
  2. 找到多少文件總共有 - SELECT COUNT(*) FROM Documents
  3. 找到一個長期多少文檔中出現 - SELECT COUNT(*) FROM DocumentTerms WHERE termId=id GROUP BY documentId

顯然我只需要運行#2一次。

有了這麼大的數據庫,每個查詢都需要很長時間。只要找出有多少文件(SELECT COUNT(*) FROM Documents)需要約45秒。

爲了加快速度,我嘗試了一些編譯指示。我只需要運行一次這個,所以我真的不介意,如果我在操作過程中斷電什麼的DB將被破壞:

PRAGMA synchronous = OFF 
PRAGMA page_size = 4096 
PRAGMA cache_size = 16384 
PRAGMA temp_store = MEMORY 
PRAGMA journal_mode = OFF 
PRAGMA locking_mode = EXCLUSIVE 

我如何可以加快這些訪問時間?

+0

我想你應該在你的問題中顯示確切的數據庫結構。例如,您可以使用Firefox的SQLite Manager插件及其「數據庫」|「導出數據庫結構」命令執行此操作。 – 2013-07-28 07:09:12

+1

你說這需要大約45秒,但你至少應該知道在7Mhz Pentium下哪個處理器和硬件哪個速度快! –

回答

1

對於只讀訪問,這些PRAGMA中的大多數不起作用。 只有cache_size很重要; page_size可能會有所幫助,但必須在創建數據庫之前進行設置。

當一個簡單的SELECT COUNT(*)需要那麼長時間時,顯然你沒有任何有用的索引。 這是很難說沒有數據庫結構,但下面的指標有可能幫助:

CREATE INDEX Documents_Id ON Documents(Id) 

(而不是Id,您可以使用Documents表的任何領域,但它通常一個是好主意,有主鍵索引)。

CREATE INDEX DocumentTerms_termId_documentId ON DocumentTerms(termId, documentId) 

你可以用EXPLAIN QUERY PLAN檢查查詢如何executed

+2

當你使用INTEGER PRIMARY KEY創建一個列時,SQLite使用這個列作爲表結構的索引(索引)。這是此列中的隱藏索引(因爲它不顯示在SQLite_Master表中)。在列上添加另一個索引是不需要的,永遠不會被使用。另外它會減慢INSERT,DELETE和UPDATE操作。 來源:https://www.sqlite.org/cvstrac/wiki?P = PerformanceTuning – Veda