Identyczne (?) Maszyny SQL Server 2005; zapytanie zajmuje 2 sekundy z jednej, 15 minut z drugiej

12

Środowisko:

Mamy dwa 32-bitowe komputery z systemem Windows Server 2003 R2 z programem SQL Server 2005. Konfiguracje sprzętowe to identyczne serwery z procesorem Xeon 5160, 4 GB pamięci RAM i 13 GB RAID0. Flagi AWE i / 3GB nie są włączone.

Serwery zostały skonfigurowane obok siebie przy użyciu wstępnie zdefiniowanej listy kontrolnej instalacji, a WSZYSTKIE zainstalowane oprogramowanie jest takie samo na obu komputerach.

Każde ustawienie instalacji serwera SQL i poziom łaty, które sprawdzamy, są identyczne. Jedną różnicą jest to, że TEMPDB ma 400 MB na szybkiej maszynie i 1,2 GB na wolnej maszynie. Jednak w obu przypadkach nie widzimy żadnej alokacji TEMPDB.

Problem:

Istnieje procedura składowana, która działa w ciągu 2 sekund z jednej, ale 15 minut z drugiej. W ciągu dodatkowych 15 minut aktywność dysku jest niewielka lub nie ma żadnych zmian w zużyciu pamięci, ale cały rdzeń procesora jest przypięty w 100%.

To zachowanie utrzymuje się, nawet gdy kopie zapasowe baz danych są przechowywane z jednej bazy danych i przywracane do drugiej.

Ponieważ jest to procedura przechowywana, monitor aktywności i profiler nie pokazują nam żadnych szczegółów na temat tego, gdzie w procedurze przechowywanej zachodzi ta wysoka aktywność procesora.

Pytanie:

Na co jeszcze powinniśmy patrzeć?

Kontynuacja:

Powolność występuje w instrukcjach FETCH NEXT dla następującej definicji kursora:

DECLARE C CURSOR FOR
    SELECT X, Y
    FROM dbo.A
    WHERE X NOT IN (SELECT X FROM dbo.B)
    AND Z <=0
...
<snip>
...
FETCH NEXT FROM C INTO @X, @Y
FETCH NEXT FROM C INTO @X, @Y
...

Każda z instrukcji FETCH - w tabeli zawierającej tylko około 1000 wierszy - wymaga około 7,25 minut. (Nie, nie wiem, dlaczego robi dwa z rzędu, muszę zapytać programistów, ale działa poprawnie na obu serwerach).

Jestem trochę podejrzliwy wobec tego „NOT IN (SELECT ...)”, ponieważ wygląda na to, że Virtual Reads jest naprawdę wysoki.

ryandenki
źródło
W jaki sposób rekordy w dbo.B mogą być indeksowane?
Mark Storey-Smith
1
jestem ciekawy, czy byłaby różnica wydajności, gdybyś poszedł z tym: wybierz dbo.ax, dbo.ay z dbo.a lewe zewnętrzne połączenie dbo.b na dbo.ax = dbo.bx, gdzie dbo.bx ma wartość null i z <= 0
DForck42
Jeszcze jedna myśl, aby wrzucić tę mieszankę. Czy jesteś pewien, że spowolnienie wynika z pobierania kursora? Czy określasz to na podstawie planu wykonania (który dotyczy szacunków), czy na podstawie profilu śledzenia?
Mark Storey-Smith
To ze śladu profilu.
ryandenki
Czy plany wykonania są takie same? Możliwe, że jeden z nich używa złego planu wykonania.
Zane,

Odpowiedzi:

7

Używając metodologii rozwiązywania problemów z wydajnością, takich jak oczekiwania i kolejki, określ przyczynę wysokiego zużycia procesora, po zidentyfikowaniu wąskiego gardła można zalecić odpowiednie działanie.

Remus Rusanu
źródło
6

SQL Server wybiera inny plan w drugim polu.

Przywracanie zazwyczaj usuwa problemy na podstawie statystyk, więc przyjrzałbym się różnicom między serwerami.

