2013-10-18 45 views
0

這裏是下面的代碼來創建兩個表和SQLite中的視圖:爲什麼SQLite拒絕使用可用的索引?

CREATE TABLE foo(id TEXT); 
CREATE INDEX `foo.index` ON foo(id); 
CREATE TABLE bar(id TEXT); 
CREATE INDEX `bar.index` ON bar(id); 
CREATE VIEW baz AS SELECT id FROM foo UNION SELECT id FROM bar; 

INSERT INTO foo VALUES('123'); 
INSERT INTO foo VALUES('1123'); 
INSERT INTO foo VALUES('2123'); 
INSERT INTO foo VALUES('3123'); 

INSERT INTO bar VALUES('44123'); 
INSERT INTO bar VALUES('441123'); 
INSERT INTO bar VALUES('442123'); 
INSERT INTO bar VALUES('443123'); 

EXPLAIN QUERY PLAN SELECT * FROM baz WHERE id='123';結果是:

SCAN TABLE foo (~1000000 rows) 
SCAN TABLE bar (~1000000 rows) 
COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION) 
SCAN SUBQUERY 1 (~200000 rows) 

SQL小提琴:http://sqlfiddle.com/#!7/b5e79/1(使用的WebSQL)

作爲你可以看到,當有一個完全可用的索引時,它正在進行表掃描。爲什麼?我如何解決這個問題以使用索引?

+0

[此SQL小提琴](http://sqlfiddle.com/#!5/b5e79/1)顯示正在使用的索引?這是你用來測試的確切腳本嗎? – GarethD

+0

您的SQLFiddle向我展示了與我輸出的內容相同的內容......沒有使用索引。 (是的,這是我測試它的確切代碼) – chacham15

+0

不是在我的瀏覽器中,它顯示'SCAN TABLE foo使用包含索引foo.index(〜1000000行)'作爲第一步顯示它使用'foo.Index '。 – GarethD

回答

2

兩件事情可能在這裏

  • 發生的表是太小了。只需幾行,所有數據都可以放入無論如何讀取的塊中。所以優化器在使用索引時看不到優勢。這不太可能,因爲所有需要的列都在索引中,因此需要更少的字節才能滿足要求。

  • 兩個selects之間的union等於union distinct意味着,在第一和第二選擇是重複的所有行被消除。爲了找到它們,數據庫必須對兩個結果集進行排序和合並。如果您是union all,則此排序步驟不是必需的,因爲所有填滿where子句的行都放在結果集中。

嘗試union all。這應該使用索引。