Ottimizzazione statement SQL

di il
5 risposte

Ottimizzazione statement SQL

Sto facendo refactoring di una applicazone Web API.
Come DBMS usa Sql Server e come Entity Framewotk dapper.
Ho la necessità di ottimizzare il seguente spezzone di codice ;

  var result = await sqlConnection.QueryAsync<ProviderAccessLog>(@"
               SELECT Id, PaymentProviderType, UserId, TimeStamp, EventType, RequestType, Url, PaymentProviderTransactionId, TransactionId, Request, Response, ElapsedTime
               FROM ProviderAccessLog
               WHERE (0=@FilterTimeStampFrom OR TimeStamp >= @TimeStampFrom)
                   AND (0=@FilterTimeStampUntil OR TimeStamp <= @TimeStampUntil)
                   AND (0=@FilterTransactionId OR TransactionId = @TransactionId)
                   AND (0=@FilterPaymentProviderType OR PaymentProviderType = @PaymentProviderType)
                   AND (0=@FilterPaymentProviderTransactionId OR PaymentProviderTransactionId = @PaymentProviderTransactionId)
                   AND (0=@FilterUserId OR UserId = @UserId)
                   AND (0=@FilterEventType OR EventType = @EventType)
                   AND (0=@FilterRequestType OR RequestType = @RequestType)
                   AND (0=@FilterRequest OR Request LIKE CONCAT('%',@Request,'%'))
                   AND (0=@FilterResponse OR Response LIKE CONCAT('%',@Response,'%'))
               ORDER BY TimeStamp DESC
               OFFSET ((@PaginationOffset-1) * @PaginationLimit) ROWS
               FETCH NEXT @PaginationLimit ROWS ONLY;", filter);

Può essere utile mostrarvi la struttura della tabella :

USE [cashier]
GO
/****** Object:  Table [dbo].[ProviderAccessLog]    Script Date: 12/15/2022 8:59:33 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[ProviderAccessLog](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[PaymentProviderType] [int] NULL,
[UserId] [bigint] NULL,
[TimeStamp] [datetime2](0) NULL,
[EventType] [int] NULL,
[RequestType] [int] NULL,
[Url] [nvarchar](1000) NULL,
[PaymentProviderTransactionId] [nvarchar](50) NULL,
[TransactionId] [nvarchar](100) NULL,
[Request] [nvarchar](max) NULL,
[Response] [nvarchar](max) NULL,
[ElapsedTime] [int] NULL,
CONSTRAINT [PK_ProviderAccessLog] PRIMARY KEY CLUSTERED 
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

Man mano che la tabella “cresce” la lettura, anche se filtrata, p sempre  più lenta.

Potete darmi qualchhe prezioso suggerimento?
Simone

5 Risposte

  • Re: Ottimizzazione statement SQL

    Salve,

    scrivi di usare Dapper….
    in questo caso, io approfitterei per eliminare, nella costruzione del SQL dinamico e laddove NON utilizzati, tutti i

    > AND (0=@param OR xxx <= @param)

    questo modo di formulare i filtri di WHERE purtroppo penalizza molto i piani generati…

    poi, ovviamente, 
    > LIKE CONCAT('%',@Response,'%'))
    non produce un'espressione sargabale, dove invece 
    LIKE CONCAT(@Response,'%'))
    lo e', ma e' anche diverso il criterio di filtro del dominio…

    salutoni romagnoli
    – 
    Andrea

  • Re: Ottimizzazione statement SQL

    15/12/2022 - asql ha scritto:

    Salve,

    scrivi di usare Dapper….
    in questo caso, io approfitterei per eliminare, nella costruzione del SQL dinamico e laddove NON utilizzati, tutti i

    > AND (0=@param OR xxx <= @param)

    questo modo di formulare i filtri di WHERE purtroppo penalizza molto i piani generati…

    poi, ovviamente, 
    > LIKE CONCAT('%',@Response,'%'))
    non produce un'espressione sargabale, dove invece 
    LIKE CONCAT(@Response,'%'))
    lo e', ma e' anche diverso il criterio di filtro del dominio…

    salutoni romagnoli
    – 
    Andrea

    Ciao,
    grazie per la risposta. Potresti  gentilmente riformulare le prime due/tre righe del where ?

    Grazie mille dal mantovano.
    Simone

  • Re: Ottimizzazione statement SQL

    Salve Simone,

    semplicemente, visto che parliamo di SQL dinamico, imposterei il filtro di WHERE solamente per le espressioni “definite”…
    se NON hai valorizzazione per @TimeStampFrom, allora lo salterei direttamente…

     WHERE (0=@FilterTimeStampFrom OR TimeStamp >= @TimeStampFrom)
           AND (0=@FilterTimeStampUntil OR TimeStamp <= @TimeStampUntil)
           ...

    ad esempio, se abbiamo SOLO la valorizzazione di @TimeStampUntil,  scriverei

     WHERE 1 = 1
        -- NON ho @TimeStampFrom, salto
        AND (TimeStamp <= @TimeStampUntil)
        .... -- solo altro parametro "valorizzato"
        

    in questo modo l'optimizer riesce sicuramente a fare un lavoro migliore…

    salutoni romagnoli,
    – 
    Andrea

  • Re: Ottimizzazione statement SQL

    In buona sostanza componiamo lo statement sql prima di darlo in pasto a dapper con solo le clausole necessare.

    OK?
    SImo

  • Re: Ottimizzazione statement SQL

    Salve Simone,

    si, io proverei cosi'.

    salutoni romagnoli,
    – 
    Andrea

Devi accedere o registrarti per scrivere nel forum
5 risposte