為這些項目需求選擇 MyISAM 而不是 InnoDB;和長期選擇
很抱歉這篇文章很長,但我必須提供盡可能多的資訊才能使這個非常模糊的問題更加具體。
我的項目的目的是讓使用者搜尋各種產品的(巨大的)數據庫。
- 每個產品都存在於一個類別下。
- 每個產品將有 10 到 100 個“規格”或“功能”供使用者搜尋。
最常見的案例是:
- 使用者點擊一個類別;然後根據需要點擊各種子類別。
- 使用者從 1 或 2 個條件開始並蒐索產品。
- 然後,使用者不斷在搜尋中添加更多條件以縮小產品範圍。
我有三個主表“產品”、“功能列舉”和“功能”。讓數據輸入使用者為產品動態創建新的“功能”非常重要——因此我使用的是 EAV(反)模式。
以下是表的結構:
'products' ID(PK), TITLE, CATEGORY (Indexed by CATEGORY) 'features_enum' ID(PK), TITLE 'features' P_ID, F_ID, VAL (Indexed by P_ID and then F_ID)
我的主要搜尋查詢的範例格式:
SELECT p.ID, p.TITLE PROD_TITLE, fe.TITLE FEATURE_TITLE, f.VAL FROM products p, features f, features_enum fe WHERE p.CATEGORY = 57 AND p.ID = f.P_ID AND f.F_ID = fe.ID AND ( (f.F_ID = 1 AND f.VAL = 'Val1') AND (f.F_ID = 2 AND f.VAL = 'Val2') AND ... (f.F_ID = N AND f.VAL = 'ValN') AND )
到目前為止我的實驗:
由於我在數據庫方面的知識和經驗有限,我在理論規劃上碰壁了。所以,我生成了大量的測試數據來簡單地看看什麼會起作用。所有三個表都有 500,000 個測試行。這裡是平均值。主要搜尋查詢的執行時間:
- 沒有索引的 InnoDB:90 年代。
- 帶索引的 InnoDB:15 秒。 緩衝池大小增加後 0.3 秒
- 沒有索引的 MyISAM:9s。
- 帶索引的 MyISAM:0.7 秒。
- MyISAM 索引 + FIXED 行類型:0.16s。
測試機 - Pentium 4 1.9GHz,1.5GB RAM,IDE HDD,Win7。
除了索引之外,我基本上沒有做任何優化。所以我可能錯過了很多事情,這些事情本來可以讓 InnoDB 執行得更快。**InnoDB 緩衝池大小設置為 16M (!!);我將其增加到 128M。現在,InnoDB 真的很快。所以我傾向於 MyISAM 的一個重要原因現在已經消失了。**也許還有更多我可以做的。
關於該項目的一些要點和長期使用估計:
- 每天添加 20 種新產品,大約每天 20 x 100’specs’ = 2000 條記錄寫入。
- 1,000,000 次頁面訪問,在最壞的情況下 - 每天執行相同數量的搜尋查詢。
- 這些表的總記錄數預計將達到 5,000,000 條。
- 寫入將由半受控制的一群人進行,其中讀取是公開的。
- 沒有復雜的“事務”類型寫入。我現在能想到的最複雜的寫法是——
$$ one product row + 100 feature rows max $$- 一口氣
- 只需要幾個約束,但如果需要選擇 MyISAM,我可以在應用程序級別本身強制執行它們。
- 來自應用程序其他部分的數據庫訪問 - 使用者註冊、身份驗證等.. 將很少而且介於兩者之間,我認為它們不會有太大影響。
鑑於所有這些,我偏向於 MyISAM。但是我需要已經有 MySQL 經驗的人的意見。
問題:
- 如果 InnoDB 執行時間錯誤/令人驚訝,我在測試中錯過了什麼?增加緩衝池大小會顯著提高性能。往上看。
- 如果不是,考慮到以上所有因素,從長遠來看,MyISAM 真的是不錯的選擇嗎?
- 如果後來發現 MyISAM 也是一個糟糕的選擇,那麼我如何輕鬆地重構數據庫?我有什麼選擇?
附帶說明:
- 如果選擇 EAV 不好,我可以為這個項目使用什麼其他架構?
InnoDB 和 MyISAM 各有優缺點。
May 03, 2012
: InnoDB 和 MyISAM 哪個更快?Sep 20, 2011
:最好的 MyISAM 和 InnoDB如果你有足夠的 RAM,我會選擇 InnoDB,因為它在 Buffer Pool 中記憶體數據和索引頁面。MyISAM 只在 Key Cache 中記憶體索引頁。
MyISAM 表在每次 INSERT、UPDATE 和 DELETE 時都會遇到全表鎖。MyISAM 表總是需要對數據進行磁碟訪問。
InnoDB 表總是在以下區域產生磁碟 I/O:
雙寫緩衝區:更改發佈在 ibdata1 以避免作業系統記憶體
插入緩衝區:對 ibdata1 中發布的輔助(非唯一)索引的更改
數據和索引
- 在 innodb_file_per_table = 0 時,將更改寫入 ibdata1
- 使用 innodb_file_per_table = 1,更改將寫入
.ibd
表空間文件。仍然需要針對 ibdata1 讀取 I/O 以交叉檢查表元數據概括
在具有以下條件的環境中:
- 大量寫入
- 重讀
- 大量記憶體
- 重連接
我總是會選擇 InnoDB。請查看我關於 InnoDB over MyISAM 的另一篇文章:何時從 MyISAM 切換到 InnoDB?
我什麼時候會選擇 MyISAM?
在以下場景下
- 使用 MySQL 複製
- 掌握所有 InnoDB
- 所有表都轉換為 MyISAM 的從站
ALTER TABLE ... ROW_FORMAT=Fixed
對於 Slave 上的所有表在磁碟 I/O 方面,MyISAM 稍有優勢,
ROW_FORMAT-Fixed
因為您只與一個文件互動,即.MYD
文件。行大小是完全可預測的,因為 VARCHAR 被視為 CHAR,這縮短了數據檢索的訪問時間。
May 10, 2011
:在固定大小的欄位上使用 CHAR 與 VARCHAR 對性能有何影響?Mar 25, 2011
: MySQL VARCHAR 大小的性能影響另一方面,InnoDB 必須與多個文件互動(ibdata1,InnoDB 表的 .ibd 上的多個讀/寫執行緒)。
根據我使用 MySQL 的經驗,MyIsam 的插入和讀取速度非常快。另一方面,如果您有許多使用者同時訪問數據庫插入和查詢數據,您將開始看到 MyIsam 的性能急劇下降。
MyIsam 在以下情況下很好:
- 你有很多寫和很少讀
- 你有很多讀取和很少寫入
- 你有一個部落格。大多數時候,每天只有少數人在文章和評論之間寫文章
MyIsam 在以下情況下很糟糕:
- 你有很多讀取和寫入同時發生
我已經測試了 PostGreSQL,當數據庫因同時發生讀取和寫入而受到嚴重打擊時,它會執行 MySQL MyIsam。此外,當您擁有高流量網站時,MyIsam 往往每月至少會損壞一次。