2015-11-13 53 views
2

全部: 我有一個表格來記錄一些維度每10分鐘一些請求的數量。這是我的表格:mysql插入vs更新性能

CREATE TABLE IF NOT EXISTS `mydb`.`realtime_bid_traffic` (
    `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '', 
    `owner_id` BIGINT(20) NOT NULL COMMENT '', 
    `log_time` DATETIME NOT NULL COMMENT '', 
    `bid_num` BIGINT(10) NOT NULL DEFAULT 0 COMMENT '', 
    `v_bid_num` BIGINT(10) NOT NULL DEFAULT 0 COMMENT '', 
    PRIMARY KEY (`id`) COMMENT '', 
    UNIQUE INDEX `dim_key` USING BTREE (`owner_id` ASC, `log_time` ASC) COMMENT '') 
ENGINE = InnoDB; 

正如你所看到的,id是一個沒有任何特殊含義的自動增量大整數。 owner_idlog_time是尺寸鍵,而bid_numv_bid_num是要更新的內容。受商業邏輯限制,我無法在插入數據庫之前收集所有數據,即我可能必須插入數據庫,其中owner_id=10log_time='2015-11-11 11:00:00'兩次。由於表可能相當大(數百萬行)並需要不斷更新,因此我有兩種選擇:

  1. 插入或更新重複鍵。通過這種方式,每個維 將只有一行,但它涉及更新,併爲了 提高性能我已經建立了owner_id和 log_time的唯一鍵。
  2. 只需插入。在這種情況下,我將刪除 owner_id和log_time的唯一密鑰,並將其插入到數據庫中。由於id是 主鍵,它永遠不會重複,但它可能會顯着增加錶行 。

我不知道從性能角度看哪個更好。

回答

1

這是有點長的評論。

如果你只有關心插入到表中,那麼第二個選項通常更快。在大多數情況下,插入一個新行比check-for-duplicates-and-insert/update方法更快。即使桌子變得非常大,這仍然是事實。只要索引符合記憶,這將保持正確。

但是,數據通常具有其他用途,而不僅僅是放入表格中。對於許多查詢目的,沒有重複可能會顯着幫助查詢。如果通過user_id/log_time(如索引建議)查詢,那麼在查詢方處理重複項應該是微不足道的 - 兩行對一行的影響最小,order by id desc limit 1在兩行上佔用非常少的資源。 (嗯,我想有一個邊緣情況下插入到一個表中有數十億行索引會比插入到一個有10行的表中檢查重複時慢,因爲索引更新會比支票換重複查詢。不過,你的用例是充分遠離這種情況下,因爲你只談論每行約2個重複。)

+0

「在幾乎所有情況下,插入新行比檢查重複和插入/更新的方法快。」 - 如果check-for-duplicates導致對非idexed字段進行更新,這可能不會像性能方面那麼糟糕,因爲索引不需要更新,就像插入時那樣。 – JimmyB

+0

@HannoBinder。 。 。這是一個好點;但是,僅插入方法不需要該索引。由於其他原因,這可能是可取的,但插入不需要。 –

0

A計劃

PRIMARY KEY(id), 
UNIQUE(owner_id, log_time) 

每一次插入絕檢查雙方的鑰匙;這會減慢插入。

B計劃

PRIMARY KEY(id), 
INDEX(owner_id, log_time) 

這就要求你SELECT代碼做一些類型的GROUP BY和聚集。

C計劃

PRIMARY KEY(owner_id, log_time) 

並沒有id。爲什麼你有id,無論如何?雖然計劃A和計劃B總是在表格的「結尾」插入數據(由於AUTO_INCREMENT),計劃C將有多個「熱點」,每個owner_id一個。還行吧。

計劃d

INDEX(id), 
PRIMARY KEY(owner_id, log_time) 

如果C計劃是不可接受的,計劃d可以讓你保持id。不,AUTO_INCREMENT不一定是PRIMARY KEY。 IODKU是必要的。

哪個?

所有,但B計劃需要IODKU(上重複鍵更新插件)。但我不認爲這是一個嚴重的缺點。

計劃C和d可能提高SELECTs性能,特別是如果你通過一個owner_id選擇。

我更喜歡計劃按以下順序:C,d,B,A。你選擇的基礎上,你可以/不能忍受的約束。