一般に、文字列キーの使用が一般に悪い考えと見なされるのはなぜですか?


24

これはしばらくの間私を悩ませてきました。ほとんどの場合、ハッシュテーブル、プログラマ、書籍、記事などの構造にデータを保存する場合、文字列値による構造内の要素のインデックス付けは悪い習慣と見なされます。しかし、これまでのところ、それが悪い習慣であると考えられる理由を説明するための単一のそのような情報源を見つけていません。プログラミング言語に依存していますか?基礎となるフレームワーク上で?実装について

役立つ場合は、2つの簡単な例を挙げます。

行がString主キーによってインデックス付けされるSQLのようなテーブル。

キーが文字列である.NET辞書。


9
一般に、文字列キーを持つことは悪い考えではありません。これらのステートメントは、より優れたキータイプが利用可能なコンテキストで作成されたと思われます。文字列キーを持つ.net辞書が常にあります。この主張の例をいくつか挙げていただけますか?
-CodesInChaos

3
通常、オブジェクト/行の存続期間にわたって変化しない主キーが必要です。たとえばusernameusersテーブルの主キーはおそらく最良のアイデアではないため、自動インクリメントIDを好むでしょう。しかし、それusernameは単なる偶発的なものであり、可変プロパティであることが主な問題です
-CodesInChaos

データベースでは、整数ではなく文字列のインデックス方法を検討してください。

@CodesInChaosほとんどのケースを見つけた場所を思い出すことができればいいのですが、今のところは、問題を思い出させた部分を貼り付けることができます。これは、ゲームの対話について議論し、<key = string、value = object>のペアで世界に関する事実を保存するValveによるGDCスライドショーからのものでした。

2
文字列は問題ありません。「魔法の」文字列ではありません。そのため、ハッシュテーブルを使用するときは、コードに裸の文字列が含まれていないことを確認してください。キーとしての大きなテキスト値はうまく機能しないため避ける必要がありますが、ほとんどの実際の状況では、短いテキスト文字列は整数と同じくらい高速です(大規模なデータベースではありません)。代替キーを使用することもできます。たとえば、主キーは数字ですが、「スラッグ」または一意の文字列もあります。
ipaul

回答:


17

基本的には、次の2つのことに関係しています。

1)ルックアップの速度(たとえば、整数がはるかに優れている場合)

2)インデックスのサイズ(文字列インデックスが爆発する場所)

現在、すべてはニーズとデータセットのサイズに依存しています。テーブルまたはコレクションに10〜20個の要素がある場合、キーのタイプは無関係です。文字列キーでも非常に高速です。

PSあなたの質問とは関係ないかもしれませんが、GUIDはデータベースキーにとっても悪いと考えられます(16バイトGUIDと4バイト整数)。データ量が多い場合、GUIDはルックアップを遅くします。


常にではありません-増分GUIDが可能です。インデックスはさらに大きくなりますが、検索のペナルティはそれほど悪くありません。
サム

7
実際、彼らは大丈夫です。タイムディスクIO時間とメモリ内の値の比較との関係を調べる必要があります。ディスクアクセス時間がメモリの比較を圧倒するため、データベースパフォーマンスの分析で実際に重要なのはIOだけです。キーがGUIDであるか、文字列であるか、整数であるかは、それほど重要ではありません。インデックスサイズは1ページに収まるインデックス値の数に影響しますが、キーが4バイトのint(十分に大きくない可能性があり、クライアントで生成できない)か16バイトの値かは重要な問題ではありません。一部のデータベースでは、rowIdのサイズは16バイトです。
ipaul

9

文字列をキーとして使用する場合、またはより正確には、文字列リテラルをキーとして使用する場合、もう1つの問題があります。純粋なパフォーマンス/効率の理由は別です。タイプミス。あなたは辞書のキーとして文字列リテラルを使用する場合は1をするとき、あなたは厄介な驚きのために自分自身を設定している"ReceiverId"なり"RecieverId"。キー値を保存する定数を設定し、辞書にアクセスするたびに再利用します。

些細で自明なことですが、Web上の驚くほど多くの.NETコード例では文字列リテラルを使用しており、この疑わしい慣行を伝播しています。ここでは、すべてのセッション、ViewState、およびQueryParamsがコードベースに散らばっているASP.NETが特に有罪です。


些細ではない私見。私はまた、キーがある例を見てきました"1"とが"1 "同じテーブルでを。
pswg

ミックスで大文字と小文字を区別する場合も、さらに面白くなります。私を含む多くの人々がその中に直接つまずくのを見ました。
トニーホプキンソン

少なくともC#では、定数を使用するよりも優れているのは、代わりに式を使用することです。そうすれば、メソッド/プロパティなどの名前から文字列を生成できるため、文字列のルックアップがタイプセーフになり、リファクタリングしやすくなります。
GoatInTheMachine

