2011-05-15 45 views
0

我需要在SQL表中存儲短標籤(A01,B34等),並確保它們的索引。爲字母表中的每個字母創建INT列是不可能的,因爲例如條目可以有多個「A」標籤。SQL - 如何標記數據?

首先我將它們存儲爲一個長字符串,用空格分隔(例如「A01 B34」)。但是這需要一個LIKE%查詢,它執行完整的掃描並忽略任何索引。所以我正在尋找替代品。

我現在使用SQLite FTS(文本搜索)來搜索這些標籤,但是這需要一個特殊的表來存儲標籤,並通過JOIN查詢獲取結果,以及其他所有我喜歡的東西避免。

我的要求很簡單:我需要存儲數百萬個短字符串,每個字符串都有自己的標籤,並對這些標籤進行簡單搜索。

我目前的做法(在標籤上執行FTS)最快嗎?或者,使用NoSQL數據庫來處理這種數據會更好嗎?

+0

標籤代表什麼?也許這會幫助我們想象這個問題。 FTS似乎有點過分。 – 2011-05-15 14:02:12

+0

他們代表類別。以IMDB爲例,其中每部電影有多個流派。 – Muis 2011-05-15 14:05:27

回答

1

我將分享我的經驗,我在之前的啓動Pageflakes社區網站上如何做到這一點。在Pageflakes中,用戶創建的內容被標記。從這裏你可以看到一個例子:

http://www.pageflakes.com/Community/Content/Flakes.aspx?moduleKey=4796

每個窗口小部件,pagecast有標籤的集合。當有人搜索時,我們給予標籤最高優先級,然後標題,然後描述項目。

假設你有一個表的內容是這樣的:

Content (id, title, description) 

首先,你需要創建一個表的所有獨特標籤。

Tag (id, name (unique), countOfItems) 

然後,您需要將標籤映射到內容行。

TagContentMap (tagid, contentid) 

您現在要問,對於每個新內容,我必須插入三個表格。不總是。只有當您有新標籤時纔可以插入標籤表格。大多數時候,人們選擇現有的標籤。經過幾個月的標記後,用戶應該已經用盡了獨特的標籤。從那時起,99%的時間用戶選擇一些現有的標籤。所以,這爲您刪除了一個插入。所以,你只有一個額外的插入。

此外,insert總是顯着低於select。很可能你會有99%的閱讀,1%的寫作。

除非您介紹這兩個表格,否則您永遠無法擁有一個用戶界面,用戶可以點擊某個標籤並查看標記有該特定標籤的所有內容。如果您不需要這種功能,那麼您當然可以在內容表格本身上添加一個「標籤」列,並以逗號分隔的格式存儲標籤。

現在最重要的一點 - 如何產生最好的搜索結果。在內容表中,我們有一個名爲「SearchData」的varchar字段。該字段首先填充標籤名稱,然後是標題,然後是說明。因此,

SearchData = tag names comma delimited + newline + title + newline + description. 

然後,您使用SQL Server的全文索引來索引僅SearchData列,而不是內容表中的任何其他字段。

這是否適合您?

+0

檢查,這是否會爲你工作? – oazabir 2011-05-18 10:44:54

+0

是的,非常有幫助! – Muis 2011-05-21 09:29:04

+0

可以將我的答覆標記爲答案嗎? – oazabir 2011-05-30 06:11:43

1

你不會給我們很多細節,但你的設計似乎都是錯誤的。這不是第三範式。

0

@Joshua,請在術語「正常化」中使用goo。目前您的數據是非規範化的。非規範化是可能的事情。但在正常化之後,以及某種性能受到破壞。目前你的設計似乎是錯誤的。

正如你應該有1臺3臺insetad一個例子:

some_records (id, column1, ..., columnN) 
tags (id, title) 
some_records_tags (some_record_id, tag_id) 

這是一個在DBMS經典的設計模式。這裏不需要NoSQL。

+0

我知道規範化,你說得對,這個1表設計不是靠書本。但是我必須存儲/搜索非常大量的數據,甚至每次優化(PRAGMA,批量事務)仍然太慢。如果我使用上述表格,我必須每次更新至少添加3行(而不是1)。如果沒有性能損失,我會很樂意改變設計。 – Muis 2011-05-15 16:20:24

+0

@Joshua,如果你的應用數據變化與讀取的數據是1到9999之間的東西,那麼你應該做「按書」。請記住,當你插入/更新內容時,你的應用程序不適合你,但是對於用戶來說,大部分時間都是從中讀取數據。無論如何,爲了獲得更高級的性能,你可以使用一些緩存系統,但是在數據庫層,我建議你採用經典的方式。插入一個新標籤並不是一項艱鉅的任務,也可以在一個SQL中插入some_records + some_records_tags。這是所有可能的。 – gaRex 2011-05-15 16:27:21

0

正如其他用戶指出的那樣,數據的標準化程度並不高。我會假設這是有意的,並且有一些非常大的(gb或tb大小的要求或者沒有提到的巨大吞吐量要求)。但是在你開始任何路徑之前,你應該準確理解你的需求是什麼:你寫和讀的頻率,寫和讀的延遲要求是多少,你必須在你的計算中包括索引維護。

如果您有明顯的性能需求,您可以嘗試在當前擁有的基礎上構建一個近線索引系統。過去我使用這種技術來處理大吞吐量需求系統。這個想法基本上是爲了寫入,你儘可能小而快地創建它們,然後創建一個批處理返回並將數據添加到輔助搜索表中,以便將其轉換爲能夠搜索的表單。好處是您的寫入操作可以快速完成,並且如果您選擇了聚簇索引,那麼可以非常有效地完成批處理的讀取操作。另外,您可以根據需要將數據分段到不同的服務器,以支持更高的搜索吞吐量。主要缺點是更新不會即時反映在搜索結果中。

如果你寫到一個表所示: 表數據(ID二進制(6),...,時間戳日期時間,標記爲varchar(256))

,並有一個輔助表: 表搜索(標籤char(3),dataId binary(6))

您可以創建一個批處理過程,以獲取最後一個BATCH_SIZE(1000個可能)記錄並將標記列拆分爲一個空格並將標記插入/從搜索表格。您將變量/行保留在您收集的最後一個時間戳值的某處,並在下一個批處理間隔從那裏開始。最後,如果刪除很重要,則每個批處理間隔都需要在數據表中找到不再存在的一組記錄。或者,如果您的數據表太大,或者您可以同時對數據執行刪除操作,並搜索它們不經常發生的情況,您可以選擇邏輯刪除表。

需要注意的事情與批處理正在使批量大小過大,並更新搜索表時採取表鎖。此外,你必須注意重複的時間戳。當然,在寫入/更新數據表時,必須始終更新時間戳。