2

非常に優れたサーバー (クアッド コア Xeon 2.0Ghz、16GB RAM、SSD ドライブ) にリストを含むデータベースがあります。データベースには約 180,000 件のリストがあります。サーバーにはまだトラフィックがありません。実際に多くのライブ リスティングと実際のトラフィックがある場合に問題が発生しないことを確認するために、多くのリスティングでテストしています。

しかし、まだトラフィックがなくても、実際よりも早く戻ってくるはずだと思います.

スロー クエリ ログから、次のことがわかりました。

# Query_time: 1.575742  Lock_time: 0.000113 Rows_sent: 12  Rows_examined: 549024

180,000 件のレコードがあり、12 件だけを返す必要がありますが、500,000 件以上を調べて 1.5 秒以上かかりますか? 何かが間違っているはずですよね?:(

実際のクエリは次のとおりです。

SELECT a.listing_id, a.name, a.item_price, a.max, a.nb, a.currency,
     a.end_time, a.closed, a.bold, a.hl, a.buy_price, a.is_offer, a.reserve,
     a.owner_id, a.postage_amount, a.fb_current_bid, a.type, a.start_time,
     a.is_relisted_item, a.enable
     FROM db_listings a
     LEFT JOIN db_users u ON u.user_id=a.owner_id  WHERE a.active=1 AND
     a.approved=1 AND a.deleted=0 AND a.creation_in_progress=0 AND
     a.closed=0 AND (a.list_in='store' OR u.shop_active='1')
     GROUP BY a.listing_id
     ORDER BY a.list_in ASC, a.end_time ASC  LIMIT 0, 12;

インデックスは、db_listings の listing_id と db_users の user_id に既に設定されています。現在そこには2人のユーザーしかいないので、db_usersの参加は問題ではないと思います。

この問題に取り組むために追加情報が必要な場合は、お知らせください。

どんな助けでも大歓迎です:)

4

1 に答える 1

1

まず、クエリに問題があります。LEFT JOIN を使用しますが、where 句で暗黙の INNER JOIN になります: AND (a.list_in='store' OR u.shop_active='1')

これにより、LEFT JOIN が暗黙の INNER に変わるのはなぜですか? LEFT JOIN は、一致するユーザーがいない場合に u.shop_active の NULL 値を生成しますが、NULL は決して「1」に等しくならないためです。OUTER JOIN によって生成されたすべての行が WHERE 条件によってフィルター処理されるため、これにより、クエリが INNER JOIN に変わります。

このフィルターは、パフォーマンスの問題の原因でもあります。2 つの異なるテーブルの列間に OR 条件があります。このような条件を満たすインデックスはありません。

パフォーマンスが向上する可能性のある別の方法を次に示します。このバージョンは、(a.list_in != 'store' および u.shop_active = '1') のリストのみを検索します (list_in='store' のリストが 12 未満の場合)。

以下を使用するには、(list_in, end_time) にインデックスがあることを確認してください

SELECT * FROM
(
    SELECT a.listing_id, a.name, a.item_price, a.max, a.nb, a.currency,
           a.end_time, a.closed, a.bold, a.hl, a.buy_price, a.is_offer, a.reserve,
           a.owner_id, a.postage_amount, a.fb_current_bid, a.type, a.start_time,
           a.is_relisted_item, a.enable
     FROM db_listings a
    WHERE list_in = 'store'
     a.active=1 AND
     a.approved=1 AND 
     a.deleted=0 AND 
     a.creation_in_progress=0 AND
     a.closed=0
    ORDER BY end_time 
    LIMIT 12 
    )
    UNION ALL
    (
        SELECT a.listing_id, a.name, a.item_price, a.max, a.nb, a.currency,
           a.end_time, a.closed, a.bold, a.hl, a.buy_price, a.is_offer, a.reserve,
           a.owner_id, a.postage_amount, a.fb_current_bid, a.type, a.start_time,
           a.is_relisted_item, a.enable
        FROM db_listings a
        JOIN users u 
          ON a.owner_id = u.user_id
         AND u.shop_active = '1'
       WHERE list_in != 'store' AND
       a.active=1 AND
       a.approved=1 AND 
       a.deleted=0 AND 
       a.creation_in_progress=0 AND
       a.closed=0
       ORDER BY end_time 
       LIMIT 12 
    )
) sq
ORDER BY list_in, end_time
LIMIT 12;
于 2012-08-04T23:58:32.257 に答える