2011-09-25 104 views
1

在我的表中我有一些列上沒有索引,在這些列中搜索值可能需要很長時間,因爲SQLite執行全表掃描。SQLite:優化表掃描

在我的具體情況下,我正在查找的行(值是唯一的)幾乎總是在最近插入的行中。

我懷疑SQLite從最舊的(第一個)行開始執行掃描時,是否有任何方法指示SQLite以相反順序執行表掃描?

更新:我發現這個在更新日誌:

現在,優化程序將掃描的逆表,如果這樣做將滿足一個ORDER BY ... DESC子句。

所以也許這意味着我可以添加一個ORDER BY子句來加速它。

+0

幾乎總是,你的意思是? 「我正在尋找的行幾乎是最近插入的行。」 – Tim

+0

謝謝,我糾正了它。 – Muis

+0

按DESC排序不會導致SQLite在找到匹配項時停止掃描行。如果您的值在該列中是唯一的,它將繼續掃描,找到第一個匹配項後找不到其他匹配項。請參閱下面的我的LIMIT建議。 – Tim

回答

2

的解決方案是:

ORDER BY rowid DESC LIMIT 1 

它使查找快如閃電!

1

由於需要全表掃描,因此掃描順序(從最老到最年輕或從最年輕到最老)是無關緊要的。每一行都必須被訪問。儘管你提「行我要找」的條件

    .... where col = 'a' 

可能會返回一個排,或者它可能返回10行,或500行。除非使用LIMIT指令,否則在遇到第一個匹配行時,SQLite不能簡單地停止並稱它爲一天的工作。

編輯:你可以做什麼,但是,是使用時間戳列,索引,然後使用內嵌視圖,以獲得相對較新的行:

   select * from 
       (
       select * from T 
       where datecreated > {somerecentdate} 
      ) as myView 
       where myView.someColumn = 'a' 

或者乾脆

  select * from T where datecreated > {some date} and somecolumn = 'a' 

該方法可能是一個迭代過程 - 如果沒有行返回,您可能需要用更寬的時間窗查詢。 但是,如果你要索引datecreated,你可能也索引[someColumn]。

+0

它總是會返回一行,因爲列中的值是唯一的。我不使用UNIQUE或INDEX,因爲它會減慢插入太多。我最初的想法是使用與上面描述的相同的迭代過程,甚至不需要額外的'datecreated'列,您可以在行的id上執行它,因爲它們總是增量。但我希望有一個內置的解決方案,而不用自己實施一個聰明的算法。 – Muis

+0

它總是會返回一行,這不是SQLite可以知道的事實,如果該列未被索引。完整的表掃描將始終是必要的。如果存在LIMIT()優化,則可以使用LIMIT 1. – Tim

+0

該查詢已包含LIMIT 1,但無論如何要感謝。 – Muis