0

私は「オンラインストリーミング」プロジェクトに取り組んでおり、最高のパフォーマンスを得るために DB を構築するのに助けが必要です。現在、ファイル、ポスター画像、post_id など、プレーヤーに関連するすべての情報を含む 1 つのテーブルがあります。

+---------------+-------------+------+-----+---------+----------------+
| Field         | Type        | Null | Key | Default | Extra          |
+---------------+-------------+------+-----+---------+----------------+
| id            | int(11)     | NO   | PRI | NULL    | auto_increment |
| post_id       | int(11)     | YES  |     | NULL    |                |
| file          | mediumtext  | NO   |     | NULL    |                |
| thumbs_img    | mediumtext  | YES  |     | NULL    |                |
| thumbs_size   | mediumtext  | YES  |     | NULL    |                |
| thumbs_points | mediumtext  | YES  |     | NULL    |                |
| poster_img    | mediumtext  | YES  |     | NULL    |                |
| type          | int(11)     | NO   |     | NULL    |                |
| uuid          | varchar(40) | YES  |     | NULL    |                |
| season        | int(11)     | YES  |     | NULL    |                |
| episode       | int(11)     | YES  |     | NULL    |                |
| comment       | text        | YES  |     | NULL    |                |
| playlistName  | text        | YES  |     | NULL    |                |
| time          | varchar(40) | YES  |     | NULL    |                |
| mini_poster   | mediumtext  | YES  |     | NULL    |                |
+---------------+-------------+------+-----+---------+----------------+

100k レコードの場合、クエリに約 0.5 秒かかり、レコードが増えるにつれてパフォーマンスが常に低下します。

+----------+------------+----------------------------------------------------------------------+
| Query_ID | Duration   | Query                                                                |
+----------+------------+----------------------------------------------------------------------+
|        1 | 0.04630675 | SELECT * FROM dle_playerFiles where post_id in ('7000') AND type='1' |
+----------+------------+----------------------------------------------------------------------+

説明 SELECT * FROM dle_playerFiles where post_id in ('7000') AND type='1';

+----+-------------+-----------------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table           | type | possible_keys | key  | key_len | ref  | rows  | Extra       |
+----+-------------+-----------------+------+---------------+------+---------+------+-------+-------------+
|  1 | SIMPLE      | dle_playerFiles | ALL  | NULL          | NULL | NULL    | NULL | 61777 | Using where |
+----+-------------+-----------------+------+---------------+------+---------+------+-------+-------------+

DB構造を改善するにはどうすればよいですか? YouTube のような大きなウェブサイトはどのようにデータベースを構築していますか?

4

2 に答える 2

2

一般に、クエリ時間が行数に正比例する場合、テーブル スキャンが推奨されます。これは、次のようなクエリを意味します。

SELECT * FROM dle_playerFiles where post_id in ('7000') AND type='1'

データベースは、文字通り、すべての行を反復処理し、基準を満たしているかどうかを確認します。

これに対する一般的な解決策は、列 (​​または列のセット) の事前計算された値のリストと、その値を持つ行のリストであるインデックスです。

dle_playerFiles の post_id 列にインデックスを作成すると、インデックスは基本的に次のようになります。

1: <some row pointer>, <some row pointer>, <some row pointer>
2: <some row pointer>, <some row pointer>, <some row pointer>
...
100: <some row pointer>, <some row pointer>, <some row pointer>
...
7000: <some row pointer>, <some row pointer>, <some row pointer>
250000: <some row pointer>, <some row pointer>, <some row pointer>

したがって、このようなインデックスが配置されている場合、上記のクエリはインデックスのノード 7000 を参照するだけで、どの行にそれが含まれているかがわかります。

次に、データベースは post_id が 7000 の行を読み取り、それらのタイプが 1 であるかどうかを確認するだけで済みます。

データベースはクエリを処理するためにすべての行を調べる必要がないため、これははるかに高速です。インデックスのコスト:

  1. ストレージスペース - これはより多くのデータであり、どこかに保存する必要があります
  2. 更新時間 - データベースはインデックスをテーブルへの変更と自動的に同期させます。つまり、INSERT、UPDATE、および DELETE ステートメントは、データを更新する必要があるため、時間がかかります。小さくて効率的なインデックスの場合、通常、このトレードオフは価値があります。

クエリについては、2 つの列にインデックスを作成することをお勧めします。2 つの個別のインデックスではなく、同じインデックスの一部にします。

create index ix_dle_playerFiles__post_id_type on dle_playerFiles (post_id, type)

これが効率的に機能するための注意事項:

  1. SELECT * はここではダメです。すべての列を返す場合、インデックスにはフィルタリング用の列しか含まれていないため、データベースはテーブルにアクセスして列を読み取る必要があります。本当に必要な列が 1 つまたは 2 つだけの場合は、SELECT 句で明示的に指定し、インデックスに追加します。インデックスを肥大化させるだけなので、多くの列に対してこれを行わないでください。
  2. 関数と型変換は、インデックスの使用を妨げる傾向があります。SQL は、整数型の post_id と type を引用符で囲み、文字列として解釈されるようにします。データベースは、すべてを変換する必要があるため、インデックスを使用できないと感じる場合があります。適切な測定のために引用符を削除します。
于 2013-08-27T23:26:56.450 に答える
1

Duration を正しく読み取ると、クエリの実行に 0.5 秒ではなく 0.04630675 (秒?) かかるようです。

いずれにせよ、適切なインデックス作成により、クエリ結果を返すのに必要な時間を短縮できます。query に基づいて、とSELECT * FROM dle_playerFiles where post_id in ('7000') AND type='1'のインデックスを作成することをお勧めします。post_idtype

また、必ずしもすべてのフィールドを返す必要がない場合は、必要なフィールドの個々の列参照を*. フィールドが少ないほど、クエリはより速く返されます。

クエリを最適化するもう 1 つの方法は、特にプライマリ/外部キーおよびインデックス フィールドで、可能な限り最小のデータ型を使用するようにすることです。abigintまたはintamediumintを使用しないsmallinttinyintください。他に選択肢がない場合を除き、PK または FK でテキスト フィールドを使用しないでください (これは DB 設計の罪であり、IMO では、十分なトレーニングと経験を積んだ人であっても、よりよく知ることができます)。可能な限り最小の正確な数値型を使用する方がはるかに優れています。これらすべてが、ストレージ サイズにもプラスの影響を与えます。

于 2013-08-27T23:47:24.810 に答える