まず、別のスタイルの構文を使用します。 ANSI-92
就寝するのに20年かかりましたが、多くのRDBMSは実際にあなたが使用した表記法を使用しないことを推奨しています. この場合、違いはありませんが、多くの理由から、実際には非常に良い習慣です(調査して自分で判断してもらいます)。
最終的な回答と構文例:
SELECT
o.*, p.name, p.amount, p.quantity
FROM
orders
INNER JOIN
products
ON orders.id = products.order_id
WHERE
orders.timestamp >= '2012-01-01'
AND orders.timestamp < '2012-02-01'
AND orders.total != '0.00'
ORDER BY
orders.timestamp ASC
orders
テーブルは最初のフィルタリングを行っているテーブルであるため、最適化を検討するのに非常に適した場所です。
1 月のすべての日付と時刻を取得することDATE(o.timestamp) BETWEEN x AND y
に成功しました。ただし、それには、テーブル内のすべての行DATE()
で関数を呼び出す必要があります(RBAR の意味と同様)。RDBMS は、時間の浪費を避ける方法を知るためだけに関数を見通すことはできません。代わりに、フィルタリングしているフィールドで関数を必要としないように数学を再配置することにより、その最適化を行う必要があります。orders
orders.timestamp >= '2012-01-01'
AND orders.timestamp < '2012-02-01'
このバージョンでは、オプティマイザーは、互いに連続した日付のブロックが必要であることを認識できます。いわゆるレンジシークです。インデックスを使用して、その範囲に適合する最初のレコードと最後のレコードを非常に迅速に見つけ、その間にあるすべてのレコードを選択できます。これにより、適合しないすべてのレコードのチェックが回避され、さらに範囲の中間にあるすべてのレコードのチェックが回避されます。境界だけを探す必要があります。
これは、すべてのレコードが日付順に並べられており、オプティマイザーがそれを確認できることを前提としています。そのためには索引が必要です。それを念頭に置いて、使用できる2つの基本的なカバーインデックスがあるようです:
- (id, timestamp)
-(timestamp, id)
1 つ目は、人々が最もよく使用しているものです。しかし、これにより、オプティマイザーはそれぞれに対して個別にtimestamp
レンジシークを行う必要があります。id
そして、すべてid
の可能性が異なるtimestamp
値を持っているため、何も得られません.
2番目のインデックスは、私が推奨するものです。
これで、オプティマイザーはクエリのこの部分を非常に迅速に満たすことができます...
SELECT
o.*
FROM
orders
WHERE
orders.timestamp >= '2012-01-01'
AND orders.timestamp < '2012-02-01'
ORDER BY
orders.timestamp ASC
たまたま、ORDER BY
提案されたインデックスで最適化されています。データを出力したい順序になっています。結合後にすべてを再ソートする必要はありません。
次に、total != '0.00'
要件を満たすために、範囲内のすべての行が引き続きチェックされます。しかし、すでに範囲をかなり狭めているので、おそらくこれで問題ありません。 (ここでは説明しませんが、MySQL でインデックスを使用してこれと範囲シークを最適化することは不可能であることがわかるでしょう。)timestamp
次に、参加します。これは、既に持っているインデックスによって最適化されています(products.order_id)
。上記のスニペットによって選択されたすべてのレコードに対して、オプティマイザーはインデックス シークを実行し、一致するレコードを非常に迅速に特定できます。
これはすべて、ほとんどの場合、すべての注文行に 1 つ以上の製品行があることを前提としています。たとえば、ごく一部の注文のみが製品行を持っていた場合、関心のある製品行を最初に選択する方が速い場合があります。基本的に、結合が逆の順序で発生していることを確認します。
オプティマイザーは実際にその決定を行いますが、オプティマイザーがそれを行っていることを知っておくと便利です。次に、最も役立つと推定されるインデックスを提供します。
説明計画をチェックして、インデックスが使用されているかどうかを確認できます。そうでない場合、あなたの支援の試みは無視されました。おそらく、別の順序で結合する方が良いことを示唆するデータの統計のためです。その場合は、代わりにインデックスを提供して、結合の順序を助けることができます。