Najpierw niektóre zgrubne kontrole. Nie zakładaj: sprawdź

  • Sprawdź, czy ustawienia SQL Server są takie same w konfiguracji sys.configuracji, np. Maksymalny stopień lub równoległość
  • Uruchom DBCC USEROPTIONS, aby sprawdzić, czy jakieś ustawienia ANSI różnią się w czasie wykonywania (ustawienia ANS mogą mieć wpływ na wybrany plan)
  • Sprawdź dzienniki Windows i SQL Server, aby sprawdzić, czy występują jakieś problemy

Następnie przeskocz na głęboki koniec, zgodnie z odpowiedzią Remusa.

gbn
źródło
Dzięki za podpowiedzi. Zarówno konfiguracje sys.config, jak i DBCC USEROPTIONS są identyczne dla obu maszyn. Brak błędów lub ostrzeżeń w dziennikach serwera Windows lub SQL.
1
Czy działają również identyczny układ bazy danych? Nie masz planu administratora do optymalizacji na (przebudowa indeksu itp.), Bazy danych mają takie same statystyki dla odpowiednich obiektów i taki sam układ dysku? Ten sam poziom łatki?
TomTom,
Tak, ten sam dysk, układ DB i poziom poprawek. W rzeczywistości baza danych na szybkim komputerze jest przywróconą kopią zapasową z powolnego komputera. I o ile mi wiadomo, nie ma planów administracyjnych, które by się różniły.
ryandenki
6

Jeśli wszystkie inne rzeczy są sobie równe, jest prawdopodobne (zgodnie z odpowiedzią @ gbn), że na każdym serwerze generowany jest inny plan wykonania. Jako ćwiczenie akademickie byłoby interesujące zobaczyć oba plany, więc pobierz je z pamięci podręcznej planu na każdym serwerze i dodaj je do pytania, jeśli to możliwe. Następnie możemy zidentyfikować różnice w planach, które powodują tak duże zróżnicowanie wydajności.

Aby uzyskać szybką poprawkę, zapoznaj się ze wskazówką USE PLAN . Umożliwia to dołączenie dobrego planu z szybkiego serwera do procedury przechowywanej na wolnym serwerze.

Edycja: Po aktualizacji do: kursor

Jeszcze jedna odmiana zapytania, której nie widzę w innych odpowiedziach:

DECLARE C CURSOR FOR
    SELECT X, Y
    FROM dbo.A
    WHERE NOT EXISTS (SELECT 1 FROM dbo.B WHERE dbo.B.X = dbo.A.X)
    AND Z <=0
...
<snip>
...
FETCH NEXT FROM C INTO @X, @Y
FETCH NEXT FROM C INTO @X, @Y
Mark Storey-Smith
źródło
To dobra rada, sprawdzamy plany zapytań. W rzeczywistości spowolnienie procedury przechowywanej wydaje się być powiązane z kursorem. Zobacz edycję.
ryandenki
4

Humor mnie i spróbuj zastąpić:

DECLARE C CURSOR FOR
SELECT X, Y
FROM dbo.A
WHERE X NOT IN (SELECT X FROM dbo.B)
AND Z <=0

z tym:

DECLARE C CURSOR FOR
SELECT 
    X, 
    Y
FROM dbo.A

    LEFT OUTER JOIN dbo.B
        ON dbo.A.X = dbo.b.X

WHERE dbo.B.X IS NULL
AND Z <=0

Nie sądzę, że powinno to objawiać się jako problem z wydajnością w części FETCH NEXT FROM twojego kodu, ale nie miałem jeszcze zastrzyku kofeiny. Wypróbuj moją sugestię i daj mi znać.

Mam nadzieję że to pomoże,

Matt

Matt M.
źródło
4

Sprawdź swoje indeksy i zaktualizuj wszystkie statystyki. Miałem bardzo podobny problem i okazało się, że statystyki na jednej maszynie były niepewne.

DForck42
źródło
1

Dwukrotnie doświadczyłem tego samego zachowania i za każdym razem powiem ci, co to naprawiło:

1.) Dodałem podpowiedź Z RECOMPILE do procedury składowanej, ponieważ buforowany plan był okropny.

2.) Zmieniłem procedurę przechowywaną, aby używała tabel tymczasowych zamiast zmiennych tabel.

Mam nadzieję, że któraś z nich pomoże. Powodzenia.

Jon
źródło