回答:
心配する必要がありますか?
さて、ここには少し気になる点がいくつかあります。
最初: a UNIQUEIDENTIFIER
(つまりGuid
)が16バイトのバイナリ値であることは事実ですが、
INT
で保存できます(たとえばBINARY(4)
、DATETIME
に保存できますBINARY(8)
、などに保存できます)。したがって、#2↴sysname
のエイリアスとしてNVARCHAR(128)
)があるのでしょう。私が見つけることができる3つの行動の違いは次のとおりです。
UNIQUEIDENTIFIER
SQL Serverでの値の比較は、良くも悪くも、実際にはBINARY(16)
値の比較と同じ方法では行われません。GUIDとuniqueidentifierの値の比較に関するMSDNページによると、UNIQUEIDENTIFIER
SQL Serverの値を比較する場合:
値の最後の6バイトが最も重要です
これらの値は頻繁にはソートされませんが、これら2つのタイプにはわずかな違いがあります。uniqueidentifierのMSDNページによると:
順序付けは、2つの値のビットパターンを比較することによって実装されません。
SQL Serverと.NET(上記の「GUIDとuniqueidentifierの値の比較」ページに記載)でGUID値の処理方法に違いがあるため、このデータをSQL Serverからアプリコードに引き出すことは、 SQL Server比較動作をエミュレートする必要がある場合は、アプリコード。その動作はに変換することでエミュレートできますSqlGuid
が、開発者はそれを行うことを知っていますか?
第二:次のステートメントに基づいて
主キーを含むすべてに対してこれを行います。
PKとして、INT
またはBIGINT
PKとしても使用すると共に、代替キーとしてではなくPKとしてGUIDを使用することにより、システムパフォーマンスについて一般的に心配します。また、これらのGUID PKがクラスター化インデックスである場合はさらに懸念されます。
OPが@Robの回答に対して行った以下のコメントは、追加の懸念をもたらします。
MySQLから移行された
GUIDは、2つの異なるバイナリ形式で保存できます。そのため、以下に応じて懸念の原因となる可能性があります。
バイナリ表現が生成された場所に関する問題は、4つの「フィールド」のうち最初の3つのバイト順序に関係しています。上記のWikipediaの記事へのリンクをたどると、RFC 4122が4つのフィールドすべてに対して「ビッグエンディアン」エンコーディングを使用するように指定しているが、Microsoft GUIDは「ネイティブ」エンディアンを使用するように指定していることがわかります。さて、Intelアーキテクチャはリトルエンディアンです。したがって、最初の3つのフィールドのバイト順は、RFC(およびビッグエンディアンシステムで生成されたMicrosoftスタイルのGUID)に準拠したシステムとは逆になります。最初のフィールド「データ1」は4バイトです。あるエンディアンでは、(仮に)として表され0x01020304
ます。しかし、他のエンディアンネスではそうなります0x04030201
。したがって、現在のデータベースBINARY(16)
そのバイナリ表現はRFCに従ってシステムで生成され、現在BINARY(16)
フィールドにあるデータをに変換すると、UNIQUEIDENTIFIER
最初に作成されたものとは異なるGUIDになります。これは本当に問題ないのIF値は、データベースを残していない、決しておよび値がしかの平等ではなく秩序のために比較されます。
順序付けの問題は、単にに変換しUNIQUEIDENTIFIER
た後、順序が同じにならないことです。幸いなことに、元のシステムが実際にMySQLであった場合、MySQLにはUUIDの文字列表現のみがあるため、そもそもバイナリ表現で順序付けは行われませんでした。
バイナリ表現がWindows / SQL Serverの外部で生成された場合、データベースの外部で使用されている文字列値に関する懸念は、より深刻です。バイトの順序が異なる可能性があるため、文字列形式の同じGUIDは、変換が行われた場所に応じて、2つの異なるバイナリ表現になります。アプリケーションコードまたは顧客のように文字列形式でGUIDを与えられた場合ABC
のバイナリ形式から来る123
と RFCを次のシステムで生成されたバイナリ表現、同じバイナリ表現(すなわちこと123
)の文字列形式に変換することになるDEF
に変換されたときA UNIQUEIDENTIFIER
。同様に、の元の文字列形式はABC
、456
に変換されるときにのバイナリ形式に変換されますUNIQUEIDENTIFIER
。
したがって、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
上記の出力では、「String」と「Binary」の値は同じGUIDからのものです。「Binary」行の下の値は「Binary」行と同じ値ですが、「String」行と同じスタイルでフォーマットされています(つまり、「0x」を削除して4つのダッシュを追加します)。最初の値と3番目の値を比較すると、それらはまったく同じではありませんが、非常に近いものです。右端の2つのセクションは同じですが、左端の3つのセクションは同じではありません。しかし、よく見ると、3つのセクションのそれぞれで同じバイトであり、順序が異なっていることがわかります。最初の3つのセクションのみを表示し、バイトに番号を付けると、2つの表現の間で順序がどのように異なるかがわかりやすくなります。
文字列= 1 5F 2 ED 3 23 4 BE – 5 E5 6 2C – 7 40 8 EE
バイナリ= 4 BE 3 23 2 ED 1 5F – 6 2C 5 E5 – 8 EE 7 40(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つの質問を残します: