T-SQLストアドプロシージャの約7000行にビジネスロジックがあり、そのほとんどに次のJOIN構文があります。
SELECT A.A, B.B, C.C
FROM aaa AS A, bbb AS B, ccc AS C
WHERE
A.B = B.ID
AND B.C = C.ID
AND C.ID = @param
このようなクエリを次のように置き換えると、パフォーマンスが向上しますか?
SELECT A.A, B.B, C.C
FROM aaa AS A
JOIN bbb AS B
ON A.B = B.ID
JOIN ccc AS C
ON B.C = C.ID
AND C.ID = @param
それとも同じですか?
2番目のクエリはANSI-92 SQL構文であり、最初のクエリはjoin句を組み込んでいない古いSQL構文であることを除いて、2つのクエリは同じです。確認することもできますが、まったく同じ内部クエリプランを作成する必要があります。
いくつかの理由からANSI-92構文を使用する必要があります
私自身はANSI-92にしばらく抵抗しました。古い構文には概念的な利点がわずかにあり、使用されるすべてのテーブルの一括デカルト結合としてSQLを考えやすく、その後にフィルタリング操作が続くためです。 SQLクエリの実行内容を把握するため。しかし、私は数年前に時代に合わせて移動する必要があると決め、比較的短い調整期間の後、今では強く好むようになりました。これは主に上記の最初の理由によるものです。 ANSI-92構文から逸脱する、またはオプションを使用しない唯一の場所は、暗黙的に危険な自然結合です。
2番目の構造は、SQLコミュニティでは「固定結合構文」として知られています。最初の構成AFAIKには広く受け入れられている名前がないため、「古いスタイル」の内部結合構文と呼びましょう。
通常の引数は次のようになります。
「伝統的」構文の長所:述語は、クエリを一般的にする任意の順序でWHERE
句で物理的にグループ化され、特にn項の関係は読みやすく、理解しやすい(ON
句は述部を広げることができるため、視覚的な距離で1つのテーブルまたは列の外観を探す必要があります)。
「従来の」構文の短所:「結合」述部の1つを省略しても解析エラーはなく、結果はデカルト積(CROSS JOIN
(挿入された構文では)およびそのようなエラーは、検出とデバッグが難しい場合があります。また、 'join'述語と 'filtering'述語はWHERE
句で物理的に一緒にグループ化されるため、互いに混同される可能性があります。
OK、彼らは同じことを実行します。同意しました。多くの人とは異なり、私は古い慣習を使用しています。 SQL-92が「理解しやすい」ことは議論の余地があります。プログラミング言語を40年間プッシュするために書いた(gulp)私は、「読みやすい」が最初に、他の慣習の前に、「視力」で始まることを知っています(ここでの用語の誤用ですが、私が使用できる最高のフレーズです)。 SQLを読むとき、最初に気にするのは、どのテーブルが関係し、どのテーブル(ほとんど)が粒度を定義するかです。次に、データに関連する制約を考慮し、次に属性を選択します。 SQL-92はこれらのアイデアをほとんど分離しますが、非常に多くのノイズワードがあり、心の目でこれらを解釈して対処する必要があり、SQLの読み取りが遅くなります。
SELECT Mgt.attrib_a AS attrib_a
,Sta.attrib_b AS attrib_b
,Stb.attrib_c AS attrib_c
FROM Main_Grain_Table Mgt
,Surrounding_TabA Sta
,Surrounding_tabB Stb
WHERE Mgt.sta_join_col = Sta.sta_join_col
AND Mgt.stb_join_col = Stb.stb_join_col
AND Mgt.bus_logic_col = 'TIGHT'
視力!新しい属性のカンマを前に配置しますコードのコメント化も容易にします関数とキーワードに特定のケースを使用しますテーブルに特定のケースを使用します属性に特定のケースを使用します垂直に演算子と操作を並べますFROMの最初のテーブルを作成しますデータの粒度を表すWHEREの最初のテーブルを結合制約にし、特定の厳しい制約を下に浮かせます。データベース内のすべてのテーブルに3文字のエイリアスを選択し、テーブルを参照するすべてのエイリアスを使用します。そのエイリアスは、そのテーブルの(多くの)インデックスのプレフィックスとしても使用する必要があります。 1 1/2ダースの6、右?多分。ただし、ANSI-92の規則を使用している場合でも(私が持っているように、今後もそうするように)視力の原則、垂直方向のアライメントを使用して、見たい場所に心の目をそらし、簡単に物事を避けます(特にノイズワード)する必要はありません。
両方を実行し、クエリプランを確認します。それらはべき等しい。
2つのクエリareは等しい-最初は非ANSI JOIN構文を使用し、2番目はANSI JOIN構文です。 ANSI JOIN構文に従うことをお勧めします。
はい、LEFT OUTER JOIN(これはANSI JOIN構文でもあります)は、結合先のテーブルに一致するレコードが含まれていない可能性がある場合に使用するものです。
私の考えでは、FROM句は、SELECT句が機能するために行で必要な列を決定する場所です。これは、計算に必要な値を同じ行にもたらすビジネスルールが表現される場所です。ビジネスルールは、請求書を持つ顧客である場合があり、その結果、責任のある顧客を含む請求書の行ができます。また、クライアントと同じ郵便番号の会場である可能性があり、その結果、互いに近い会場とクライアントのリストが作成されます。
結果セットの行の中心性を計算する場所です。結局、RDBMSのリストのメタファーが表示されます。各リストはトピック(エンティティ)を持ち、各行はエンティティのインスタンスです。行の中心性が理解されると、結果セットのエンティティが理解されます。
FROM句で概念的に行が定義された後に概念的に実行されるWHERE句は、SELECT句が機能するために不要な(または必要な行を含む)行をカリングします。
結合ロジックはFROM句とWHERE句の両方で表現できるため、また複雑なロジックを分割して征服するために句が存在するため、FROM句の列に値を含む結合ロジックを配置することを選択します。列内の値の一致によってサポートされるルール。
つまり、次のようなWHERE句は書きません。
WHERE Column1 = Column2
これを次のようにFROM句に入れます。
ON Column1 = Column2
同様に、郵便番号を特定の郵便番号と比較するなど、列を外部値(列に含まれる場合も含まれない場合もある値)と比較する場合、基本的に私は欲しいだけだと言っているので、それをWHERE句に入れますこのような行。
すなわち、私はこのようなFROM句を書きません:
ON PostCode = '1234'
これを次のようなWHERE句に入れます。
WHERE PostCode = '1234'
ANSI構文では、適切な句(ONまたはWHERE)に述語を配置することも、隣接するテーブル参照に対するON句のアフィニティも強制しません。開発者はこのような混乱を自由に書くことができます
SELECT
C.FullName,
C.CustomerCode,
O.OrderDate,
O.OrderTotal,
OD.ExtendedShippingNotes
FROM
Customer C
CROSS JOIN Order O
INNER JOIN OrderDetail OD
ON C.CustomerID = O.CustomerID
AND C.CustomerStatus = 'Preferred'
AND O.OrderTotal > 1000.0
WHERE
O.OrderID = OD.OrderID;
「ANSI-92を生成する」クエリツールと言えば、生成されたため、ここでコメントします。
SELECT 1
FROM DEPARTMENTS C
JOIN EMPLOYEES A
JOIN JOBS B
ON C.DEPARTMENT_ID = A.DEPARTMENT_ID
ON A.JOB_ID = B.JOB_ID
従来の"restrict-project-cartesian product"をエスケープする唯一の構文は外部結合です。この操作は連想的ではないため(それ自体と通常の結合の両方で)より複雑です。少なくとも、外部結合を使用してクエリを慎重に括弧で囲む必要があります。ただし、これはエキゾチックな操作です。頻繁に使用する場合は、リレーショナルデータベースクラスを使用することをお勧めします。