4

ここには多くのトレードオフがあります。実際には文字列キーを頻繁に使用しますが、多くの場合、結合に代理のセカンダリキーを含めます(MySQLを使用している場合は明らかに逆になります)。ただし、そうしない場合があります。

最初に、dbがこれをうまく処理できる主キーとして自然キーを宣言するのが好きです(たとえば、PostgreSQL)。これは正規化に役立ち、データベース設計をより明確にします。代理キーを使用すると、簡単に参加できます。

私が通常サロゲートキーを追加する理由は2つあります。

  1. 自然な鍵が何であるかは必ずしも明確ではありません。これらは時々変更する必要があります。結合および参照整合性に使用される自然な複合キーの変更は複雑であり、エラーが発生しやすくなります。

  2. 複合キーの結合パフォーマンスには問題があり、自然なキールートをたどると、そこに行き詰まります。

ただし、自然キーが定義、単一列、およびテキストの場合、通常は文字列キーに参加します。これを行う理由は、これによりルックアップでの結合が回避されることが多いためです。最も一般的な使用法は、列挙型のユースケースに関する適切なdb設計を提供することです。ほとんどの場合、これらはルーチンクエリの追加の結合を必要としませ。この場合、結合キーとしての文字列キーは完全に理にかなっています。

たとえば、LedgerSMBでは、アカウントの分類を保存します。これらは文字列参照によって識別されます。その他のデータは、アカウントに影響を与える可能性のある分類の組み合わせに関する規則を実施するために使用される文字列参照とともに保存されます。ロジックが必要なのは、一連のカテゴリを保存するときだけなので、文字列キーに参加します。

デフォルトが整数キーになる理由については、単にインデックスサイズの問題ではないと思います。大きな問題はキーの管理です。キーは任意であり、数百万のレコードを処理する可能性があるため、一意の文字列を生成する方法が必要です。このためにUUIDを使用する場合もありますが、UUID衝突の可能性はゼロではなく、数十億のレコードが保存されているため、この可能性は、増分整数型との衝突の可能性がゼロである間に実際に見られるほど高くなります定義により。


整数型をラップアラウンドしてゼロに戻すことができれば、ゼロではありません。「レコード数十億」に近い不穏でわずか4Gである符号なし32ビットタイプ、...のために
ドナルフェロー

「ラップアラウンドではなくエラー」を伝えることができるデータベースがある場合、ゼロです。いずれにせよ、擬似乱数値よりも整数の増分による衝突の可能性を管理する方が簡単です。
クリストラヴァーズ

1

キーとして文字列を使用する場合、特にsqlのようなテーブルに関しては、多くの潜在的な問題があります。@bunnyで述べたように、テーブルのインデックスは大きくなりますが、より重要なことは、テーブルへの外部キーの関係には、より軽い(整数)識別子ではなく、両方のテーブルに文字列が含まれることです。最初のテーブルを参照するテーブルがさらにある場合は、データベース全体で文字列キーが増殖します。


1

それ自体は悪い考えではありません。通常、20/20後知恵で貧弱な設計上の妥協です。文字列の柔軟性と範囲対追加のコストと複雑さ。

整数がジョブ範囲を賢く処理し、高価な処理の大部分が整数が何を表すかを知る必要がない場合は、それを使用します。


0

どういうわけか、Hashtableから間違ったデータを取得しました。

「DaytimeTelephone」または「EveningTelephone」という意味ですか?

または

1234567または1234576のことですか?

数字は間違いなく、より効率的である一方で、マシン(と彼らやる)物事がゆがんで行く時はいつでも、それはの同類に落ち、あなたと私は、その時点で、起こったことの意味を理解し、そのストレージの数バイトの節約と数マイクロ(ナノ?)秒の処理は、毎回明瞭さを失います。


1
そのため、コード内の定数の名前を使用してマジック番号を表す定数のリストが作成されます... Java列挙型は、さらにそれを抽象化して、名前だけで序数を残しますマッピングは見えません。
ジュウェンティング

-1

多くのトレードオフがあり、誰も正しい答えはありません。多くのプログラマーは、ハッシュとデータベースの動作を認識していないため、データベースで文字列キーを使用することを検討しません。文字列キーは、非常に安定している、または無意味(代理)である限り、多くの状況で適切な設計選択です。


2
この回答は、他の回答でまだ言われていないことを追加するものではありません。
マーティンピーターズ14

-2

文字列キーは、約10〜100の短い文字列レコードを持つルックアップテーブルになると意味があります。関連データが読みやすい+変更追跡(数値/ GUID IDと文字列(「管理者」など)など)。ところで、ASP.NETメンバーシップデータベースは、AspNetRolesに文字列キーを使用します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.