Moja firma korzysta z aplikacji, która ma dość poważne problemy z wydajnością. Istnieje wiele problemów z samą bazą danych, nad którymi pracuję, ale wiele z nich dotyczy wyłącznie aplikacji.
Podczas mojego dochodzenia odkryłem, że do bazy danych SQL Server trafiają miliony zapytań, które odpytują puste tabele. Mamy około 300 pustych tabel, a niektóre z nich są sprawdzane do 100-200 razy na minutę. Tabele nie mają nic wspólnego z naszym obszarem działalności i są zasadniczo częścią oryginalnej aplikacji, której sprzedawca nie usunął, gdy firma zleciła mi opracowanie rozwiązania programowego dla nas.
Oprócz tego, że podejrzewamy, że nasz dziennik błędów aplikacji jest zalewany błędami związanymi z tym problemem, sprzedawca zapewnia nas, że nie ma wpływu na wydajność ani stabilność ani aplikacji, ani serwera bazy danych. Dziennik błędów jest zalany do tego stopnia, że nie możemy zobaczyć błędów dłuższych niż 2 minuty na wykonanie diagnozy.
Rzeczywisty koszt tych zapytań będzie oczywiście niski pod względem cykli procesora itp. Ale czy ktoś może zasugerować, jaki wpływ miałby na SQL Server i aplikację? Podejrzewam, że sama mechanika wysyłania zapytania, potwierdzania go, przetwarzania, zwracania i potwierdzania odbioru przez aplikację sama w sobie miałaby wpływ na wydajność.
Do aplikacji używamy SQL Server 2008 R2, Oracle Weblogic 11g.
@ Frisbee - Krótko mówiąc, stworzyłem tabelę zawierającą kwerendę, która uderzyła w puste tabele w bazie danych aplikacji, a następnie zapytałem o wszystkie nazwy tablic, które znam puste i mam bardzo długą listę. Największym hitem było wykonanie 2,7 miliona egzekucji w ciągu 30 dni bezawaryjności, mając na uwadze, że aplikacja jest zwykle używana w godzinach 8–18, więc liczby te są bardziej skoncentrowane na godzinach pracy. Wiele tabel, wiele zapytań, pewnie niektóre ponownie powiązane poprzez połączenia, niektóre nie. Największym hitem (w tym czasie 2,7 miliona) był prosty wybór z pojedynczego pustego stołu z klauzulą where, bez łączenia. Spodziewałbym się, że większe zapytania z łączeniami do pustych tabel mogą obejmować aktualizacje połączonych tabel, ale sprawdzę to i zaktualizuję to pytanie jak najszybciej.
Aktualizacja: Istnieje 1000 zapytań o liczbie wykonań od 1043 do 4622614 (ponad 2,5 miesiąca). Będę musiał kopać więcej, aby dowiedzieć się, kiedy pochodzi buforowany plan. Ma to na celu zobrazowanie zakresu zapytań. Większość jest dość skomplikowana z ponad 20 złączeniami.
@ srutzky- tak Wydaje mi się, że istnieje kolumna dat związana z czasem, kiedy plan został opracowany, więc byłoby to interesujące, więc to sprawdzę. Zastanawiam się, czy ograniczenia wątków byłyby w ogóle czynnikiem, gdy SQL Server znajduje się w klastrze VMware? Na szczęście wkrótce będzie dedykowany Dell PE 730xD na szczęście.
@Frisbee - Przepraszamy za spóźnioną odpowiedź. Jak zasugerowałeś, uruchomiłem select * z pustej tabeli 10 000 razy w ciągu 24 wątków za pomocą SQLQueryStress (czyli w rzeczywistości 240 000 iteracji) i natychmiast otrzymałem 10 000 żądań wsadowych / s. Następnie zredukowałem do 1000 razy w ciągu 24 wątków i trafiłem nieco poniżej 4000 żądań partii / s. Próbowałem także 10 000 iteracji tylko na 12 wątkach (czyli 120000 wszystkich iteracji), co dało ciągły wynik 6505 partii / s. Wpływ na procesor był zauważalny, około 5-10% całkowitego zużycia procesora podczas każdego uruchomienia testowego. Oczekiwania sieciowe były znikome (jak 3ms z klientem na mojej stacji roboczej), ale wpływ procesora był na pewno, co jest dość rozstrzygające, jeśli o mnie chodzi. Wydaje się, że sprowadza się to do użycia procesora i trochę niepotrzebnego IO pliku bazy danych. Łączna liczba egzekucji na sekundę wynosi niespełna 3000, co jest więcej niż w produkcji, jednak testuję tylko jedno z kilkudziesięciu takich zapytań. Efekt netto setek zapytań trafiających w puste tabele z szybkością 300–4000 razy na minutę nie byłby zatem nieistotny, jeśli chodzi o czas pracy procesora. Wszystkie testy przeprowadzono na bezczynnym PE 730xD z podwójnym układem pamięci flash i 256 GB pamięci RAM, 12 nowoczesnych rdzeni.
@ srutzky- dobre myślenie. Wygląda na to, że SQLQueryStress domyślnie korzysta z puli połączeń, ale mimo to rzuciłem okiem i stwierdziłem, że tak, pole puli połączeń jest zaznaczone. Zaktualizuj, aby śledzić
@ srutzky- Pule połączeń najwyraźniej nie są włączone w aplikacji - a jeśli tak, to nie działa. Zrobiłem śledzenie profilera i stwierdziłem, że połączenia mają EventSubClass „1 - Nonpooled” dla zdarzeń logowania inspekcji.
RE: Pula połączeń - sprawdzono logikę i znalazłem włączone połączenie połączeń. Sprawdziłem więcej śladów na żywo i znalazłem, że pule nie występują prawidłowo / wcale:
Oto, jak to wygląda, gdy uruchamiam jedno zapytanie bez sprzężeń z zapełnioną tabelą; wyjątki brzmią: „Wystąpił błąd związany z siecią lub specyficzny dla instancji podczas nawiązywania połączenia z programem SQL Server. Serwer nie został znaleziony lub był niedostępny. Sprawdź, czy nazwa instancji jest poprawna i czy program SQL Server jest skonfigurowany tak, aby zezwalał na połączenia zdalne. (dostawca: Dostawca nazwanych potoków, błąd: 40 - Nie można otworzyć połączenia z programem SQL Server) „Zanotuj licznik żądań wsadowych. Pingowanie serwera podczas generowania wyjątków powoduje pomyślną odpowiedź ping.
Aktualizacja - dwa kolejne testy, to samo obciążenie (wybierz * z Pustej tabeli), włączanie / wyłączanie buforowania. Nieco więcej użycia procesora i dużo awarii i nigdy nie przekracza 500 żądań wsadowych na sekundę. Testy wykazują 10 000 partii / s i brak awarii przy włączonym buforowaniu oraz około 400 partii / s, a następnie wiele awarii spowodowanych wyłączeniem puli. Zastanawiam się, czy te awarie są związane z brakiem dostępności połączenia?
@ srutzky- Wybierz Count (*) z sys.dm_exec_connections;
Pula danych włączona: 37 konsekwentnie, nawet po zakończeniu testu obciążenia
Pula wyłączona: 11–37 w zależności od tego, czy wyjątki
występują w SQLQueryStress, tj .: gdy te koryta pojawiają się na
wykresie partii / s, wyjątki występują w SQLQueryStress, a
liczba połączeń spada do 11, a następnie stopniowo wraca do 37 kiedy partie zaczynają osiągać szczyt i wyjątki nie występują. Bardzo, bardzo interesujące.
Maksymalna liczba połączeń w obu instancjach testowych / na żywo ustawiona na wartość domyślną 0.
Sprawdziłem dzienniki aplikacji i nie mogę znaleźć problemów z łącznością, jednak rejestrowanie jest możliwe tylko przez kilka minut ze względu na dużą liczbę i rozmiar błędów, tj .: wiele błędów śledzenia stosu. Kolega z działu obsługi aplikacji informuje, że występuje znaczna liczba błędów HTTP związanych z łącznością. Wydaje się na tej podstawie, że z jakiegoś powodu aplikacja nie tworzy poprawnej puli połączeń, w wyniku czego serwerowi ciągle brakuje połączeń. Przyjrzę się więcej dziennikom aplikacji. Zastanawiam się, czy istnieje sposób na udowodnienie, że dzieje się to w produkcji od strony SQL Servera?
@ srutzky- Dziękuję. Sprawdzę jutro konfigurację weblogiczną i zaktualizuję. Myślałem jednak o zaledwie 37 połączeniach - jeśli SQLQueryStress wykonuje 12 wątków przy 10 000 iteracjach = 120 000 instrukcji select bez puli, czy nie powinno to oznaczać, że każdy wybór tworzy odrębne połączenie z instancją SQL?
@ srutzky- Weblogics są skonfigurowane do pula połączeń, więc powinno działać dobrze. Pula połączeń jest skonfigurowana w następujący sposób na każdej z 4 logik internetowych z równoważeniem obciążenia:
- Początkowa pojemność: 10
- Maksymalna pojemność: 50
- Minimalna pojemność: 5
Gdy zwiększam liczbę wątków wykonujących zapytanie „wybierz z pustej tabeli”, liczba połączeń osiąga wartość szczytową około 47. Przy wyłączonej puli połączeń konsekwentnie widzę niższe maksymalne żądania wsadowe / s (z 10 000 do około 400). Co się stanie za każdym razem, gdy „wyjątki” w SQLQueryStress pojawią się wkrótce po przejściu serii / sek. Ma to związek z łącznością, ale nie mogę zrozumieć, dlaczego tak się dzieje. Gdy nie są uruchomione żadne testy, liczba połączeń spada do około 12.
Przy wyłączonej puli połączeń mam problem ze zrozumieniem, dlaczego występują wyjątki, ale może to zupełnie inny stos. Wymienić pytanie / pytanie dla Adama Machanica?
@srutzky Zastanawiam się więc, dlaczego występują wyjątki bez włączonej puli, nawet jeśli w SQL Server nie brakuje połączeń?
SELECT COUNT(*) FROM sys.dm_exec_connections;
aby sprawdzić, czy wartość różni się znacznie między włączeniem puli lub nie. W oparciu o te błędy, myślę, że byłoby więcej połączeń, gdy pula była wyłączona.Pooling=false
czyMax Pool Size
?Odpowiedzi:
Tak, istnieją nawet dodatkowe czynniki, ale nie można powiedzieć, w jakim stopniu którekolwiek z nich faktycznie wpływają na twój system bez analizy systemu.
To powiedziawszy, pytasz o to, co może być problemem, i jest kilka rzeczy do wspomnienia, nawet jeśli niektóre z nich nie są obecnie czynnikiem w twojej konkretnej sytuacji. Mówisz tak:
Może być nawet więcej, ale to powinno pomóc w zrozumieniu rzeczy. I pamiętaj, że podobnie jak większość problemów z wydajnością, wszystko zależy od skali. Wszystkie wyżej wymienione przedmioty nie są problemami, jeśli zostaną trafione raz na minutę. To jak testowanie zmiany na stacji roboczej lub w bazie danych programowania: zawsze działa tylko z 10 - 100 wierszami w tabelach. Przenieś ten kod do produkcji, a uruchomienie zajmie 10 minut, a ktoś musi powiedzieć: „dobrze, działa na moim pudełku” ;-). Oznacza to, że widzisz problem tylko z powodu samej liczby wykonywanych połączeń, ale taka jest sytuacja.
Zatem nawet przy 1 milionie bezużytecznych zapytań bez wiersza, co stanowi:
utrzymywanych jest więcej połączeń, które zajmują więcej pamięci. Ile masz nieużywanej fizycznej pamięci RAM? pamięć ta byłaby lepiej wykorzystana do uruchamiania zapytań i / lub pamięci podręcznej planu zapytań. Najgorszym przypadkiem jest brak pamięci fizycznej i SQL Server musi zacząć korzystać z pamięci wirtualnej (swap), ponieważ to spowalnia proces (sprawdź dziennik błędów SQL Server, aby zobaczyć, czy otrzymujesz komunikaty o stronicowaniu pamięci).
I na wypadek, gdyby ktoś wspomniał: „cóż, istnieje pula połączeń”. Tak, to zdecydowanie pomaga zmniejszyć liczbę potrzebnych połączeń. Ale przy zapytaniach przychodzących z prędkością do 200 razy na minutę jest to dużo równoczesnych działań i połączenia muszą nadal istnieć w celu uzyskania uzasadnionych żądań. Zrób,
SELECT * FROM sys.dm_exec_connections;
aby zobaczyć, ile utrzymujesz aktywnych połączeń.Jeśli nie mylę się co do tego, co tu mówię, wydaje mi się, że nawet na niewielką skalę jest to rodzaj ataku DDoS na twój system, ponieważ zalewa on sieć i twój SQL Server fałszywymi żądaniami , zapobiegając przedostawaniu się rzeczywistych żądań do SQL Server lub przetwarzaniu przez SQL Server.
źródło
Jeśli stoły trafiają 100-200 razy na minutę, to (miejmy nadzieję) są w pamięci. Obciążenie serwera jest bardzo, bardzo niskie. Chyba że masz wysoki procesor lub pamięć na serwerze bazy danych, prawdopodobnie nie stanowi to problemu.
Tak, zapytania biorą wspólne blokady, ale mam nadzieję, że nie blokują żadnych blokad aktualizacji ani nie są blokowane przez żadną blokadę aktualizacji. Czy masz jakieś aktualizacje, wstawianie lub usuwanie w tych tabelach. Jeśli nie, po prostu odpuszczę - jeśli masz problemy z wydajnością, z perspektywy serwera bazy danych muszą być większe ryby do smażenia.
Przeprowadziłem test na 100 000 wybranych liczników (*) na pustej tabeli i wykonano go w 32 sekundy, a zapytania były przesyłane przez sieć. 1/3 milisekundy. O ile sieć nie zostanie przeciążona, nie ma to nawet wpływu na klienta. Jeśli masz poważne problemy z wydajnością, te 1/3 milisekund puste zapytania nie są przyczyną śmierci aplikacji.
Mogą to być tylko fragmenty lewego łącznika przechwytujące dane statyczne, które nie są częścią bieżącej aplikacji. Można go połączyć z innymi zapytaniami, więc nie jest to dodatkowa podróż w obie strony. Jeśli tak, to jest niechlujny, ale nawet nie powoduje większego ruchu.
Wróćmy więc do faktycznych stwierdzeń. Czy widzisz jakieś aktualizacje, dodania lub usunięcia w tych tabelach?
Tak, wiele pustych tabel i zapytania do pustych tabel wskazują na niechlujne kodowanie. Ale jeśli masz poważne problemy z wydajnością, nie jest to przyczyną, o ile nie wykonujesz naprawdę niechlujnych operacji zapisu przy tych tabelach.
źródło
Ogólnie przy każdym zapytaniu wykonuje się następujące kroki:
wiele zapytań, o których wspomniałeś, może spowodować dodatkowe obciążenie już obciążonego systemu - dodatkowe obciążenie połączeń, procesora, pamięci RAM i operacji we / wy.
źródło