web-dev-qa-db-ja.com

巨大なデータベース...クエリが遅すぎます。パフォーマンスを改善するには?

現在、3000万行のMySQLデータベースを管理しています(今後さらに増える予定です)。データベース全体は280GBです。サーバーには4GBのRAMおよび3.2Ghz 4コアプロセッサがあります。最大の列には整数の配列がテキストとして格納されます(varcharは十分な大きさにできませんでした)。

シンプルな

テーブル名の制限200,000から行を選択してください。

完了するまでに30秒かかります... 3000万行すべてを選択し、理想的にするには最大で10秒でいくつかのアルゴリズムを実行する必要があります。

私はそのような大きなデータベースを管理することに慣れていません。クエリがこれほど長くかかるのは正常ですか?インデックス作成について聞いたことがありますが、テキストデータタイプの列にインデックスを付けることができません。

パフォーマンスを向上させるにはどうすればよいですか。パフォーマンスを向上させる方法があまりに多くないので、次の方法はありません。

  • インデックス
  • より多くのRAM
  • SSD
  • テーブルの分割(サウンドは複雑ですか?)

考えていないことはありますか?

助けてくれてありがとう! :)

1
God Usopp

インデックスは、特定の述語に一致する行をすばやく識別するためのパスを提供します。一度にテーブルのごく一部を参照する必要がある場合に、これらは最も役立ちます。すべての行が必要なので、これは役に立たないでしょう。また、シーケンスを強制します。あなたがそれを言及しなかったとしても、これがあなたのアルゴリズムが順序付けから利益を得るなら、役に立つかもしれません。

DBMSは、行を処理する前に、データをディスクからメモリにコピーします。したがって、より多くのデータをメモリに保持できるため、より多くのデータが役立ちます。対応するIO待機は少なくなります。280GBを処理する必要があるため、最後の4GBは最後にメモリに格納されます。次のサイクルでは、データが削除され、新しいデータが読み取られます。280GBを超えるメモリをインストールできない場合は、メモリを増やすことはできません。

パーティショニングは、アーカイブのようなものです。ただし、シャーディングが役立つ場合があります。これは、データを複数のサーバーに分散することを意味します。 4台のサーバーは、処理時間を約4分の1にします。ただし、答えをつなぎ合わせるためのカスタムプロセスが必要になりますが、これは簡単ではありません。

単純な事実は、3億行を処理する必要がある場合、3億行を読み取る必要があるということです。これは、おそらくストレージ帯域幅によって制限されます。 SSDは明らかにここで役立ちます。

ただし、毎回すべての行を処理する必要がない方法はありますか?これらの値を事前に計算したり、中間結果をキャッシュしたり、クエリ間の差分のみを処理したりできますか?

Editテキスト列から一部の値を解析するためだけにすべての行を読み取っていますが、実際には特定のクエリで大部分の行を使用していませんか? LIKEはIOを排除するのに役立ちません。値の大部分はテキストの中央にあるためです。インデックスはここでは役立ちません。達成できる最善の方法は、ネットワーク時間を排除するDBサーバー。

全文検索 は、大きなテキスト列内のラベルを見つけるのに役立ちます。おそらく、列をJSONとして再定義し、セカンダリインデックスを追加すると役立ちます。しかし、実際にはこれらは次善の設計のための粗末な回避策です。リレーショナルデータベースは、リレーション、つまりテーブルを処理するために構築されています。データをテーブルとして適切に構造化すると、良好なパフォーマンスが得られる可能性が最も高くなります。この場合、それは、テキスト列に埋め込まれたキーと値のペアを、値ごとに1つずつ、別々の行に分離することを意味します。 「キー」列(およびWHERE句にあるその他の列)のインデックスは、すばらしいスタートです。はい、DBは少し大きくなる可能性がありますが、ソフトウェアはこれ用に設計されています。テラバイト単位のデータが数十億行にあるシステムは数多くあります。大丈夫でしょう。

2
Michael Green