簡體   English   中英

MySQL分區和唯一鍵

[英]MySQL partition and unique key

我們有一個這樣的表來保存每個用戶會話的登錄令牌。 對該表進行了早期分區,但現在我們決定對其進行分區以提高性能,因為該表包含數百萬行。

CREATE TABLE `tokens` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `uid` int(10) unsigned DEFAULT NULL,
  `session` int(10) unsigned DEFAULT '0',
  `token` varchar(128) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  UNIQUE KEY `usersession` (`uid`,`session`),
  KEY `uid` (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 PARTITION BY HASH(id) PARTITIONS 101;

我們計划基於“ id ”進行分區,因為它主要用於“ select ”查詢,因此可以有效地執行修剪。

但是問題是我們維護(uid,session)的唯一索引,並且分區要求參與列成為唯一索引的一部分。 現在,在這種情況下, (id,uid,session)的唯一索引沒有意義(始終是唯一的)。

有沒有解決此問題而無需手動檢查(uid,會話)的方法。

大概您唯一的uid,sessionkey索引為您實施了一些業務規則。

您是否依賴DBMS執行該規則? 您是否使用INSERT .... ON DUPLICATE KEY UPDATE...語句,或使用錯誤處理程序或類似的方法來處理這種唯一性? 還是只是為了好措施?

如果您依賴該唯一索引, 則無法在id上對該表進行分區。 Fugeddaboudit。

如果可以刪除該索引或刪除其唯一約束,則可以繼續進行分區。 但是分區通常不適用於具有多個唯一鍵的表。

通常,40M行的表不夠大,無法很好地進行分區。 如果您遇到性能問題,則應該研究改進索引。

編輯 :如果您擁有現代化的硬件(多TB存儲,足夠的RAM)和精心選擇的索引,則分區(我認為)是值得解決的更多麻煩。 對於少於約10 ** 9行的表,這肯定會帶來很多麻煩。 當您的自動遞增id必須BIGINT而不是INT數據類型時(因為int.MaxValue不夠大),那么分區開始值得考慮。

當所有查詢都基於分區鍵進行過濾時,這是最有效的。 沒有分區鍵的其他條件上的篩選速度很慢。

專家提示:關於正則表達式的古老說法也適用於分區。 如果您解決了分區問題,那么現在有兩個問題。

  • 不要使用分區。 它不會加快這種表的速度。
  • 我還沒有看到BY HASH可以加速系統的情況。
  • PRIMARY KEY上分區幾乎幾乎沒有用。
  • 通常,當您擁有完美的“自然” PK (uid, session) -- (uid, session)時,不要使用AUTO_INCREMENT id。 還是應該(toke n)
  • 不要讓一個索引成為另一個索引的第一部分: (uid)是多余的,給定(uid, session)
  • 如果您希望使用表情符號或中文,請考慮使用utf8mb4。 另一方面,如果token是base64,則將其ascii或其他名稱。

因此,我認為這會更好地工作(更小,更快等):

CREATE TABLE `tokens` (
  `uid` int(10) unsigned DEFAULT NULL,
  `session` int(10) unsigned DEFAULT '0',
  `token` VARBINARY(128) NOT NULL DEFAULT '',
  PRIMARY KEY (token),
) ENGINE=InnoDB

您搜索哪個?

WHERE token = ...
WHERE uid = ... AND session = ...

缺點之一是我擺脫了id ; 如果其他表需要id則需要在其中進行更改。

暫無
暫無

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

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