「ビッグテク」環境(ユーザートン、膨大なデータセット、急速に進化する要件)では、データベースに依存するUNIQUE INDEX
二重データを防止するための制約 - すべてのペニーが正確でなければならない金融調和のようなもの以外は - 正直に言えば、あなたが考えるほど効果的ではないかもしれません。 加えて、それらを維持するコストは驚くほど高いかもしれません。 より良いアプローチは、しばしばアプリケーションレイヤーで大半のデドプリケーション論理を処理することです。
なぜ私はユニークなインデックスを再考し始めたのか? なぜ私は燃え尽きたのか。
データベースのユニークなインデックスはかなり信頼できるように聞こえますか? データの重複に対する最後の防衛ラインです。 私もそう思っていました。 テーブル内のフィールドがユニークである必要があるとき、私は偶然、それにユニークなインデックスを落とします。
現実が私に厳しい目覚まし声をかけた時まで。
久しぶりに、髪の毛がもっと充実していた頃、私は数千万行のテーブルに複合型のユニークなインデックスを追加する必要がありました(例えば、tenant_id
そしてis_deleted
一緒にユニークになる必要がある) 単純に聞こえるよね? いいね、変化のプロセス全体が引き続き続いています。日々この間、マスター・スラブ・レプリケーションの遅れはロールカーストにあり、我々は潜在的なサービスハックについて常に心配していました。その後、私は疑問に思わず、このデータベースレベルの「ユニークさ」はその努力とリスクの価値があるのでしょうか。
その後、もう一つの不便な状況がありました ビジネス賢明な私たちは皆知っていますuser@example.com
そしてUSER@EXAMPLE.COM
実際には同じメールです あなたのアプリケーションコードは確実にそれらを正常化する (例えば、ダウンケース) 登録中に複製をチェックする前に. しかし、データベースのユニークなインデックス (しばしばデフォルトでケースに敏感) はそれをそのように見ない. 時には、歴史的なデータや正しく正常化されていないサイドチャンネルデータの同期のために、あなたはデータベースの「同じ」メールの両方のケースのバージョンで終わります. そのような場合、ユニークなインデックスは、このビジネスレベルの複製に「盲目」または、あなたがデータを修正しようとすると、その固いルールは実際にあなたの道に入ります。
たとえば、たぶん「メールのユニークさ」は以前は十分だったかもしれないが、今では要求が「レンタルID+メールのユニークさ」に変わる。DROP
ped and a new one(ペットと新しいひと)CREATE
d.この2つの操作セットをどのように連携するか?どちらが先に進むか?その間に何かが間違っているとどうなるか?大規模なテーブルでこのような操作を実行することは、毎回爆弾を排除するように感じる――完全に神経崩壊する。
これらの経験により、大規模なデータ量、高い同期性、急速に変化する要件を伴う環境では、ユニークなインデックスに対する伝統的なアプローチはまだ正しいものなのでしょうか? 欠点は利益を上回り始めていますか?
この記事は、これについての私の反省を共有するためのものです。
2. ユニークな指数
なぜ我々はそれほど信頼しているのか。
ユニークな指数
私が苦情に浸る前に、公平であり、なぜユニークなインデックスがそれほど人気があるのかを認識しましょう。
- データの完全性の究極の保障:データの重複を防ぐ究極の障壁。
- 実装しやすい: テーブルを作成するときに数行の SQL や、後で DDL を追加すると、完了します。
- Schema as documentation: このフィールドは複製を含むことができない。
- クエリのパフォーマンス向上の可能性:インデックスであるため、このキーのクエリはより速く処理できます。
これらの利点は、小規模なプロジェクト、またはデータの量が管理可能で、ビジネス論理が過度に複雑ではない場合に非常に魅力的ですが、ビッグデータと迅速なイテレーションの「戦場」に入ると、物事は劇的に変化します。
3. ユニークな指数
「ビッグテクノロジー」レンズの下で:それらの利点はまだ有効ですか?
ユニークな指数
上記の「利点」のそれぞれを調べて、大規模で急速なテクノロジー環境でそれらがまだ持続しているかどうかを調べてみましょう。
-
"The ultimate safeguard"? Is this safeguard reliable? What exactly is it safeguarding against?
It doesn't fully recognize business-level "duplicates"! Except the email case sensitivity issue I mentioned earlier (which could be solved by using
collation
but introduce more complexity in the DB layer), or phone numbers with or without+44
, or usernames with or without special characters stripped... these nuances, which business logic considers "the same," are beyond the grasp of a database's simplistic "byte-for-byte identical" unique index. It can't prevent "logical duplicates" at the business layer.The application layer has to do the heavy lifting anyway. Since all these complex "sameness" checks must be handled in the application code (you can't just throw raw database errors at users, can you?), the application layer is the true workhorse ensuring "business data uniqueness." The database's unique index is, at best, an "auxiliary police officer" whose standards might not even align with the business rules.
In distributed systems, it's merely a "local bodyguard." Once you shard your tables in a distributed scenario, an in-table unique index can't ensure global uniqueness. Global uniqueness then relies on ID generation services or application-level global validation. At this point, the "safeguard" provided by the local database index becomes even less significant.
This "ultimate safeguard" might miss the mark, has limited coverage, and relying solely on it is a bit precarious.
-
"Easy to implement"? One-time setup, week-long headache.
Adding a unique index to a brand new table is indeed just one SQL statement. But more often, you're changing the rules for an old table that's been running for ages and has accumulated mountains of data. Trying to alter a unique index on a table with tens of millions of rows (e.g., changing from a single-field unique to a composite unique) could mean several minutes of table locking! Online DDL tools might save you from service downtime, but the entire process can still be lengthy, resource-intensive, and risky.
Agile? Not so fast! In scenarios with rapid iteration, multi-region synchronization, and compliance requirements, a single unique index change at the database level can hold you up for days. So much for agility.
So, that initial "simplicity" is like bait compared to the "hell" of modifying it later.
-
"Schema as documentation"? The documentation might not match reality!
Yes, a unique index in the table structure acts as a form of "technical documentation." But "documentation" can be misleading. If the "uniqueness" defined by this index doesn't align with the actual, more complex business rules (like the case-insensitivity example), then this "documentation" is not only useless but can also mislead future developers. If changing this "documentation" (i.e., modifying the unique index) involves an epic struggle, why not write down the business rules properly in actual design documents, wikis, or code comments? Those are far easier to update.
-
"A potential query performance boost"? Is the tail wagging the dog?
This is a common misconception, or rather, an overemphasized "added value." If you simply want to speed up queries on a specific field or set of fields, you can absolutely create a regular, non-unique index for them! A non-unique index will boost query speeds just fine, and it comes without the write overhead, DDL pains, and rigid business logic constraints of a unique index.
-
Master-slave index inconsistency can instantly "paralyze" replication:
I've seen it happen multiple times: the unique index configuration on the primary database is updated (e.g., a field is added, or a constraint is changed), but the index on the replica isn't modified in sync. Then, as soon as data changes on the primary (e.g., a row is inserted that would be considered a duplicate on the replica, or the primary can write it but the replica can't due to the incorrect/outdated index), the binlog is applied to the replica, and bam!
Slave_SQL_Running: No
. Replication just dies. When this happens, you get data lag, read-write splitting is affected, and it can even impact failover capabilities. What a nightmare, right?
アプリケーション レイヤーが仕事をするように - It's What It's Good At!
データベースのユニークなインデックスに関するこれらの問題を考慮すると、データのユニーク性を確保する責任は主に当社のアプリケーション層にかかるべきです。
アプリケーションレイヤーでのユニーク性を扱う利点は数多くあります:
- 柔軟性と正確性:ビジネスが複製として定義するものは何であれ、我々はそれに応じて論理をコードすることができます - ケースの敏感性、フォーマット、複雑な条件、あなたがそれを名乗る。
- より良いユーザーエクスペリエンス:ユーザーが間違いを犯した場合、私たちは「この電話番号はすでに登録されています。
- Efficient Early Rejection: Intercept duplicates at the service interface layer or even the gateway layer, before the data even hits the database, saving a pointless round trip. データがデータベースに到達する前に、サービスインターフェイスレイヤーレイヤーまたはゲートウェイレイヤーで複製されます。
- インターフェイス Idempotency: これは複製操作に対する強力な武器です。ユーザーが Submit ボタンをダブルクリックする場合、またはネットワークの問題がリリースを引き起こす場合、アプリケーション レイヤーの適切な idempotency はデータが複製されないことを保証します。
結論
ユニークなインデックスを使用する場合にのみ、その利点(通常は極端な場合に絶対的な最後のリソースデータバックストップとして)が、膨大なデータボリュームと迅速なイテレーション(アクセシビリティを妨げ、操作の痛み)を伴う複雑な環境で引き起こす無数のトラブルを明確に、大幅に上回ることを考慮してください。強力なアプリケーション層のユニークさのメカニズム(フロントエンド検証、アシンクロン処理、アイドパッケージ、グローバルID生成など)を優先してください。