8

DBが数百万レコードに成長したため、時間がかかりすぎる(300ミリ秒)クエリがいくつかあります。幸いなことに、クエリはこのデータの大部分を調べる必要はありません。最新の100,000レコードで十分なので、最新の100,000レコードを含む別のテーブルを維持し、これに対してクエリを実行する予定です。誰かがこれを行うためのより良い方法について何か提案があれば、それは素晴らしいことです。私の本当の質問は、クエリを履歴データに対して実行する必要がある場合のオプションは何ですか、次のステップは何ですか?私が考えたこと:

  • ハードウェアをアップグレードする
  • インメモリデータベースを使用する
  • 独自のデータ構造でオブジェクトを手動でキャッシュします

これらは正しいですか、他にオプションはありますか?一部のDBプロバイダーは、これらの問題に対処するために他のプロバイダーよりも多くの機能を備えていますか?たとえば、特定のテーブル/インデックスを完全にメモリ内に指定するなどです。

申し訳ありませんが、私はこれについて言及する必要があります、私はmysqlを使用しています。

上記で索引付けについて言及するのを忘れました。正直なところ、これまでのところ、インデックス作成は私の唯一の改善の源です。ボトルネックを特定するために、インデックスが使用されているかどうかを示すクエリにmaatkitを使用しています。

私は今、質問の意図から離れていることを理解しているので、別の質問を作成する必要があるかもしれません。私の問題は、EXPLAINjprofilerが報告している300msではなく10msかかるということです。誰か提案があれば、本当にありがたいです。クエリは次のとおりです。

select bv.* 
from BerthVisit bv 
inner join BerthVisitChainLinks on bv.berthVisitID = BerthVisitChainLinks.berthVisitID 
inner join BerthVisitChain on BerthVisitChainLinks.berthVisitChainID = BerthVisitChain.berthVisitChainID 
inner join BerthJourneyChains on BerthVisitChain.berthVisitChainID = BerthJourneyChains.berthVisitChainID 
inner join BerthJourney on BerthJourneyChains.berthJourneyID = BerthJourney.berthJourneyID 
inner join TDObjectBerthJourneyMap on BerthJourney.berthJourneyID = TDObjectBerthJourneyMap.berthJourneyID 
inner join TDObject on TDObjectBerthJourneyMap.tdObjectID = TDObject.tdObjectID 
where 
BerthJourney.journeyType='A' and 
bv.berthID=251860 and 
TDObject.headcode='2L32' and 
bv.depTime is null and 
bv.arrTime > '2011-07-28 16:00:00'

からの出力EXPLAINは次のとおりです。

+----+-------------+-------------------------+-------------+---------------------------------------------+-------------------------+---------+------------------------------------------------+------+-------------------------------------------------------+
| id | select_type | table                   | type        | possible_keys                               | key                     | key_len | ref                                            | rows | Extra                                                 |
+----+-------------+-------------------------+-------------+---------------------------------------------+-------------------------+---------+------------------------------------------------+------+-------------------------------------------------------+
|  1 | SIMPLE      | bv                      | index_merge | PRIMARY,idx_berthID,idx_arrTime,idx_depTime | idx_berthID,idx_depTime | 9,9     | NULL                                           |  117 | Using intersect(idx_berthID,idx_depTime); Using where | 
|  1 | SIMPLE      | BerthVisitChainLinks    | ref         | idx_berthVisitChainID,idx_berthVisitID      | idx_berthVisitID        | 8       | Network.bv.berthVisitID                        |    1 | Using where                                           | 
|  1 | SIMPLE      | BerthVisitChain         | eq_ref      | PRIMARY                                     | PRIMARY                 | 8       | Network.BerthVisitChainLinks.berthVisitChainID |    1 | Using where; Using index                              | 
|  1 | SIMPLE      | BerthJourneyChains      | ref         | idx_berthJourneyID,idx_berthVisitChainID    | idx_berthVisitChainID   | 8       | Network.BerthVisitChain.berthVisitChainID      |    1 | Using where                                           | 
|  1 | SIMPLE      | BerthJourney            | eq_ref      | PRIMARY,idx_journeyType                     | PRIMARY                 | 8       | Network.BerthJourneyChains.berthJourneyID      |    1 | Using where                                           | 
|  1 | SIMPLE      | TDObjectBerthJourneyMap | ref         | idx_tdObjectID,idx_berthJourneyID           | idx_berthJourneyID      | 8       | Network.BerthJourney.berthJourneyID            |    1 | Using where                                           | 
|  1 | SIMPLE      | TDObject                | eq_ref      | PRIMARY,idx_headcode                        | PRIMARY                 | 8       | Network.TDObjectBerthJourneyMap.tdObjectID     |    1 | Using where                                           | 
+----+-------------+-------------------------+-------------+---------------------------------------------+-------------------------+---------+------------------------------------------------+------+---------------------------------------

