2

ゲームの成行注文がたくさんあるデータベースがあります。DB での私の意図は、安く買って高く売ることにあるので、私がしていることは、お金を稼ぐことができる製品を検索することです。始点と終点を入力し、DB で始点で売りに出されている商品をチェックし、終点で一致して利益のある買い注文がないかチェックします。

現在、約 75 万件のリスティングがあり、クエリの処理に約 8 秒かかります。行数が少ないほど時間がかかりませんでした。データベースがいっぱいになると、おそらく 500 万を超えるエントリがあり、クエリを高速化する方法を理解する必要があります。HAVING と ORDER BY を取り出すと、クエリに約 0.25/秒かかります。mySQLでこれを行う別の方法はありますか、それともPHPで行う方法を見つける必要がありますか? どんな助けでも大歓迎です!

これが私のクエリです:

    SELECT DISTINCT  
    f.orderID as fOrderID,
    f.typeID as fTypeId,
    f.solarSystemID as fSystemId,
    f.regionID as fRegionId,
    f.price as fPrice,
    f.volRemaining as fVolRemain,
    f.bid as fBid,
    f.reportedTime as fReportedTime,
    t.orderID as tOrderID,
    t.typeID as tTypeId, 
    t.solarSystemID as tSystemId,
    t.regionID as tRegionId,
    t.price as tPrice,
    t.volRemaining as tVolRemain,
    t.bid as tBid,
    if(((f.volRemaining < t.volRemaining)),
      ((f.volRemaining * t.price) - (f.price * f.volRemaining)), 
      ((t.volRemaining * t.Price) - (f.price * t.volRemaining))) as profit,
    t.reportedTime as tReporedtTime
    FROM marketData as f
    JOIN marketData as t on t.typeID = f.typeID 
    WHERE f.regionID = 10000001
    AND t.regionID = 10000030
    AND f.bid = 0
    AND t.bid = 1
    GROUP BY f.orderID
    HAVING profit > 1000000
    ORDER BY profit DESC
    LIMIT 100       

MarketDB レイアウト (現在使用していない 9 つの追加の列は含まれていません):

prim-unique                        indexed
+-------------------------------------------------------+
| orderID | regionID | stationID | typeID | bid | price |
+-------------------------------------------------------+ 
| 12345   |  223344  |  334455   |  13    |  0  | 22.43 |
| 12543   |  298474  |  348993   |  13    |  1  | 24.55 |   
| 24574   |  273646  |  392273   |  13    |  0  | 19.32 |
+-------------------------------------------------------+

編集:追加説明:

id  select_type  table   type    possible_keys    key    key_len  ref              rows    Extra
1   SIMPLE       f       ALL     typeID           NULL   NULL     NULL             761338  Using where; Using temporary; Using filesort
1   SIMPLE       t       ref     typeID           typeID 8        market.f.typeID  76      Using where
4

1 に答える 1

2

テーブルには 2 つのインデックスが必要なようです。おそらくこの順序で (regionID,bid,typeID) を含む 1 つのインデックスと、(typeID) だけを持つ 2 つ目のインデックス。最初のインデックスは、条件に一致するレコードを f ですばやくスキャンし、typeID を取得するために使用されます (インデックス内にあります)。2 番目のインデックスは、結合のために t で使用されます。より大きなインデックスを使用して同時に where 句を含めない理由はわかりませんが、MySQL の新しいバージョンでは変更される可能性があります。

実際のデータ パターンによっては、最初のインデックスの複数のバリエーションを同時に作成することで、最初のインデックスをもう少し微調整できる場合があります。6 つの異なる可能な順序を試し、説明計画を実行して、どのインデックスが使用されているかを確認します。 . 次に、未使用のインデックスを削除します。

注 1: 2 つのインデックスがあると、テーブルでの挿入と削除が遅くなりますが、特にインデックスがない場合、この結合クエリの速度がより大きな問題になると思います。

注 2: テーブル内の列の数を減らすことも多少役立ちますが、結合によるスケーリングの問題には対処しません。

于 2013-05-06T15:57:00.917 に答える