私はMySQLを使用して、10億以上の結果の結果を一時的に保存しています。この場合、結果は並列で実行されるプロセスによって計算されます。各結果は、[o1]と[o2]でそれぞれ識別されるオブジェクトの表現[r1]と[r2]で関数[f]を使用して計算されます。現在、このプロセスを実行するために3つのテーブルを使用しています。(1)オブジェクト識別子をそれらの表現にマッピングするテーブル:
mysql> describe v2_3282_fp;
+----------------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+------+------+-----+---------+-------+
| objid | text | YES | | NULL | |
| representation | text | YES | | NULL | |
+----------------+------+------+-----+---------+-------+
(2)各計算プロセスが取得する必要のあるジョブを保持するテーブルと計算:
mysql> describe v2_3282_job;
+----------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------------------+------+-----+---------+----------------+
| jobid | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| workerid | int(11) | YES | | NULL | |
| pairid1 | text | YES | | NULL | |
| pairid2 | text | YES | | NULL | |
+----------+---------------------+------+-----+---------+----------------+
(3)計算ジョブの結果を保持するテーブル:
mysql> describe v2_3282_res;
+-----------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------------------+------+-----+---------+----------------+
| resultid | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| pairid1 | text | YES | | NULL | |
| pairid2 | text | YES | | NULL | |
| pairscore | double(36,18) | YES | | NULL | |
+-----------+---------------------+------+-----+---------+----------------+
(ペアスコアタイプは実行中に動的に決定され、(36,18)に固定されません。)
表現が登録されると、1つのプロセスが結果テーブルを継続的にスキャンして新しい結果を探し、メモリ内に存在するオブジェクトに転送します。残りのプロセスは、計算の終了を通知する識別子のペアを持つジョブを受け取るまで、計算するジョブを取得します。
1,000,000程度の計算を使用した単体テストでは、このシステムは問題なく機能します。ただし、このシステムを使用するための需要が1,000,000,000以上に増加するにつれて、システムがメモリとディスクの間で行き来することで最終的に行き詰まることがわかります。使用中のシステムメモリとスワップスペースを確認すると、使用されているシステムメモリは完全に使用されていますが、通常、使用されているスワップの20%未満です。
私は、テーブル全体をメモリに読み込むことができるときにMySQLのパフォーマンスが最高であり、ディスクI/Oに頼ることが主要なボトルネックであることを読みました。これは私にも当てはまるようです。12GBと16GBのRAMを搭載したシステムで計算を実行すると、最終的にはワーカープロセスサイクルの間隔が長くなりますが、64GBのシステムでこの問題が発生することはありません。
正直な答えは「やあ、RAMをもっと買う」ですが、より根本的な設計上の問題があり、需要の増加に伴ってシステムが劣化していると思います。MySQLは広く使用されている優れた設計の製品であり、データベースとテーブルの設計を考慮するとパフォーマンスに大きな影響を与える可能性があることを私は知っています。
したがって、メモリを追加購入するという強引な解決策に頼ることなく、私が思いついたMySQLテーブル設計のエンジニアリングを改善する方法についての提案を探しています。MySQLテーブルの正規化の基本を知っており、ニーズを実装するためのクエリを作成できますが、各タイプのデータベースエンジン、インデックス作成の詳細、およびその他のデータベース固有の設計上の考慮事項についてはよくわかりません。
私が持っている質問は次のとおりです。(1)結果テーブルとジョブテーブルを単一の大きなテーブルではなく小さなテーブルに分割した場合、パフォーマンスは異なりますか?(私はそうは思いません。)(2)私は現在、プログラムで制限句を発行して、各取得サイクルで一定数の結果を取得しています。ただし、これが単純な「SELECT ... FROM [result table] LIMIT start、size」よりもさらに最適化できるかどうかはわかりません。(私はそう思います。)(3)MySQLを「追いつく」ために、サイクル間でスリープするようにワーカープロセスに指示することは意味がありますか?(私はそうは思いません。)
データベースとテーブルの設計の経験者からのアドバイスに感謝します。