Czy wykorzystanie procesora wpływa na koszt zagranicznego dostępu NUMA?

21

Scenariusz

Załóżmy, że mam SQL Server z 4 gniazdami z każdym 1 węzłem NUMA. Każde gniazdo ma 4 rdzenie fizyczne. Łącznie jest 512 GB pamięci, więc każdy węzeł NUMA ma 128 GB pamięci RAM.

Tabela kluczy jest ładowana do pierwszego węzła NUMA.

Pytanie

Załóżmy, że mamy duży odczyt ruchu z tej tabeli. Jeśli wszystkie fizyczne rdzenie gniazda, które jest właścicielem węzła NUMA, w 100% wykorzystują procesor, czy to negatywnie wpływa na koszt nielokalnego dostępu NUMA pochodzącego z innych gniazd? Albo z drugiej strony, czy koszt nielokalnego dostępu do NUMA jest niezależny od tego, jak zajęte jest to gniazdo?

Mam nadzieję, że moje pytanie ma sens. Daj mi znać, jeśli nie, postaram się wyjaśnić.

tło

W ubiegłym tygodniu mieliśmy problem z bazą danych na naszym serwerze produkcyjnym, a niektóre z przetwarzanych przez nas firm wyglądały na bardziej dotknięte niż inne. Mieliśmy zapytania z kilkoma logicznymi odczytami, które trwały dłużej niż 1 minutę. Przyjrzeliśmy się całkowitemu wykorzystaniu procesora, które wyniosło około 60 procent. Nie przyjrzeliśmy się charakterystyce procesora specyficznej dla gniazd. Dane we / wy były średnie.

Xav
źródło
Jeśli możesz wyprodukować coś, o czym wspomniał Kin, będzie to pomocne. Ponadto, na co ustawiłeś MAXDOP?
user41207,

Odpowiedzi:

18

Ogromne pytanie :-) Przedstawię niektóre z czynników. W dowolnym kontekście czynniki te i inne mogą się różnić i dać interesujący wynik.

