Domanda

sto usando Sybase 12.5.3 (ASE) ; Sono nuovo di Sybase anche se ho lavorato con MSSQL abbastanza ampiamente. Sono in esecuzione in uno scenario in cui una stored procedure è davvero molto lento. Ho rintracciato la questione ad un unico stmt SELEZIONA per un tempo relativamente grande tavolo. Modifica questa affermazione migliora notevolmente le prestazioni della procedura (e ritornando drasticamente lo rallenta, vale a dire, la stmt SELECT è sicuramente il colpevole).

-- Sybase optimizes and uses multi-column index... fast!<br>
SELECT ID,status,dateTime
FROM myTable
WHERE status in ('NEW','SENT')
ORDER BY ID

-- Sybase does not use index and does very slow table scan<br>
SELECT ID,status,dateTime
FROM myTable
WHERE status in (select status from allowableStatusValues)
ORDER BY ID

Il codice sopra è una versione adattata / semplificato del codice effettivo. Si noti che ho già provato ricompilare la procedura, l'aggiornamento delle statistiche, ecc.

Non ho idea del motivo per cui Sybase ASE avrebbe scelto un indice solo quando le stringhe sono hard-coded e scegliere una scansione di tabella per la scelta da un'altra tabella. Qualcuno per favore mi dia un indizio, e vi ringrazio in anticipo.

È stato utile?

Soluzione

problema 1. qui è povera di codifica. Nel vostro comunicato, povero codice e cattiva progettazione tavolo sono le ragioni principali (98%) l'ottimizzatore prende decisioni errate (le due vanno di pari passo, non ho capito la proporzione di ciascuno). Entrambi:

    WHERE status IN ('NEW','SENT')

e

    WHERE status IN (SELECT status FROM allowableStatusValues)

sono scadente, perché in entrambi i casi che provocano ASE per creare un piano di lavoro per i contenuti tra le parentesi, che possono essere facilmente evitati (e tutti i problemi conseguenti evitati con esso). Non v'è alcuna possibilità di statistiche su un piano di lavoro, dal momento che le statistiche su entrambi t.status o s.status manca (AdamH è corretto re quel punto), si sceglie correttamente una scansione di tabella.

Sottointerrogazioni hanno il loro posto, ma mai come sostituto di una pura (le tabelle sono legati) si uniscono. Le correzioni sono:

    WHERE status = "NEW" OR status = "SENT"

e

    FROM  myTable t,
          allowableStatusValues s
    WHERE t.status = s.status

dichiarazione 2.

|. Ora non c'è bisogno di aggiungere un indice per ottenere statistiche su una colonna, ma E 'probabilmente il modo migliore

non è corretto. Non creare indici che non utilizzerà. Se si desidera che le statistiche aggiornate su una colonna, semplicemente

    UPDATE STATISTICS myTable (status)

3.It è importante assicurarsi di avere statistiche aggiornate sulle (a) tutte le colonne indicizzate e (b) tutti si riuniscono colonne.

4.Yes, non v'è alcun sostituto per SHOWPLAN su ogni segmento di codice che è destinato per il rilascio, doppiamente così per qualsiasi codice con prestazioni discutibili. È inoltre possibile SET NOEXEC ON, per evitare l'esecuzione, ad esempio. per i grandi insiemi di risultati.

Altri suggerimenti

Un hint per l'indice funziona intorno ad esso, ma probabilmente non è la soluzione.

In primo luogo mi piacerebbe sapere se c'è un indice su allowableStatusValues.status, se non v'è quindi Sybase avrà statistiche su di esso e avrà una buona idea sul numero dei valori in là. Se poi non l'ottimizzatore probabilmente non avrà una buona idea di quanti differenti valori di stato può assumere. E 'poi dover fare l'ipotesi che si sta andando ad essere l'estrazione di quasi tutte le righe da myTable, e il modo migliore per farlo è una scansione di tabella (se non indice di copertura).

Ora non c'è bisogno di aggiungere un indice per ottenere statistiche su una colonna, ma è probabilmente il modo migliore.

Se si dispone di un indice su allowableStatusValues.status, poi mi chiedo quanto bene le statistiche sono. Procuratevi una copia di sp__optdiag . Probabilmente anche bisogno di regolare i valori del "fattore istogramma tuning" e "numero di passi di istogramma", aumentando leggermente da questi valori predefiniti vi darà statistiche più dettagliate che aiuta sempre l'ottimizzatore.

Ha ancora fare una scansione di tabella se si sostituisce il subquery con un join:

SELECT m.ID,m.status,m.dateTime 
FROM myTable m
JOIN allowableStatusValues a on m.status = a.status
ORDER BY ID 

Piuttosto che basarsi su osservazioni sperimentali di quanto tempo una query richiede per funzionare, mi raccomando ottenere Sybase visualizzare i piani di esecuzione per ogni query, ad esempio:

SET showplan ON
GO

-- query/procedure call goes here
SELECT id, status, datetime
FROM myTable
WHERE status IN('NEW','SENT')
ORDER BY id
GO

SET showplan OFF
GO

Con SET showplan ON, Sybase genera piani di esecuzione per ogni istruzione viene eseguita. Questi possono essere prezioso per aiutare a identificare dove le query non stanno facendo uso di indici appropriati. Per stored procedure Sybase, il piano di esecuzione per l'intera procedura viene generato quando la stored procedure viene prima eseguito dopo essere compilato.

Se pubblichi i piani per ciascuna delle vostre domande potremmo essere in grado di far luce sul problema.

Sorprendentemente, utilizzando un index suggerimento risolve il problema (si veda la (indice myIndexName) riga sotto - riscritto / code simplififed di seguito:

-- using INDEX HINT
SELECT ID,status,dateTime 
FROM myTable (index myIndexName)
WHERE status in (select status from allowableStatusValues) 
ORDER BY ID 

Strano che sono per utilizzare questa tecnica per evitare una scansione di tabella, ma ci ya go.

Garrett, mostrando solo il codice semplificato, probabilmente avete spogliato esattamente le informazioni che sarebbero illuminare la fonte del problema.

La mia prima risposta sarebbe un tipo di mancata corrispondenza tra allowableStatusValues.status e myTable.status. Tuttavia, questo non è l'unica possibilità. Come ninesided detto, i piani completi di query (utilizzando bandiere Showplan e FMTONLY), così come le definizioni di tabella effettivi e fonte di stored procedure, è molto più probabile per produrre una risposta utile.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top