0

200,000 行のテーブルがあります。重複レコードを構成するものの定義に適合するさまざまな基準に基づいて、このテーブルからデータのスライスを削除するビューを作成しました。そのためのコードを以下に示します。誰かがこのクエリをより高速で効率的に作成する方法を提案できるかどうか疑問に思っていました。現在、実行に約 20 秒かかりますが、このクエリを実行するのにせいぜい数秒かかることを望んでいました。私は SQL Server 2005 を使用しています。SQL に関する私の知識は非常に初心者であり、助けていただければ幸いです。

WITH dsm_hardware_basic_cte AS
(
 SELECT    TOP 100 PERCENT
           dbo.dsm_hardware_basic.[UUID]
          ,dbo.dsm_hardware_basic.[Name]
          ,dbo.dsm_hardware_basic.[LastAgentExecution]
          ,dbo.dsm_hardware_basic.[MaxUserRegistration]
          ,REPLACE(RIGHT([MaxUserRegistration], CHARINDEX('/', REVERSE([MaxUserRegistration])) - 1),'_ADMIN','') AS [MaxUserUsername]
          ,dbo.dsm_hardware_basic.[LastUserRegistration]
          ,REPLACE(RIGHT([LastUserRegistration], CHARINDEX('/', REVERSE([LastUserRegistration])) - 1),'_ADMIN','') AS [LastUserUsername]
          ,dbo.dsm_hardware_basic.[IPAddress]
          ,dbo.dsm_hardware_basic.[HostName]
          ,dbo.dsm_hardware_basic.[MACAddress]
 FROM      dbo.dsm_hardware_basic
)

SELECT     TOP 100 PERCENT
           dsm_hardware_basic_cte.[UUID]
          ,dsm_hardware_basic_cte.[Name]
          ,dsm_hardware_basic_cte.[LastAgentExecution]
          ,dsm_hardware_basic_cte.[MaxUserRegistration]
          ,dsm_hardware_basic_cte.[LastUserRegistration]
          ,dsm_hardware_basic_cte.[IPAddress]
          ,dsm_hardware_basic_cte.[HostName]
          ,dsm_hardware_basic_cte.[MACAddress]
FROM       dsm_hardware_basic_cte
           INNER JOIN
           (
            SELECT    [UUID]
                     ,ROW_NUMBER() OVER (PARTITION BY [Name], [MACAddress] ORDER BY [LastAgentExecution] DESC) AS [NameMACRowNum]
            FROM      dsm_hardware_basic_cte
           ) AS duplicate_NameMAC_filtered
             ON duplicate_NameMAC_filtered.[UUID] = dsm_hardware_basic_cte.[UUID]
            AND duplicate_NameMAC_filtered.[NameMACRowNum] = 1
           INNER JOIN
           (
            SELECT    [UUID]
                     ,ROW_NUMBER() OVER (PARTITION BY [Name], [HostName] ORDER BY [LastAgentExecution] DESC) AS [NameHostNameRowNum]
            FROM      dsm_hardware_basic_cte
           ) AS duplicate_NameHostName_filtered
             ON duplicate_NameHostName_filtered.[UUID] = dsm_hardware_basic_cte.[UUID]
            AND duplicate_NameHostName_filtered.[NameHostNameRowNum] = 1
           INNER JOIN
           (
            SELECT    [UUID]
                     ,ROW_NUMBER() OVER (PARTITION BY [HostName], [MACAddress] ORDER BY [LastAgentExecution] DESC) AS [HostNameMACRowNum]
            FROM      dsm_hardware_basic_cte
           ) AS duplicate_HostNameMAC_filtered
             ON duplicate_HostNameMAC_filtered.[UUID] = dsm_hardware_basic_cte.[UUID]
            AND duplicate_HostNameMAC_filtered.[HostNameMACRowNum] = 1
           INNER JOIN
           (
            SELECT    [UUID]
                     ,ROW_NUMBER() OVER (PARTITION BY [HostName], [IPAddress] ORDER BY [LastAgentExecution] DESC) AS [HostNameIPAddressRowNum]
            FROM      dsm_hardware_basic_cte
           ) AS duplicate_HostNameIPAddress_filtered
             ON duplicate_HostNameIPAddress_filtered.[UUID] = dsm_hardware_basic_cte.[UUID]
            AND duplicate_HostNameIPAddress_filtered.[HostNameIPAddressRowNum] = 1
           INNER JOIN
           (
            SELECT    [UUID]
                     ,ROW_NUMBER() OVER (PARTITION BY [Name], [MaxUserUsername] ORDER BY [LastAgentExecution] DESC) AS [NameMaxUserRowNum]
            FROM      dsm_hardware_basic_cte
           ) AS duplicate_NameMaxUser_filtered
             ON duplicate_NameMaxUser_filtered.[UUID] = dsm_hardware_basic_cte.[UUID]
            AND duplicate_NameMaxUser_filtered.[NameMaxUserRowNum] = 1
           INNER JOIN
           (
            SELECT    [UUID]
                     ,ROW_NUMBER() OVER (PARTITION BY [Name], [LastUserUsername] ORDER BY [LastAgentExecution] DESC) AS [NameLastUserRowNum]
            FROM      dsm_hardware_basic_cte
           ) AS duplicate_NameLastUser_filtered
             ON duplicate_NameLastUser_filtered.[UUID] = dsm_hardware_basic_cte.[UUID]
            AND duplicate_NameLastUser_filtered.[NameLastUserRowNum] = 1