Przepraszam, że nie byłem w stanie uczynić tego o wiele krótszym ...

  1. Accumuated CPU ms vs logical IO
  2. Wyrównanie węzłów logicznej pamięci SQL Server z fizycznymi węzłami NUMA
  3. Spór o blokadę w alokacji pamięci obszaru roboczego zapytania
  4. Przypisanie zadań do harmonogramów
  5. Odpowiednie umieszczenie danych w puli buforów
  6. Umieszczenie pamięci fizycznej

  1. Accumuated CPU ms vs logical IO

    Bardzo często używam wykresów logicznego We / Wy (lub w terminologii perfmon „wyszukiwania stron puli buforów”) w stosunku do wykorzystania procesora, aby zmierzyć wydajność procesorów obciążeń i poszukać przypadków podatnych na spinlock.

    Ale SQL Server kumuluje czas procesora przy dużej aktywności innej niż wyszukiwanie stron i blokady:

    • Plany są kompilowane i ponownie kompilowane.
    • Kod CLR jest wykonywany.
    • Funkcje są wykonywane.

    Wiele innych działań pochłonie znaczny czas procesora bez odzwierciedlenia w wyszukiwaniu strony.

    W obserwowanych przeze mnie obciążeniach głównym spośród tych „nielogicznych operacji intensywnie korzystających z IO, ale pochłaniających CPU” jest sortowanie / mieszanie.

    Ma rację: rozważ wymyślony przykład dwóch zapytań przeciwko tablicy hashującej bez indeksów nieklastrowanych. Dwa zapytania mają identyczne zestawy wyników, ale jeden z zestawów wyników jest całkowicie nieuporządkowany, a drugi zestaw wyników jest uporządkowany według więcej niż jednej wybranej kolumny. Oczekuje się, że drugie zapytanie zużyje więcej czasu procesora, nawet jeśli odwołuje się do tej samej liczby stron w puli buforów.

    Więcej informacji o pamięci obszaru roboczego i ilości wykorzystanego przyznanego obszaru roboczego w tych postach:


  1. Wyrównanie węzłów logicznej pamięci SQL Server z fizycznymi węzłami NUMA

    SQL Server (od momentu włączenia strategii obsługujących NUMA) domyślnie tworzy węzeł pamięci SQLOS dla każdego węzła NUMA na serwerze. W miarę wzrostu przydziałów pamięci każdy przydział jest kontrolowany przez jeden z węzłów pamięci SQLOS.

    Idealnie, węzły pamięci SQLOS są całkowicie wyrównane z fizycznymi węzłami NUMA. Oznacza to, że każdy węzeł pamięci SQLOS zawiera pamięć z pojedynczego węzła NUMA, przy czym żaden inny węzeł pamięci SQLOS nie zawiera również pamięci z tego samego węzła NUMA.

    Jednak nie zawsze jest tak idealna sytuacja.

    Poniższy post na blogu CSS SQL Server Engineers (również uwzględniony w odpowiedzi Kin) szczegółowo opisuje zachowanie, które może prowadzić do utrzymywania się alokacji pamięci między węzłami NUMA dla węzłów pamięci SQLOS. Gdy tak się dzieje, wpływ na wydajność może być katastrofalny.

    Wprowadzono kilka poprawek dla szczególnie bolesnego przypadku uporczywego odwołania do węzła krzyżowego NUMA. Prawdopodobnie oprócz tych dwóch również:


  1. Rywalizacja o blokadę podczas przydzielania pamięci obszaru roboczego

    Tutaj zaczyna się dobrze bawić. Opisałem już, że praca sortowania i mieszania w pamięci obszaru roboczego zużywa procesor, ale nie znajduje odzwierciedlenia w liczbach wyszukiwania bpool.

    Spór o blokadę to kolejna warstwa tej szczególnej zabawy. Gdy pamięć zostanie skradziona z puli buforów i przydzielona do użycia z przyznaniem pamięci zapytania, dostęp do pamięci jest szeregowany za pomocą blokady. Domyślnie dzieje się tak z zasobem podzielonym na partycje na poziomie węzła NUMA. Tak więc każde zapytanie w tym samym węźle NUMA korzystającym z pamięci obszaru roboczego może potencjalnie doświadczyć rywalizacji o blokadę podczas kradzieży pamięci przeciwko grantom. Bardzo ważne, aby pamiętać: nie jest to ryzyko rywalizacji „jeden raz na zapytanie”, tak jak byłoby, gdyby punkt rywalizacji był w momencie faktycznego przyznania. Raczej jest, gdy pamięć zostaje skradziona w stosunku do grantu - więc zapytanie z bardzo dużym przydziałem pamięci będzie miało wiele możliwości rywalizacji o spinlock, jeśli wykorzysta większość grantu.

    Flaga śledzenia 8048 ma świetną robotę w łagodzeniu tego sporu poprzez dalsze dzielenie zasobu na poziomie podstawowym.

    Microsoft mówi „rozważ flagę śledzenia 8048, jeśli 8 lub więcej rdzeni na gniazdo”. Ale ... tak naprawdę nie chodzi o liczbę rdzeni na gniazdo (o ile jest ich wiele), ale raczej o liczbę okazji do rywalizacji w pracy wykonywanej na jednym węźle NUMA.

    Na przyklejonych procesorach AMD (12 rdzeni na gniazdo, 2 węzły NUMA na gniazdo) było 6 rdzeni na węzeł NUMA. Widziałem system z 4 tymi procesorami (czyli osiem węzłów NUMA, każdy po 6 rdzeni), który został zablokowany w konwoju spinlocka do momentu włączenia flagi śledzenia 8048.

    Widziałem tę rywalizację o spinlock zmniejszającą wydajność na maszynach wirtualnych tak małych jak 4 vCPU. Flaga śledzenia 8048 działała tak, jak powinna, gdy była włączona w tych systemach.

    Biorąc pod uwagę, że istnieją jeszcze jakieś 4 procesory o zoptymalizowanej częstotliwości rdzeniowej, przy odpowiednim obciążeniu, skorzystaliby również z flagi śledzenia 8048.

    CMEMTHREAD czeka wraz z typem sporu o blokadę, który łagodzi flagę śledzenia 8048. Ale słowo ostrzeżenia: CMEMTHREAD czeka, co potwierdza, a nie jest podstawową przyczyną tego konkretnego problemu. Widziałem systemy z dużymi „początkami oczekiwania” CMEMTHREAD, w których flaga śledzenia 8048 i / lub 9024 były opóźnione we wdrożeniu, ponieważ skumulowany czas oczekiwania CMEMTHREAD był dość krótki. W przypadku spinlocków skumulowany czas oczekiwania jest zwykle niewłaściwy. Zamiast tego chcesz spojrzeć na zmarnowany czas procesora - reprezentowany głównie przez same spiny, a następnie przez powiązane oczekiwania, które reprezentują potencjalnie niepotrzebne przełączniki kontekstu.


  1. Przypisanie zadań do harmonogramów

    W systemach NUMA połączenia są dystrybuowane do węzłów NUMA (cóż - właściwie do powiązanych z nimi grup harmonogramu SQLOS), przy założeniu, że nie ma punktów końcowych połączeń powiązanych z poszczególnymi węzłami NUMA. Jeśli sesja wykonuje zapytanie równoległe, istnieje silna preferencja do używania pracowników z jednego węzła NUMA. Hmmm ... rozważ serwer 4 węzłów NUMA ze złożonym zapytaniem podzielonym na 4 ścieżki i domyślnie 0 MAXDOP. Nawet jeśli zapytanie użyje tylko wątków roboczych MAXDOP, dla każdego logicznego procesora w węźle NUMA będą 4 wątki robocze. Ale w złożonym planie są 4 ścieżki - więc każdy logiczny procesor w węźle NUMA może mieć 16 pracowników - wszystko na jedno zapytanie!

    Dlatego czasami widzisz jeden węzeł NUMA, który ciężko pracuje, podczas gdy inne są próżnujące.

    Istnieje kilka innych niuansów w przypisywaniu zadań. Ale główną zaletą jest to, że procesor zajęty niekoniecznie musi być równomiernie rozłożony na węzły NUMA. (Warto również zdawać sobie sprawę, że wstawki stron bpool (odczyty lub zapisy na pierwszej stronie) trafią do puli w węźle pamięci SQLOS skojarzonym z harmonogramem, na którym działa pracownik. A skradzione strony będą pochodzić z „lokalnej” pamięci SQLOS węzeł też.

    Przekonałem się, że zwiększenie maxdop od 0 do nie więcej niż 8 jest pomocne. W zależności od profilu obciążenia (głównie imo na podstawie liczby oczekiwanych równoległych zapytań potencjalnie długo działających), przejście do MAXDOP = 2 może być uzasadnione.

    Pomocne może być również dostosowanie progu kosztów dla równoległości. Systemy, na których pracuję, są zwykle obciążone wysokimi kosztami i rzadko spotykam się z planem poniżej 50 lub 100, więc miałem większą przyczepność, dostosowując maxdop (często na poziomie grupy obciążenia) niż dostosowując próg kosztów.


  1. Odpowiednie umieszczanie danych w puli

    Jest to warunek, który moim zdaniem jest najbardziej intuicyjny w przypadku serwerów NUMA. Zazwyczaj nie jest to szczególnie istotne dla wydajności obciążenia.

    Co się stanie, jeśli tabela zostanie wczytana do puli w węźle NUMA 3, a później zapytanie w węźle NUMA 4 skanuje tabelę, wykonując wszystkie wyszukiwania puli w węzłach NUMA?

    Linchi Shea ma świetny post na temat tego wpływu na wydajność:

    Dostęp do pamięci w węzłach NUMA wiąże się z niewielkim dodatkowym opóźnieniem pamięci. Jestem pewien, że istnieją pewne obciążenia, które muszą wyeliminować to dodatkowe opóźnienie pamięci podstawowej w celu uzyskania optymalnej wydajności - nie było to problemem w systemach, z którymi pracuję.

    Ale - dostęp między węzłami zapewnia również inny punkt transferu, który może potencjalnie zostać nasycony. Jeśli aktywność jest tak duża, że ​​przepustowość pamięci między węzłami NUMA jest nasycona, opóźnienie pamięci między węzłami wzrośnie. Ta sama praca będzie wymagała dodatkowych cykli procesora.

    Znowu - jestem pewien, że istnieją takie obciążenia, że ​​przepustowość pamięci ma kluczowe znaczenie. Jednak w przypadku moich systemów inne rozważania, które wymieniam, były bardziej znaczące.


  1. Umieszczenie pamięci fizycznej

    Ten jest rzadki, ale kiedy ma znaczenie, naprawdę ma znaczenie. Na większości serwerów instalacja pamięci prawie naturalnie równoważy wszystkie węzły NUMA. Ale w niektórych przypadkach należy zachować szczególną ostrożność w celu zrównoważenia pamięci w węzłach. Wydajność w niektórych systemach może zostać całkowicie zmarnowana, jeśli pamięć została tak rozmieszczona, że ​​nie jest zrównoważona. Jest to jednak ustawione i zapomnij. Dość rzadkie jest wykrycie takiego problemu po miesiącach pracy w produkcji, a nie po pierwszym naprawdę pracowitym dniu :-)


