2010-11-15 65 views
5

如果你有一個查詢,如:SQLite的連接優化

select a.Name, a.Description from a 
inner join b on a.id1 = b.id1 
inner join c on b.id2 = c.id2 
group by a.Name, a.Description 

什麼是索引最優化的列此查詢SQLite中,如果你認爲有超過10萬行的每個表?

,我想問的原因是,我沒有得到與由我希望從另一個RDBMS(SQL Server)的,當我採用同樣的優化與該組的查詢性能。

我會是正確的思維,在SQLite的查詢中的單個表引用的所有列必須列入最佳性能單一的綜合指數?

+2

我的內心靈變態是抽搐的事實,你有一個group by子句沒有任何聚合函數(S)。你想通過團隊達成什麼目標? – 2010-11-15 13:24:05

+1

@MyOtherMe:看到我下面的答案,我想他想要的是在b和c表中引用的所有描述和名稱。 – MPelletier 2010-11-15 13:27:45

+0

那正是我所追求的。 – gmn 2010-11-22 09:28:42

回答

4

的問題是,你希望的SQLite具有相同的性能作爲一個完整的RDBMS。它不會。 SQLLite在內存中沒有足夠的緩存空間,每次運行應用程序時都必須重新構建緩存,可能僅限於設置內核數量等,等等。使用嵌入式RDBMS的權衡超過一個完整的。

只要優化進行,請嘗試索引查找列並進行測試。然後嘗試創建一個覆蓋索引。一定要測試selects和更新數據庫的代碼路徑,你會以犧牲另一個爲代價加快速度。找到適合您需求的兩種最佳平衡的索引,並與之配合。

+0

感謝您的回答,我以前曾嘗試在a.Id1,a.name,a.description以及b.id1,b.id2和c.id2上的另一個索引上添加一個複合索引。但是,這些都沒有幫助該團隊的表現。這是什麼引發了這個問題,因爲在這種情況下,使用SQLite似乎不可能通過性能獲得足夠的分組。我想這只是擁有嵌入式數據庫的限制之一。 – gmn 2010-11-22 09:41:03

1

請注意:我什麼都不知道SQLite和它的執行計劃可能錯綜複雜。

您絕對需要索引a.id1,b.id1,b.id2c.id2。我認爲一個綜合指數(b.id1, b.id2)可以產生一個小的性能增加。 (a.id1, a.Name, a.Description)也是如此。

2

SQLite query optimization overview

當執行行的索引查找,通常的程序是做對指數的二進制搜索來查找索引項,然後提取從索引和使用ROWID是rowid在原始表上執行二進制搜索。因此,典型的索引查找包含兩個二進制搜索。但是,如果從表中提取的所有列在索引中已經可用,則SQLite將使用索引中包含的值,並且永遠不會查找原始表格行。這爲每行節省了一次二進制搜索,並且可以使許多查詢以兩倍的速度運行。

對於任何其他RDBMS,我會說把一個聚集索引上b.id1和c.id2。對於SQLite,你可能會更好,包括你想在這些索引中查找的b和c中的任何列。

+0

覆蓋索引幾乎存在於每個RDBMS中,並且對查找具有相同的效果。問題是大型索引會影響插入/更新性能,所以您必須在更新性能和選擇性能之間進行權衡。 – Donnie 2010-11-15 13:16:00

+0

感謝您的回覆,請原諒我的無知,但是您是否聲稱可以在SQLite中創建包含多個表中的列的索引,類似於SQLServer中的索引視圖? – gmn 2010-11-22 09:43:40

+1

嗯,我在說當你在B上創建索引時,不要只在B.id上創建索引,而是在索引中包含你需要從B中獲得的所有數據列。這將爲您節省一個二進制搜索這些數據列。在另一個DBMS中,通過在索引中包含來自多個表的列可能會更快,但SQLite並沒有那麼先進。 – thomaspaulb 2010-11-23 10:40:55

0

既然你不使用你的歸來列的其它表,這也許會更快:

SELECT DISTINCT a.Name, a.Description 
FROM a, b, c 
WHERE a.id1 = b.id1 
AND b.id2 = c.id2 

望着返回的列,因爲該標準似乎只有他們必須從被鏈接abc,你可以看看所有獨特的a.Namea.Description對。

SELECT DISTINCT a.Name, a.Description 
FROM a 
WHERE a.id1 IN (
SELECT b.id1 
FROM b 
WHERE b.id2 IN (
    SELECT c.id2 
    FROM c 
) 
) 

,或者取決於如果每對a.Namea.Description已經是獨一無二的,應該是在找出第一個唯一的ID的獲取,然後其他列一定的增益。

SELECT a.Name, a.Description 
FROM a 
WHERE a.id1 IN (
SELECT DISTINCT a.id1 
FROM a 
WHERE a.id1 IN (
    SELECT b.id1 
    FROM b 
    WHERE b.id2 IN (
    SELECT c.id2 
    FROM c 
    ) 
) 
) 
1

我認爲a.id1和b.id2指標會給你有關,你可以在這些連接方面得到儘可能多的好處。但SQLite提供了EXPLAIN,它可以幫助您確定當前執行計劃中的效率是否可以避免。