4

3 に答える 3

0

内部結合の代わりに、次のような「Exists」句に置き換えてみてください

WHERE      EXISTS           
           ((SELECT [UUID],[NameMACRowNum]
                FROM
                        (SELECT    [UUID]
                                 ,ROW_NUMBER() OVER (PARTITION BY [Name], [MACAddress] ORDER BY [LastAgentExecution] DESC) AS [NameMACRowNum]
                        FROM      dsm_hardware_basic_cte) AS duplicate_NameMAC_filtered
            WHERE duplicate_NameMAC_filtered.[UUID] = dsm_hardware_basic_cte.[UUID]
            AND duplicate_NameMAC_filtered.[NameMACRowNum] = 1)

存在するか存在しないかはわかりませんが、残りが機能したら簡単に変更できます。

于 2012-12-04T06:42:43.453 に答える
0

クエリ プランによると、LastAgentExecution による並べ替えには 19% の時間がかかります。この列にインデックスを作成することから始めます。

ただし、私があなただったら、「ROW_NUMBER() OVER (PARTITION BY [Name], [MACAddress] ORDER BY [LastAgentExecution] DESC)」タイプの構文を使用する習慣を変更します。あまり効果的ではないように思われるからです。

于 2012-12-04T04:58:04.923 に答える
0

あなたのニーズが何であるかはわかりませんが、クエリを次のように書き直してみてください。

WITH dsm_hardware_basic_cte AS (
 SELECT
    d.[UUID]
    ,d.[Name]
    ,d.[LastAgentExecution]
    ,d.[MaxUserRegistration]
    ,REPLACE(RIGHT([MaxUserRegistration], CHARINDEX('/', REVERSE([MaxUserRegistration])) - 1),'_ADMIN','') AS [MaxUserUsername]
    ,d.[LastUserRegistration]
    ,REPLACE(RIGHT([LastUserRegistration], CHARINDEX('/', REVERSE([LastUserRegistration])) - 1),'_ADMIN','') AS [LastUserUsername]
    ,d.[IPAddress]
    ,d.[HostName]
    ,d.[MACAddress]
    ,ROW_NUMBER() OVER (PARTITION BY [Name], [MACAddress] ORDER BY [LastAgentExecution] DESC) AS [NameMACRowNum]
    ,ROW_NUMBER() OVER (PARTITION BY [Name], [HostName] ORDER BY [LastAgentExecution] DESC) AS [NameHostNameRowNum]
    ,ROW_NUMBER() OVER (PARTITION BY [HostName], [MACAddress] ORDER BY [LastAgentExecution] DESC) AS [HostNameMACRowNum]
    ,ROW_NUMBER() OVER (PARTITION BY [HostName], [IPAddress] ORDER BY [LastAgentExecution] DESC) AS [HostNameIPAddressRowNum]
    ,ROW_NUMBER() OVER (PARTITION BY [Name], [MaxUserUsername] ORDER BY [LastAgentExecution] DESC) AS [NameMaxUserRowNum]
    ,ROW_NUMBER() OVER (PARTITION BY [Name], [LastUserUsername] ORDER BY [LastAgentExecution] DESC) AS [NameLastUserRowNum]
 FROM      dbo.dsm_hardware_basic as d
)

SELECT
    c.[UUID]
    ,c.[Name]
    ,c.[LastAgentExecution]
    ,c.[MaxUserRegistration]
    ,c.[LastUserRegistration]
    ,c.[IPAddress]
    ,c.[HostName]
    ,c.[MACAddress]
FROM       dsm_hardware_basic_cte as c
WHERE
    c.[NameMACRowNum] = 1
    or c.[NameHostNameRowNum] = 1
    or c.[HostNameMACRowNum] = 1
    or [HostNameIPAddressRowNum] = 1
    or [NameMaxUserRowNum] = 1
    or [NameLastUserRowNum] = 1

あなたのクエリと私のクエリは論理的に同等だと思います。オプティマイザーはあなたのクエリを私のものに減らすのに十分賢いかもしれませんが、試してみてください! いくつかのメモ:

  1. もう少し読みやすくするために、テーブルエイリアスを使用しました(私の意見では)
  2. あなたの選択から「上位 100 パーセント」句を削除しました。必要ありません。これは通常、ビューで順序付けを行って、「順序付けられたビュー」を取得できるようにするためのハックです。そうしないでください。:)
于 2012-12-04T11:14:20.387 に答える