WIELKIE WYKOŃCZENIE!

Ktoś inny zauważył, że zły wybór planu, być może z powodu nieaktualnych statystyk, może powodować objawy, które widziałeś. Z mojego doświadczenia tak nie było. Złe plany mogą sprawić, że zapytanie zajmie więcej czasu niż oczekiwano - ale zwykle dlatego, że wykonywane są bardziej logiczne operacje wejścia / wyjścia niż to konieczne. Lub z powodu wycieku do tempdb. Ogromny wyciek do tempdb powinien być widoczny podczas obserwowania serwera - i zamiast wysokiego procesora można oczekiwać mierzalnego czasu oczekiwania na zapis dysku związany z wyciekami.

Zamiast tego, jeśli obserwowana przez ciebie sytuacja jest związana z NUMA, spodziewam się, że będzie to kombinacja czynników wymienionych powyżej, głównie:

  1. wykorzystanie pamięci obszaru roboczego (która nie pojawi się w logicznych liczbach operacji we / wy)

  2. który może być węzłem krzyżowym NUMA z powodu trwałego stanu pamięci obcej (w takim przypadku poszukaj odpowiednich poprawek)

  3. i które mogą pociągać za sobą spór o blokadę w węźle NUMA za każdym razem, gdy dokonywany jest przydział dla dotacji (poprawka w T8048)

  4. i mogą być wykonywane przez pracowników na logicznych procesorach przeciążonych przez innych równoległych pracowników zapytania (w razie potrzeby dostosuj maxdop i / lub próg kosztu równoległości)

