最近、Guidを格納するためにUNIQUEIDENTIFIER
ではなくBINARY(16)
を使用するSQL Serverデータベースを継承しました。主キーを含むすべてに対してこれを行います。
心配すべきですか?
心配する必要がありますか?
さて、ここで少し気になることがいくつかあります。
最初:UNIQUEIDENTIFIER
(つまりGuid
)が16バイトのバイナリ値であることは事実ですが、次のことも当てはまります。
INT
はBINARY(4)
に格納でき、DATETIME
はBINARY(8)
に格納できます)。したがって、 #2↴NVARCHAR(128)
のエイリアスとしてのsysname
)。私が見つけることができる3つの行動の違いは次のとおりです。
SQL ServerでのUNIQUEIDENTIFIER
値の比較は、良くも悪くも、実際にBINARY(16)
値を比較する方法とは異なります。 MSDNページによると、SQL ServerでUNIQUEIDENTIFIER
値を比較する場合、 (GUIDとuniqueidentifier値の比較 を比較します。
値の最後の6バイトが最も重要です
これらの値は頻繁にソートされませんが、これら2つのタイプにはわずかな違いがあります。 niqueidentifier のMSDNページによると:
2つの値のビットパターンを比較することによる順序付けは実装されていません。
SQL Serverと.NETの間でGUID値の処理方法に違いがあることを考慮して(上記の「GUIDとuniqueidentifier値の比較」ページに記載)、このデータをSQL Serverの比較動作をエミュレートする必要がある場合、アプリコードへのSQL Serverがアプリコードで適切に処理されない可能性があります。その動作はSqlGuid
に変換することでエミュレートできますが、開発者はそれを行うことを知っていますか?
2番目:次のステートメントに基づく
主キーを含むすべてに対してこれを行います。
PKとしてINT
またはBIGINT
を使用するとともに、代替キーとしてではなくGUIDをPKとして使用することで、システムパフォーマンスを全般的に懸念します。また、これらのGUID PKがクラスター化インデックスである場合は、さらに心配になります。
O.P.が@Robの回答について行った次のコメントは、さらに懸念を引き起こします。
mySQLから移行したと思います
GUIDは 2つの異なるバイナリ形式 で保存できます。したがって、以下に応じてが懸念の原因になる可能性があります。
バイナリ表現が生成された場所の問題は、4つの「フィールド」のうち最初の3つのバイト順序に関係しています。上記のWikipediaの記事へのリンクをたどると、RFC 4122で4つのフィールドすべてに「ビッグエンディアン」エンコーディングを使用するように指定されているのに、Microsoft GUIDでは「ネイティブ」エンディアンを使用して指定していることがわかります。まあ、Intelアーキテクチャはリトルエンディアンなので、最初の3つのフィールドのバイト順は、RFCに準拠したシステム(およびビッグエンディアンシステムで生成されたMicrosoftスタイルのGUID)と逆になります。最初のフィールド「データ1」は4バイトです。 1つのエンディアンネスでは、(仮説的に)0x01020304
として表されます。しかし、他のエンディアンでは、それは0x04030201
になります。したがって、現在のデータベースのBINARY(16)
フィールドが、0x01020304バイナリ表記を使用してインポートファイルから入力され、バイナリ表現がRFCに従ってシステムで生成された場合、変換現在BINARY(16)
フィールドからUNIQUEIDENTIFIER
へのデータは、最初に作成されたものとは異なるGUIDになります。これは実際には問題を引き起こしません[〜#〜] if [〜#〜]値がデータベースから出なかった場合、and値は、順序付けではなく、等しいかどうかのみ比較されます。
順序付けの問題は、UNIQUEIDENTIFIER
に変換した後に同じ順序にならないことだけです。幸いなことに、元のシステムが実際にMySQLである場合、MySQLには文字列表現 [〜#〜] uuid [〜#〜] しかないため、最初にバイナリ表現で順序付けが行われることはありませんでした。
バイナリ表現がWindows/SQL Serverの外部で生成された場合、データベースの外部で使用される文字列値に関する懸念はさらに深刻です。バイト順序が異なる可能性があるため、文字列形式の同じGUIDは、変換が行われた場所に応じて、2つの異なるバイナリ表現になります。アプリコードまたは顧客に文字列形式のGUIDがABC
として123
およびのバイナリ形式から取得され、バイナリ表現が生成された場合RFCに従ったシステムでは、同じバイナリ表現(つまり、123
)は、DEF
に変換されると、UNIQUEIDENTIFIER
の文字列形式に変換されます。同様に、ABC
の元の文字列形式は、UNIQUEIDENTIFIER
に変換すると、456
のバイナリ形式に変換されます。
したがって、GUIDがデータベースから出ていない場合は、順序付け以外のことについてはそれほど心配する必要はありません。または、MySQLからのインポートが文字列形式(つまり、FCCEC3D8-22A0-4C8A-BF35-EC18227C9F40
)の変換によって行われた場合は、問題ない可能性があります。そうでない場合、それらのGUIDが顧客またはアプリのコードに与えられている場合は、それらを取得してSELECT CONVERT(UNIQUEIDENTIFIER, 'value found outside of the database');
を介して変換することにより、それらがどのように変換されるかをテストし、期待されるレコードを見つけることができます。レコードを照合できない場合は、フィールドをBINARY(16)
のままにする必要があります。
おそらく問題はありませんが、適切な条件下では問題が発生する可能性があるため、これについて言及します。
とにかく新しいGUIDはどのように挿入されますか?アプリのコードで生成されましたか?
別のシステムで生成されたGUIDのバイナリ表現のインポートに関連する潜在的な問題についての前の説明が少し(または多く)混乱している場合、うまくいけば、以下が少し明確になるでしょう。
DECLARE @GUID UNIQUEIDENTIFIER = NEWID();
SELECT @GUID AS [String], CONVERT(BINARY(16), @GUID) AS [Binary];
-- String = 5FED23BE-E52C-40EE-8F45-49664C9472FD
-- Binary = 0xBE23ED5F2CE5EE408F4549664C9472FD
-- BE23ED5F-2CE5-EE40-8F45-49664C9472FD
上記の出力では、「文字列」と「バイナリ」の値は同じGUIDからのものです。 「Binary」行の下の値は「Binary」行と同じ値ですが、「String」行と同じスタイルでフォーマットされます(つまり、「0x」が削除され、4つのダッシュが追加されます)。最初と3番目の値を比較すると、それらは正確ではありませんが、非常に近いです。右端の2つのセクションは同じですが、左端の3つのセクションはない。ただし、よく見ると、3つのセクションのそれぞれで同じバイトであり、順序が異なっていることがわかります。最初の3つのセクションのみを表示してバイトに番号を付けると、2つの表現の順序がどのように異なるかを確認しやすくなるので、簡単に確認できます。
文字列= 15F2ED3234BE– 5E562C– 7408EE
バイナリ= 4BE3232ED15F– 62C5E5– 8EE740(Windows/SQL Serverの場合)
したがって、各グループ内では、バイトの順序が逆になりますが、Windows内とSQL Server内のみです。ただし、RFCに準拠しているシステムでは、バイト順の逆転がないため、バイナリ表現はスティング表現をミラーリングします。
MySQLからSQL Serverにデータはどのように取り込まれましたか?ここにいくつかの選択肢があります:
SELECT CONVERT(BINARY(16), '5FED23BE-E52C-40EE-8F45-49664C9472FD'),
CONVERT(BINARY(16), 0x5FED23BEE52C40EE8F4549664C9472FD),
CONVERT(BINARY(16), CONVERT(UNIQUEIDENTIFIER, '5FED23BE-E52C-40EE-8F45-49664C9472FD'));
戻り値:
0x35464544323342452D453532432D3430
0x5FED23BEE52C40EE8F4549664C9472FD
0xBE23ED5F2CE5EE408F4549664C9472FD
バイナリからバイナリへの変換(上記の#2の変換)であると仮定すると、結果のGUIDは、実際のUNIQUEIDENTIFIER
に変換すると、次のようになります。
SELECT CONVERT(UNIQUEIDENTIFIER, 0x5FED23BEE52C40EE8F4549664C9472FD);
戻り値:
BE23ED5F-2CE5-EE40-8F45-49664C9472FD
それは間違っています。そして、それは私たちに3つの質問を残す:
あなたはいつも心配することができます。 ;)
システムは、uniqueidentifierをサポートしていない他のシステムから移行された可能性があります。あなたが知らない他の妥協はありますか?
設計者は、uniqueidentifierタイプについて知らなかった可能性があります。彼らは他に何を知らなかったのですか?
技術的には-それは大きな問題ではありません。