2012-01-09 2 views
4

違いがある場合、私はApache Derby 10.8を使用しています。select maxを使用する列で結合すると、このSQL(結合)クエリが遅くなるのはなぜですか?

私は非常にシンプルなデータベースを持っています。テーブルにはアイテムがたくさんあり、テーブルにはそのアイテムの入札がいっぱいです。私はそれに加わったその項目の最高入札額を持つすべての項目を選択したいと思います。次はそれで私の最初の試みで、パフォーマンスがひどいです:

select 
    item.id as item_id, 
    item.name as item_name, 
    item.retail_value as item_retail_value, 
    item.vendor as item_vendor, 
    bid.bid_amount as bid_amount, 
    bid.bidder_name as bid_bidder_name, 
    bid.bidder_phone as bid_bidder_phone, 
    bid.operator_name as bid_operator_name 
from item 
    left outer join bid on bid.item_id = item.id and 
    bid.bid_amount = (select max(bid.bid_amount) from bid where bid.item_id = item.id and bid.status = 'OK') 

私は、各項目(56400件の入札合計)のための200件の入札で282個のアイテムを使用したテストデータのセットを作成しました。上記のクエリは約30〜40秒で実行されます。すべてのアイテムを選択し、手動で各アイテムの入札単価を高くすると、1秒未満で完了します。

bid.bid_amountbid.statusのインデックスを作成しようとしましたが、目立ったことはありませんでした。 SQLは私の最強の領域ではないので、もし誰でも説明しようと思えばなぜその質問がとても遅いのですか本当に感謝します。

答えて

8

相関サブクエリと呼ばれる処理を実行しているため、クエリの処理速度が遅くなります。つまり、各ローに対してmaxが実行されています。

はこのような何かを試してみてください:

select 
    item.id as item_id, 
    item.name as item_name, 
    item.retail_value as item_retail_value, 
    item.vendor as item_vendor, 
    bid.bid_amount as bid_amount, 
    bid.bidder_name as bid_bidder_name, 
    bid.bidder_phone as bid_bidder_phone, 
    bid.operator_name as bid_operator_name 
from 
    item 
    left outer join (
     select 
      item_id, 
      MAX(bid_amount) maxamount 
     from 
      bid 
     where 
      status = 'OK' 
     group by 
      item_id 
    ) b1 on 
     item.id = b1.item_id 
    left outer join bid on 
     bid.item_id = item.id 
     and bid.bid_amount = b1.maxamount 

このサブクエリは、一度だけ実行され、それははるかに高速になりますです。

+1

+1:サブクエリnippierを作るために 'status、item_id、bid_amount'にINDEXを推奨します。 *(おそらく 'item_id、status、bid_amount'はLEFT JOINにも親切です)* – MatBailie

+0

私はエリックと私の答えがほぼ同じであることを実感しました。エリックのために1つの投票! –

+0

これは、余分なインデックスなしで約半分にまで低下します。助けてくれてありがとう! –

2

同期(または相関)サブクエリを作成しました。副問合せは、外部表(項目)のすべての行に対して実行されます。

1

JOIN操作の各ステップでネストされたサブクエリが実行されています。クエリのパフォーマンスが悪いのは不思議ではありません.CPUとディスクはおそらく大変です!あなたがアイテムテーブル内のすべての項目の最大OK'd入札を取得しようとしていると仮定すると、あなたはこのクエリをしようとする場合があります:あなたはまた、入札にインデックスを適用することにより、クエリのパフォーマンスを向上させることができ

SELECT I.id AS item_id, 
     I.name AS item_name, 
     I.retail_value AS item_retail_value, 
     I.vendor AS item_vendor, 
     B.bid_amount AS bid_amount, 
     B.bidder_name AS bid_bidder_name, 
     B.bidder_phone AS bid_bidder_phone, 
     B.operator_name AS bid_operator_name 
FROM item AS I 
    LEFT OUTER JOIN (SELECT item_id, MAX(bid_amount) AS bid_amount 
         FROM bid 
         WHERE STATUS = 'OK' 
         GROUP BY item_id) AS _TEMP ON _TEMP.item_id = B.item_id 
    LEFT OUTER JOIN bid AS B ON B.item_id = _TEMP.item_id AND B.bid_amount = _TEMP.bid_amount; 
0

。 item_idサブクエリはitem_idに基づいてレコードを選択しているためです。

関連する問題