uchwyt sql
źródło
7

( zaktualizuj swoje pytanie o coreinfo -vdane wyjściowe (narzędzie sysinternal), aby uzyskać lepszy kontekst procesora / gniazd i dystrybucji NUMA )

Przyjrzeliśmy się całkowitemu wykorzystaniu procesora, które wyniosło około 60 procent. Nie przyjrzeliśmy się charakterystyce procesora specyficznej dla gniazd. Dane we / wy były średnie.

Wydaje mi się, że szczekasz na niewłaściwe drzewo. SQL Server jest NUMAświadomy. Jest znacznie mniejszy spadek wydajności za dostęp do pamięci krzyżowej NUMA . Możesz również użyć tego zapytania, aby zobaczyć, ile NUMAmasz węzłów i do których procesorów i rdzeni są przypisane NUMA:

SELECT parent_node_id, scheduler_id, cpu_id
FROM sys.dm_os_schedulers WITH (NOLOCK) 
WHERE [status] = N'VISIBLE ONLINE';

Lub po prostu ile NUMA:

select COUNT(distinct Parent_node_id)
from sys.dm_os_schedulers
where [STATUS] = 'VISIBLE ONLINE'
    and Parent_node_ID < 64

Mieliśmy zapytania z kilkoma logicznymi odczytami, które trwały dłużej niż 1 minutę.

Zwykle dzieje się tak, gdy generowane są złe plany zapytań z powodu nieaktualnych statystyk. Upewnij się, że masz zaktualizowane statystyki, a indeksy są poprawnie defragmentowane .

Musisz także ustawić MAXDOP na bardziej rozsądną wartość, aby uniknąć głodu wątków roboczych .

Ustaw cost threshold of parallelismdomyślną wartość 5 na dobrą wartość początkową, taką jak 45, a następnie monitoruj tę wartość i dostosuj ją do swojego środowiska.

Jeśli wykonujesz wiele zapytań adhoc, włącz (ustaw na 1), optimize for ad hoc workloadsaby zapobiec rozdęciu pamięci podręcznej planu.

Używaj ostrożnie: możesz używać T8048, jeśli korzystasz z SQL Server 2008/2008 R2 na nowszych komputerach z prezentacją więcej niż 8 procesorów na węzeł NUMA, a jeśli korzystasz z SQL Server 2012 lub 2014, istnieje poprawka .

Zdecydowanie zalecamy rozpoczęcie zbierania informacji o statystykach Wait dotyczących instancji serwera bazy danych.

Patrz: Jak to działa: SQL Server (bloki pamięci lokalnej, zagranicznej i wyjazdowej NUMA)

Kin Shah
źródło
1

Z punktu widzenia sprzętowego zarządzanie pamięcią główną od architektury Nehalem jest zarządzane przez zintegrowany kontroler pamięci, jest to część „nie-rdzeniowa” matrycy procesora, która jest oddzielona od części, na której żyją rzeczywiste rdzenie, ponieważ pamięć jest skutecznie „Przewodowa” dla każdego procesora, dostęp do pamięci zagranicznej AFAIK odbywa się za pośrednictwem szybkiego połączenia (ponownie od Nehalem i dalej), dlatego powiedziałbym, że nasycenie rdzenia procesora w lokalnym węźle NUMA nie powinno wpływać na zdalny dostęp do tej pamięci.

Ten link może być przydatny:

http://cs.nyu.edu/~lerner/spring10/projects/NUMA.pdf

Chris

Chris Adkin
źródło