sql >> データベース >  >> RDS >> Sqlserver

SQL Server DRI (ON DELETE CASCADE) は遅いですか?

    SQL Server CASCADE はセットベースの操作に最適です。 削除は、その性質上、レコードベースです。

    SQL Server は、他のサーバーとは異なり、即時のセットベースの操作を最適化しようとしますが、1 レベルの深さでしか機能しません。下位テーブルのレコードを削除するには、上位テーブルのレコードを削除する必要があります。

    言い換えると、カスケード操作は上から下に動作しますが、ソリューションは下から上に動作します。これは、よりセットベースで効率的です。

    サンプル スキーマは次のとおりです。

    CREATE TABLE t_g (id INT NOT NULL PRIMARY KEY)
    
    CREATE TABLE t_p (id INT NOT NULL PRIMARY KEY, g INT NOT NULL, CONSTRAINT fk_p_g FOREIGN KEY (g) REFERENCES t_g ON DELETE CASCADE)
    
    CREATE TABLE t_c (id INT NOT NULL PRIMARY KEY, p INT NOT NULL, CONSTRAINT fk_c_p FOREIGN KEY (p) REFERENCES t_p ON DELETE CASCADE)
    
    CREATE INDEX ix_p_g ON t_p (g)
    
    CREATE INDEX ix_c_p ON t_c (p)
    

    、このクエリ:

    DELETE
    FROM    t_g
    WHERE   id > 50000
    

    とその計画:

      |--Sequence
           |--Table Spool
           |    |--Clustered Index Delete(OBJECT:([test].[dbo].[t_g].[PK__t_g__176E4C6B]), WHERE:([test].[dbo].[t_g].[id] > (50000)))
           |--Index Delete(OBJECT:([test].[dbo].[t_p].[ix_p_g]) WITH ORDERED PREFETCH)
           |    |--Sort(ORDER BY:([test].[dbo].[t_p].[g] ASC, [test].[dbo].[t_p].[id] ASC))
           |         |--Table Spool
           |              |--Clustered Index Delete(OBJECT:([test].[dbo].[t_p].[PK__t_p__195694DD]) WITH ORDERED PREFETCH)
           |                   |--Sort(ORDER BY:([test].[dbo].[t_p].[id] ASC))
           |                        |--Merge Join(Inner Join, MERGE:([test].[dbo].[t_g].[id])=([test].[dbo].[t_p].[g]), RESIDUAL:([test].[dbo].[t_p].[g]=[test].[dbo].[t_g].[id]))
           |                             |--Table Spool
           |                             |--Index Scan(OBJECT:([test].[dbo].[t_p].[ix_p_g]), ORDERED FORWARD)
           |--Index Delete(OBJECT:([test].[dbo].[t_c].[ix_c_p]) WITH ORDERED PREFETCH)
                |--Sort(ORDER BY:([test].[dbo].[t_c].[p] ASC, [test].[dbo].[t_c].[id] ASC))
                     |--Clustered Index Delete(OBJECT:([test].[dbo].[t_c].[PK__t_c__1C330188]) WITH ORDERED PREFETCH)
                          |--Table Spool
                               |--Sort(ORDER BY:([test].[dbo].[t_c].[id] ASC))
                                    |--Hash Match(Inner Join, HASH:([test].[dbo].[t_p].[id])=([test].[dbo].[t_c].[p]))
                                         |--Table Spool
                                         |--Index Scan(OBJECT:([test].[dbo].[t_c].[ix_c_p]), ORDERED FORWARD)
    

    まず、SQL Server t_g からレコードを削除します 、次に t_p で削除されたレコードを結合します 後者から削除し、最後に t_p から削除されたレコードを結合します t_ct_c から削除します .

    この場合、1 つの 3 つのテーブルを結合する方がはるかに効率的であり、これが回避策で行うことです。

    気分が良くなったら Oracle カスケード操作は決して最適化されません:それらは常に NESTED LOOPS です 参照列にインデックスを作成するのを忘れた場合は、神が助けてくれます。




    1. ファイル全体をメモリにロードせずに巨大なファイルをBLOB(Oracle)に挿入するにはどうすればよいですか?

    2. 何千もの WHERE 句を含む SQL クエリを最適化する方法

    3. ActiveRecord3デッドロックの再試行

    4. phppassword_verifyがデータベースで機能しない