2010-11-10 32 views
7

一個(簡化的)Internet書籤數據庫。我覺得這一定是有意義的邏輯組織表,就像這樣:在SQLite中連接三個表的最佳方式

Bookmarks (id, title, url; basically external data) 
+------+------------+-----+ 
| suid | Title | ... | 
+------+------------+-----+ 

User (user-specific data: favorites, ratings, etc) 
+------+------------+-----+ 
| suid | IsFavorite | ... | 
+  + (0 or 1) +  + 
+------+------------+-----+ 

History (last used, use count etc) 
+------+------------+-----+ 
| suid | LastUsed | ... | 
+  +(TDateTime) +  + 
+------+------------+-----+ 

(「SUID」是唯一的ID,整數主鍵)

從標記爲喜歡書籤,我需要選擇N 最近使用過(爲了便利,在運行時在菜單中填充菜單)。

SELECT Bookmarks.suid, Title from Bookmarks 
    INNER JOIN User USING (suid) 
    INNER JOIN History USING (suid) 
    WHERE IsFavorite = 1 
    ORDER BY LastUsed DESC 
    LIMIT 15; 

該聲明起作用,並且似乎具有足夠的可讀性,但它是否最優?書籤表的目的是平均保存20-50k條記錄(即,不是您的標準瀏覽器書籤管理器:-)應用程序將在啓動時執行3或4條類似語句來填充控件。示例中使用的所有字段都被編入索引。

我在教自己的SQL,並提出了上面的代碼,但也許我忽略了一種語法或可以改善它的成語嗎?

+0

如果收藏指標存儲在用戶表中,那麼推斷出與用戶關聯的所有書籤都是收藏夾 - 它需要位於書籤級別,或者我誤解了目的。 – 2010-11-10 17:23:45

+0

我有一個傾向於在我的問題中過度解釋,所以我編造了一個簡單的例子來避免這個問題。主書籤表將定期更新。在更新期間,我不想觸摸用戶輸入的任何數據,例如評分,標記爲收藏夾等。將兩者分開似乎更爲清晰。同樣,一些用戶可能不想保留歷史記錄,在這種情況下,應用程序可以清除或刪除整個歷史記錄表。 (或者,'用戶'這個名字可能是誤導性的,它不是用戶帳戶數據的表格,而是用戶輸入的數據點,它是一個單用戶桌面應用程序。) – 2010-11-10 22:29:06

回答

4

從原始SQL猜測數據庫引擎如何滿足查詢是不可能的(或者至少非常非常困難)。出於這個原因,您需要使用EXPLAIN來了解SQLite如何實際獲取數據。並且請注意,它產生的執行計劃將會有所不同,具體取決於每個表中的數據量以及數據「看起來」的類似程度(根據索引列中的不同值的數量)。因此,請確保使用真實的數據填充測試數據庫。

一旦您嘗試EXPLAIN,我認爲有可能您會發現SQLite在進行前15個匹配之前一起將這些表連接在一起,如果屬實,這將是非最優的。如果原來是這樣,你可以嘗試這樣的:

SELECT Bookmarks.suid, Title from Bookmarks 
    INNER JOIN User USING (suid) 
    WHERE IsFavorite = 1 
    AND suid IN (SELECT suid FROM History ORDER BY LastUsed DESC LIMIT 15); 

但是,再次強調,不要嘗試,直到你看到從該EXPLAIN SQLite是在非最佳的方式獲取數據。

0

它看起來對我好。您可能已經知道這一點,但如果您想進一步調整,可以使用explain關鍵字(http://www.sqlite.org/lang_explain.html)調查您的查詢。

乾杯!

0

您可以像前面所說的那樣使用關鍵字EXPLAIN,但還有其他方法可以改進它。 有一個網站的一些信息...檢查出點擊'here瞭解更多關於它... 祝你好運!

相關問題