2012-05-09 19 views
2

這是我最近一直在做的事情,並想知道別人是否也這樣做,如果是的話,這種做法的名稱是什麼。在MySQL中保持捷徑是一種常見的做法嗎?

我在我的表格中保留了快捷方式列,這樣我就可以避免做太多的連接。例如,如果我有一個用戶表和地理表:

用戶:

id | username | zip  | copy_latitude | copy_longitude | other info 
------------------------------------------------------------------------ 
1 | Bob  | 11345  | 40.81518000 | -73.04550000 | etc... 

地理:

id | zip_code | latitude | longitude 
---------------------------------------- 
1 | 11345 | 40.81518000 | -73.04550000 

現在,如果我想獲得Bob的緯度和經度,我可以這麼做我會用同樣的選擇語句來獲取bob的其他信息:

SELECT a_bunch_of_other_columns, copy_latitude, copy_longitude 
FROM users WHERE id = 1; 

vs(如果我沒有保留shortcu ts):

SELECT a_bunch_of_other_columns, latitude, longitude 
FROM users 
INNER JOIN geo ON user.zip = geo.zip_code 
WHERE users.id = 1; 

通過保持快捷方式,我爲自己保存了一個連接。現在對於這個示例表和聲明來說這可能不是什麼大問題,但是我有一些有6或7個連接的巨大表和聲明,我覺得這很有幫助。

唯一的開銷是必須隨時更新這兩個地方隨時更改。我通過存儲過程處理這件事。

我的問題是:

  • 這是開發者,如果是一種常見的做法是什麼叫?
  • 是我的數據庫仍然正常化,如果我這樣做? (我假設如此以來,我一直在保持數據的有效副本在適當的位置 即使我沒有在那裏使用它,對於數據完整性的緣故)

回答

2

由於您的表格中有重複的數據,因此它不再標準化。

我想你可以稱之爲「非規範化」。

您真正需要的唯一時間就是速度/優化目的,這就是您在問題中所說的內容,即您已經完成了這項工作以消除複雜性。

老實說,我從來沒有到過任何我需要這樣做來優化查詢速度的數據庫。

我建議做基準,看到它是如何更快然後很好的索引加入

+0

基準是一個很好的主意。 –

2

是這個開發者之間的慣例,如果是的話,它是什麼?

我只能說我自己 - 我不這樣做

這是開發者,如果是一種常見的做法是什麼叫? 是我的數據庫仍然正常化,如果我這樣做? (我假設如此以來,我一直在保持數據的有效副本在適當的位置,即使我沒有在那裏使用它,對於數據完整性的緣故)

沒有

順便說一句 - 你有另一個開銷 - 存儲

3

我不知道這是否是常見的,但我覺得這是不好的做法。無論何時,您將數據存儲在多個位置都不是最佳選擇。有時使用非標準化的數據庫有時會提高性能,例如報告數據庫或數據倉庫。在這些情況下,數據庫通常是事務數據庫的只讀非規範化副本。

如果你真的需要減少你的連接,你不能只是創建視圖,以滿足這些情況?

所有這些重複的數據,你正在創造什麼,你認爲增加你的查詢性能當然會降低你的插入/更新性能。你如何跟蹤所有這些額外的數據,如果它不同步會發生什麼?當你離開並且其他人需要發現所有需要更新數據的額外位置時會發生什麼?

+0

使用連接構建的視圖不會減少連接。在OP的情況下 - 但在通常情況下不是*,如果表格構建正確,則重複數據不會失去同步。 (例如,請參閱我的回答。) –

+0

@Catcall我的懷疑是非規範化的動機是缺乏編寫查詢而不是真正表現的願望。 – Gratzy

0

讓我們來看看它一分鐘這樣。你已經知道一些這個。 (PostgreSQL語法; dbms對於規範化並不重要,僅用於實現。)

create table geo (
    zip_code char(5) not null, 
    -- CHECK constraints on lat and long omitted. 
    latitude float not null, 
    longitude float not null, 
    primary key (zip_code), 
    unique (latitude, longitude) 
); 

create table users (
    user_id integer not null, 
    username varchar(10) not null, 
    zip_code char(5) not null, 
    primary key (user_id), 
    foreign key (zip_code) references geo (zip_code) 
    on update cascade on delete restrict 
); 

很明顯,這兩個表都在5NF。

可以創建地理表中的ID號,你可以該ID號取代users.zip_code。但用代理id號代替真實數據與標準化沒有任何關係,也不會改變這些表的標準格式。

用id號代替真實數據確實改變性能;每次您需要用戶的郵政編碼時,您都需要進行連接才能獲得。這不是一個完全可預見的變化;實際性能隨着dbms,服務器,鍵的寬度等而變化。你不應該有麻煩測試你自己的表。您可能會發現,多達數百萬行,自然鍵比代理ID號執行得更好。 (這是我在這裏測試我們生產數據庫的設計時發現的。)

現在讓我們稍微改變一下結構。

create table geo (
    zip_code char(5) not null, 
    -- CHECK constraints on lat and long omitted. 
    latitude float not null, 
    longitude float not null, 
    primary key (zip_code), 
    unique (latitude, longitude), 
    -- Allows all three columns to be the target for a foreign key. 
    unique (zip_code, latitude, longitude) 
); 

create table users (
    user_id integer not null, 
    username varchar(10) not null, 
    zip_code char(5) not null, 
    latitude float not null, 
    longitude float not null, 
    primary key (user_id), 
    -- This FK has to reference all three columns. If split, it's possible 
    -- to reference the latitude and longitude for the wrong zip code. 
    foreign key (zip_code, latitude, longitude) 
    references geo (zip_code, latitude, longitude) 
    on update cascade on delete restrict 
); 

雖然這種變化確實引入傳遞性依賴,在USER_ID - > ZIP_CODE和ZIP_CODE - >緯度等,它不會引起任何插入,更新或刪除異常。這是因爲傳遞依賴關係中涉及的所有值都由對5NF表的單個外鍵引用覆蓋。

表格geo仍然在5NF;用戶現在在2NF。我們在這裏獲得或失去了什麼?

  • 我們丟失磁盤空間來存儲更廣泛的外鍵數據和 索引。
  • 達到一定數量的行(可能數百萬),我們在 SELECT查詢中獲得更快的性能。 (我沒有測試你的模式,因爲我沒有時間,但我使用自然鍵測量了20到30倍的速度增加。您的 差異可能不會顯着)
  • 我們在INSERT語句和大多數UPDATE 語句上獲得較慢的性能。 (較慢並不意味着。5毫秒比3毫秒, 但慢5毫秒不一定慢。大多數我自己的插入和更新的毫秒級運行 。)

所以構建一個測試模式,用幾百萬行填充它,並測量性能。測試與

  • 上ZIP_CODE外鍵的性能,並且加入以獲得緯度和 經度,然後
  • 調整和測試與{ZIP_CODE,緯度,經度}外鍵,然後
  • 使用代理ID號和連接進行重組和測試,以獲得zip_code,緯度和經度。

並在此處發佈結果。我很想看到他們。

相關問題