簡體   English   中英

使用一個表的多個索引優化數據庫性能

[英]Optimizing DB performance with multiple indices for one table

我有一些關於我存儲(在這個玩具示例中)的一些項目的時間序列數據在一對簡單的表格中。 目前,這是在MySQL中完成的,但如果有足夠強大的理由試圖在不同的DBMS中解決我的問題,我會全力以赴!

ITEM表有一個主鍵和一個類似文本的列,可以被認為是一個描述,讓我們稱之為descr DATAPOINT表有一個主鍵和3個其他列:一個進入ITEM表的外鍵(稱之為fk_item ),一個日期時間我將調用timestamp和浮點值,我們稱之為value 此外,在(fk_item, timestamp)列對上存在聯合唯一性約束(fk_item, timestamp)在給定時間,我們只需要DB中的一個值用於給定項)。

為了在其上放置實數, DATAPOINT表有大約10億行,這是每10k個不同項目大約有10萬行的結果。

我的問題是在這種情況下優化讀寫性能的能力,以及強制執行唯一性約束的最佳方法。

從這個數據庫中讀取的典型數據將涉及少量項目(半打?),我們希望獲得給定日期時間范圍內的所有值(每個項目包含大約1k點)。 為此,擁有一個索引(fk_item, timestamp)並在該索引上強制執行聯合唯一性標准將非常方便。 讀取此類型背后的動機是:“我想在這3年范圍內制作2或3個項目的折線圖”。

但是,此數據庫的典型寫入看起來會非常不同。 它將為數千個項目中的每一個插入一個數據點,所有項目都具有相同(或少量)的時間戳。 這種寫作的動機可以直觀地被認為是:“我想為每一個項目添加昨天的數據點”。 因此,對於那種類型的寫入,擁有一個索引(timestamp, fk_item)並對該索引強制執行唯一性限制會更實際。

重要的是,對於我的數據和硬件的規模,這些索引都不能完全適合RAM。

通常,絕大多數寫入每天都會在短時間內發生:即在每天結束時,當天的所有數據都會在15分鍾內寫入,然后在一天中進行讀取(但通常不會在那15分鍾的時間)。

因此,根據我的理解,如果我使用read-optimized (fk_item, timestamp)索引構建表(並在其中放置唯一性約束),那么我的典型讀取將是美好而快速的。 但是我擔心我的寫入會很慢,因為我們需要以非連續的方式更新索引。 但是,如果我使用寫優化(timestamp, fk_item)索引構建表(並在其中放置唯一性約束),那么我的典型寫入將(timestamp, fk_item)但我的典型讀取將受到影響。

有沒有辦法讓兩全其美? 例如,如果我構建兩個索引: (fk_item, timestamp) (timestamp, fk_item)並將唯一性放在兩者的后者上,那么效果會好嗎? 或者寫入仍將以“慢”速度進行,因為即使存在寫入優化索引(例如,檢查唯一性約束),也需要在任何插入上更新讀取優化索引,並且該更新將是不連續的?

提前致謝!

簡短回答: (fk_item, timestamp)僅限。

答案很長:

唯一性而言, (fk_item, timestamp)(timestamp, fk_item)是相同的。 雖然他們都聲明唯一性同樣出色,他們都吮吸唯一的。 有一天,特定項目將在同一秒內出現兩次。

你確實提過“昨天”。 因此,如果條目實際上是當天的小計,那么(fk_item, date)是合理的。

在構建索引時,最好將日期/時間項最后保留。 這樣, WHERE fk_item = 123 AND date BETWEEN ... AND ...可以使用該索引。 寫作不關心(多)事情的順序。

PRIMARY KEY怎么樣? 它是,但MySQL的定義, UNIQUEINDEX 所以,如果(fk_item, date)合理,那就把它作為PK吧。 這將使需要查看特定項的多行的查詢更有效。

“我希望在這3年的范圍內制作2或3個項目的折線圖”。 - 如果涉及數百萬行,那么您已經無效地設計了模式。 您需要構建和維護每個項目的每日值的摘要表。 然后它將是數百,而不是數百萬行 - 更可行。

回到INSERTs 使用10k個不同的項和PRIMARY KEY(fk_item, date) ,表中將有10K個點,其中插入發生。 這實際上是可以的,並且與其他一些訂購的速度大致相同。

每日INSERTs最好使用LOAD DATA INFILE或多行INSERTs

我是從MySQL的角度講的。 我說的一些(盡管可能不是全部)適用於其他產品。

除非您打算清除“舊”數據,否則PARTITIONing對於MySQL來說是一個無用的想法。 (我不能代表Posgres。)

如果隨機插入行,可能會遇到不切實際的性能問題。 這是因為你的真實情況將不那么“隨機”。 將只有10K點,你做INSERTs今天,而不是1十億。 明天,它將是“相同的”10K點。

“如何構造這樣的表” - 最小化數據類型(例如,不要使用8字節BIGINT作為是/否標志); 提供最佳PK(我建議(item, day) )。 但是你必須有暫定的SELECTs才能確定二級索引。 適當時標准化( item_id ),但不要過度標准化(日期)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM