1

ここで単一の SQL ステートメントでブログ投稿にタグを付ける方法を見つけようとしているときに、次の考えが頭をよぎりました。

tags
+-------+-----------+
| tagid | tag       |
+-------+-----------+
|     1 | news      | 
|     2 | top-story | 
+-------+-----------+

tag2post
+----+--------+-------+
| id | postid | tagid |     
+----+--------+-------+
|  0 |    322 |     1 |
+----+--------+-------+

次のようにタグ自体にインデックスを付ける次のモデルを使用しないのはなぜですか? タグの名前が変更されることはなく、追加および削除されることはないと考えれば、これは理にかなっていますよね? どう思いますか?

tag2post
+----+--------+-------+
| id | postid | tag   |     
+----+--------+-------+
|  1 |    322 | sun   |
+----+--------+-------+
|  2 |    322 | moon  |
+----+--------+-------+
|  3 |   4443 | sun   |
+----+--------+-------+
|  4 |   2567 | love  |
+----+--------+-------+

PS: 私はidを保持しています。最後に追加されたn 個のタグを簡単に表示するために...

4

5 に答える 5

7

機能しますが、タグに冗長性があるため、正規化されていません。また、「同じ」タグを使用して投稿以外のものにタグを付ける機能も失われます。N が小さい場合、最適化は問題にならないので、実行しても問題ありません。

実際問題として、インデックスは大きくなります (検索のためにタグにインデックスを付けると仮定すると、重複のインデックスと文字列のインデックスが作成されます)。正規化されたバージョンでは、tags テーブルのインデックスが小さくなり、重複がなくなり、tagid の tag2post テーブルのインデックスが小さくなります。さらに、固定サイズの int 列はインデックス作成に非常に効率的であり、クラスタリングの選択によっては断片化を回避することもできます。

名前を変更しないと言ったことは知っていますが、一般的に、どちらの場合でも、タグの名前を変更する (または削除する) ことの意味について考える必要があるかもしれません - すべてのエントリを変更する必要があるのか​​、それともタグ何らかの方法で分割します。これは最悪の場合 (すべての tag2post の名前を変更する必要がある) トランザクション内でのバッチ操作であるため、設計の観点からは、これを重要なものとして分類することはあまりありません。

于 2009-01-26T16:14:52.570 に答える
2

ID を使用して別のテーブルに委任したものを参照することは、データベース内のすべての場所で名前を変更したくないため、ユーザーの名前など、さまざまなものがある場合に意味があります。彼がそれを変えるとき。ただし、この場合、タグ名自体は変わらないため、唯一の潜在的な欠点は、テキスト インデックスは数値インデックスよりも検索が少し遅くなる可能性があることです。

于 2009-01-26T16:06:16.160 に答える
2

ID を含む関係テーブルに対するあなたの提案の本当の利点はどこにありますか?

技術的には同じ問題を解決しますが、提案されたソリューションは冗長で非正規化された方法でそれを行います。これは、関係テーブルからデータを直接読み取ることができるという本能的な衝動を満たすだけのようです。

DB サーバーは、テーブルの結合に非常に優れており、結合がインデックスを持つ INT フィールドにある場合はなおさらです。INT id, VARCHAR(50) TagName別のテーブル (: など) をクエリに結合するときに、壊滅的なパフォーマンスの問題に直面することはないと思います。

ただし、タグの名前を簡単に変更する機能が失われ (そうする予定がない場合でも)、冗長なデータで関係テーブルを不必要に膨らませることになります。時間の経過とともに、正規化されたソリューションよりもパフォーマンスが低下する可能性があります。

于 2009-01-26T16:33:32.767 に答える
2

アプリケーションによっては、正規化されていない方法で問題ない場合があります。VARCHAR データの大規模なセットを検索するため、パフォーマンス ヒットが発生する場合があります。

「sun*」(sun、sunny、sunrise など) のようにタグ付けされたものを検索する場合、結合を行う必要はありません。ただし、はるかに大きな VARCHAR データのセットに対して同様の比較を行う必要があります。適切なインデックス作成によりこの問題は軽減される可能性がありますが、データセットでどの方法がより高速であるかはテストのみでわかります。

正規化されたテーブルを事前に結合する VIEW を追加するオプションもあります。これにより、高度に正規化されたデータを保持しながら、より単純なクエリが得られます。

データ スキーマの非正規化によって問題が修正されるまで、正規化された構造を使用することをお勧めします (そして、使いやすさのために必要な非正規化されたビューを追加します)。

于 2009-01-26T16:46:56.873 に答える
0

私もそれを検討していました。データベース内のタグのリストが必要な場合は、tag2post から個別のタグを選択するだけです。select ステートメントを最適化したいので、文字列を使用するよりもはるかに高速であるため、整数キーを使用する方がよいと言われました。

于 2009-01-26T16:16:56.763 に答える