わかりましたので、私は職場でこの (かなり古い) プロジェクトに取り組んでおり、Oracle データベースに対して大量のクエリを使用しています。私は最近、実行に約 6 ~ 7時間かかり、約1400 行を返すこの宝石に出くわしました。問題のテーブル/ビューには ~200'000 行が含まれています。合理的と思われるよりも少し時間がかかっているように感じたので、詳しく調べてみました。セキュリティ/独自の理由から、正確なクエリを共有することはできませんが、これはクエリがより一般的な用語で何をするかを示すはずです:
SELECT
some_field,
some_other_field
FROM (
SELECT
*
FROM
some_view a
WHERE
some_criteria AND
a.client_no || ':' || a.engagement_no || ':' || a.registered_date = (
SELECT
b.client_no || ':' || b.engagement_no || ':' || MAX(b.registered_date)
FROM
some_view b
JOIN some_engagement_view e
ON e.client_no = b.client_no AND e.engagement_no = b.engagement_no
JOIN some_client_view c
ON c.client_no = b.client_no
WHERE
some_other_criteria AND
b.client_no = a.client_no AND
b.engagement_no = a.engagement_no
GROUP BY
b.client_no,
b.engagement_no
)
);
基本的に、私が理解している限りでは、some_view (顧客/エンゲージメントの評価を含む) から、一意のクライアント/エンゲージメントごとに最新の評価を取得することになっています。
2 つの結合は、クライアントとエンゲージメントが別のシステムに存在することを確認するためにあります。このシステムで評価を行った後、それらは主に処理されます。
2 つの数値と日付を連結し、それをサブクエリと比較する方法に注目してください。「面白い」デザインチョイス。したがって、連結を適切な比較に置き換えると、少なくとも何らかのパフォーマンスが向上する可能性があると考えました。私は主に .NET と Web の開発を行っており、データベースに関しては専門家ではありませんが、次のように書き直しました。
SELECT
some_field,
some_other_filed
FROM
some_view a
WHERE
some_criteria AND
(a.client_no, a.engagement_no, a.registered_date) = (
SELECT
b.client_no,
b.engagement_no,
MAX(b.registered_date)
FROM
some_view b
JOIN some_engagement_view e
ON e.client_no = b.client_no AND e.engagement_no = b.engagement_no
JOIN some_client_view c
ON c.client_no = b.client_no
WHERE
some_other_criteria AND
b.client_no = a.client_no AND
b.engagement_no = a.engagement_no
GROUP BY
b.client_no,
b.engagement_no
)
);
ここで、最初の選択のフィールドを に置き換えると、COUNT(1)
両方のクエリでまったく同じ数の行が得られるので、良いスタートです。新しいクエリは、カウントと同じ速さでデータを取得します。10 秒未満です。古いクエリは約 20 秒でカウントを取得し、前述したように、データには 6 ~ 7 時間近くかかります。現在実行中なので、新しいクエリが有効かどうかを確認するために何らかの分析を行うことができますが、明らかに間違っていることがあるかどうかを確認するために、ここでも質問したいと思いました。
編集また、最も外側のクエリを削除しました。これは、クエリをよりクールに見せることを除いて、何らかの目的を果たしているようには見えませんでした..または何か..私は知りません..