1

この形式の挿入クエリがあります:

on INSERT into abc values .... on DUPLICATE KEY UPDATE .... 

パーティションのない元のテーブルでは、一意のキーがオンでした(subject_id, object_id)が、現在はパーティションを作成しており、すべての一意のキーにパーティションキーを含めるというmysqlの要件のためts、一意のキーを使用する必要があります。(subject_id, object_id, ts)

これは、私の挿入クエリが(以前の挿入からの)同じsubject_idとobject_idの挿入に失敗することを意味しますが、異なるタイムスタンプは一意の新しい行として扱われ、目的の更新の代わりに挿入されます。

回避策はありますか?

CREATE TABLE `abc` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `subject_id` varchar(40) COLLATE utf8_unicode_ci NOT NULL,
  `object_id` varchar(36) COLLATE utf8_unicode_ci NOT NULL,
  `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`,`ts`),
  UNIQUE KEY `userint_sub_type_obj` (`subject_id`,`object_id`, `ts`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
/*!50100 PARTITION BY RANGE (unix_timestamp(ts))
(PARTITION p2012_08_27 VALUES LESS THAN (1346025600) ENGINE = InnoDB,
 PARTITION p2012_08_28 VALUES LESS THAN (1346112000) ENGINE = InnoDB,
 PARTITION p2012_08_29 VALUES LESS THAN (1346198400) ENGINE = InnoDB,
 PARTITION p2012_08_30 VALUES LESS THAN (1346284800) ENGINE = InnoDB,
 PARTITION p2012_08_31 VALUES LESS THAN (1346371200) ENGINE = InnoDB) */
4

1 に答える 1

3

簡単に言うと、パーティションキーをすべての一意の(したがってプライマリ)キーの一部にすることなく、パーティションを追加する方法はありません。

http://dev.mysql.com/doc/refman/5.5/en/partitioning-limitations-partitioning-keys-unique-keys.html

先週、有効/無効の列にパーティションをドロップしようとして、実際に同じ問題が発生しました。頭に浮かんだ2つの解決策があります。

  1. タイムスタンプをmeta_infoテーブルに移動し、それをパーティション化できます。時間条件のあるルックアップは、(subject_id、object_id)キーをいじることなくパーティションを利用できます。もちろん、オーバーヘッドは参加する必要があります。あなたのテーブルが巨大な場合、これは実行可能ではないかもしれません。
  2. 更新する前に確認してください。ON DUPLICATE KEYオプションを使用する代わりに、アクションをSELECTに分割してレコードが存在するかどうかを確認し、その答えに応じてINSERTまたはUPDATEを実行します。

言うまでもなく、このパーティション分割の制限は後部で大きな苦痛であることがわかりましたが、MySQLの制限のようであり、Google Fuを使って質問したところ、簡単な方法があるようです。

于 2012-09-20T21:26:38.870 に答える