7 rows in set (0.01 sec)
4

7 に答える 7

3
  1. すべてのインデックスが最適化されていることを確認してください。クエリで使用explainして、インデックスが効率的に使用されているかどうかを確認します。
  2. 重い結合を行っている場合は、Javaでこの計算を行うことを検討してください。
  3. NoSQLなどの他のDBを使用することを検討してください。少し前処理を行ってデータをMemcacheに配置すると、少し役立つかもしれません。
于 2011-07-28T14:37:12.687 に答える
1

データベースとクエリを最適化した場合、データを切り刻むのではなく、次のステップは次のことを確認することです。

a)mysql構成を作成し、ハードウェアを最大限に活用していることを確認します

b)ハードウェアを確認します。使用しているハードウェアはわかりません。データベースからの読み取りを分割するために2台または3台のサーバーを購入できる場合は、レプリケーションがオプションであることがわかります(書き込みは中央サーバーに対して行う必要がありますが、読み取りは任意の数のスレーブから読み取ることができます) 。

于 2011-07-28T14:47:46.707 に答える
1

このような設計変更を考慮することは良い兆候ではありません-EXPLAINを使用して絞り出し、db変数を調整し、インデックスとクエリを改善するための十分なパフォーマンスがまだあると思います。しかし、あなたはおそらく「ものを試す」が非常にうまく機能するポイントを過ぎています。これは、分析とログを解釈する方法を学び、学んだことをインデックスとクエリの特定の改善に使用する機会です。

あなたの提案が良いものであれば、その理由をすでに教えてくれるはずです。そして、これは人気のある悲観論であることに注意してください-

あなたが見た中で最もばかげた悲観論は何ですか?

于 2011-07-28T17:25:27.623 に答える
1

最新の結果を得るために別のテーブルを作成する代わりに、テーブルのパーティション化について考えてください。MySQLには、バージョン5.1以降にこの機能が組み込まれています


明確にするために:私はこれがあなたの問題の解決策であると言っているのではありません。あなたが試すことができるただ一つのこと

于 2011-07-28T17:44:32.347 に答える
0

リストした対策を講じる前に、テーブル/インデックス/クエリを最適化することから始めます。RDBMSの機能の限界に達していると絶対に確信できるところまで、パフォーマンスの低いクエリを掘り下げましたか?

編集:実際に適切に最適化されているが、それでも問題がある場合は、必要な正確なデータのマテリアライズド・ビューを作成することを検討してください。あなたが提供したよりも多くの要因に基づいて、それは良い考えかもしれないし、そうでないかもしれませんが、私はそれを考慮すべき事柄のリストの一番上に置きます。

于 2011-07-28T14:37:39.057 に答える
0

最後の100,000レコードの検索は非常に高速であるはずですが、インデックスに問題があることは間違いありません。EXPLAINを使用して修正します。

于 2011-07-28T14:43:08.140 に答える
0

私は今、質問の意図から離れていることを理解しているので、別の質問を作成する必要があるかもしれません。私の問題は、EXPLAINが、jprofilerが報告している300msではなく10msかかると言っていることです。

それならあなたの問題(そして解決策)はJavaになければなりませんよね?

于 2011-07-28T17:44:42.333 に答える