Czy jest jakaś prawdopodobna korzyść z iteratora szpuli w pierwszym planie?
Zależy to od tego, co uważasz za „prawdopodobne”, ale odpowiedź zgodnie z modelem kosztów brzmi „tak”. Oczywiście jest to prawda, ponieważ optymalizator zawsze wybiera najtańszy znaleziony plan.
Prawdziwe pytanie brzmi: dlaczego model kosztów uważa, że plan ze szpulą jest o wiele tańszy niż plan bez niego? Rozważ szacunkowe plany utworzone dla nowej tabeli (ze skryptu) przed dodaniem wierszy do sklepu delta:
DELETE Fact.RecordedMetricsDetail
WHERE MeasurementTime < DATEADD(day,-1,GETUTCDATE())
OPTION (RECOMPILE);
Szacunkowy koszt tego planu to ogromne 771,734 jednostek :
Koszt jest prawie w całości związany z usuwaniem indeksu klastrowanego, ponieważ oczekuje się, że usunięcie spowoduje wiele losowych operacji we / wy. To tylko ogólna logika, która dotyczy wszystkich modyfikacji danych. Na przykład zakłada się, że nieuporządkowany zestaw modyfikacji indeksu b-drzewa powoduje w dużej mierze losowe operacje we / wy, co wiąże się z wysokimi kosztami operacji we / wy.
Plany zmieniające dane mogą zawierać opcję Sortuj, aby wyświetlać wiersze w kolejności, która będzie promować dostęp sekwencyjny, właśnie z tych powodów kosztów. W tym przypadku wpływ jest zaostrzony, ponieważ tabela jest podzielona na partycje. W rzeczywistości bardzo podzielony; twój skrypt tworzy 15 000 z nich. Losowe aktualizacje tabeli bardzo podzielonej na partycje są szczególnie kosztowne, ponieważ cena przełączania partycji (zestawów wierszy) w środkowym strumieniu również jest wysoka.
Ostatnim ważnym czynnikiem, który należy wziąć pod uwagę, jest to, że powyższe proste zapytanie o aktualizację (gdzie „aktualizacja” oznacza dowolną operację zmiany danych, w tym usunięcie) kwalifikuje się do optymalizacji zwanej „udostępnianiem zestawu zestawów wierszy”, gdzie ten sam zestaw zestawów wierszy jest używany zarówno do skanowania, jak i aktualizacja tabeli. Plan wykonania nadal pokazuje dwa oddzielne operatory, ale jednak jest używany tylko jeden zestaw wierszy.
Wspominam o tym, ponieważ możliwość zastosowania tej optymalizacji oznacza, że optymalizator przyjmuje ścieżkę kodu, która po prostu nie bierze pod uwagę potencjalnych korzyści z jawnego sortowania w celu zmniejszenia kosztów losowych operacji we / wy. Gdy tabela jest drzewem b, ma to sens, ponieważ struktura jest z natury uporządkowana, więc udostępnianie zestawu wierszy automatycznie zapewnia wszystkie potencjalne korzyści.
Ważną konsekwencją jest to, że logika kalkulacji kosztów dla operatora aktualizacji nie bierze pod uwagę tej korzyści związanej z porządkowaniem (promowanie sekwencyjnego We / Wy lub innych optymalizacji), w przypadku gdy podstawowym obiektem jest magazyn kolumn. Wynika to z faktu, że modyfikacje magazynu kolumn nie są wykonywane w miejscu; używają sklepu delta. Model kosztów odzwierciedla zatem różnicę między aktualizacjami zestawu wierszy współdzielonych w drzewach b w porównaniu z magazynami kolumn.
Niemniej jednak, w szczególnym przypadku (bardzo!) Partycjonowanego magazynu kolumn, może istnieć korzyść z zachowanego porządku, ponieważ wykonywanie wszystkich aktualizacji jednej partycji przed przejściem do następnej może być korzystne z punktu widzenia I / O .
Standardowa logika kosztów jest tutaj ponownie używana dla magazynów kolumn, więc plan, który zachowuje porządkowanie partycji (choć nie kolejność w obrębie każdej partycji), kosztuje mniej. Możemy to zobaczyć w zapytaniu testowym, używając nieudokumentowanej flagi śledzenia 2332, aby wymagać posortowanego wejścia do operatora aktualizacji. To powoduje, że DMLRequestSort
właściwość ma wartość true podczas aktualizacji i zmusza optymalizator do stworzenia planu, który udostępnia wszystkie wiersze dla jednej partycji przed przejściem do następnej:
DELETE Fact.RecordedMetricsDetail
WHERE MeasurementTime < DATEADD(day,-1,GETUTCDATE())
OPTION (RECOMPILE, QUERYTRACEON 2332);
Szacunkowy koszt tego planu jest znacznie niższy i wynosi 52,5174 jednostek:
To zmniejszenie kosztów wynika z niższego szacowanego kosztu we / wy podczas aktualizacji. Wprowadzona szpula nie spełnia żadnej użytecznej funkcji, z wyjątkiem tego, że może gwarantować wyjście w kolejności partycji, zgodnie z wymaganiami aktualizacji za pomocą DMLRequestSort = true
(skanowanie szeregowe indeksu magazynu kolumn nie może zapewnić tej gwarancji). Koszt samej szpuli jest uważany za stosunkowo niski, zwłaszcza w porównaniu z (prawdopodobnie nierealistycznym) obniżeniem kosztów w trakcie aktualizacji.
Decyzja o tym, czy wymagać uporządkowanych danych wejściowych do operatora aktualizacji, jest podejmowana bardzo wcześnie podczas optymalizacji zapytań. Heurystyki zastosowane w tej decyzji nigdy nie zostały udokumentowane, ale można je ustalić metodą prób i błędów. Wydaje się, że wielkość dowolnych sklepów delta stanowi wkład w tę decyzję. Po dokonaniu wyboru wybór jest stały dla kompilacji zapytań. Żadna USE PLAN
podpowiedź się nie powiedzie: cel planu albo zamówił dane wejściowe do aktualizacji, albo nie.
Istnieje inny sposób uzyskania taniego planu dla tego zapytania bez sztucznego ograniczania oszacowania liczności. Wystarczająco niska ocena, aby uniknąć buforowania, prawdopodobnie spowoduje, że DMLRequestSort będzie fałszywy, co spowoduje bardzo wysoki szacowany koszt planu z powodu oczekiwanego losowego wejścia / wyjścia. Alternatywą jest użycie flagi śledzenia 8649 (plan równoległy) w połączeniu z 2332 (DMLRequestSort = true):
DELETE Fact.RecordedMetricsDetail
WHERE MeasurementTime < DATEADD(day,-1,GETUTCDATE())
OPTION (RECOMPILE, QUERYTRACEON 2332, QUERYTRACEON 8649);
Wynikiem tego jest plan, który wykorzystuje skanowanie równoległe w trybie partycji dla partycji i utrzymywanie (łączenie) zbierania strumieni wymiany:
W zależności od efektywności zamawiania partycji w czasie rzeczywistym na twoim sprzęcie, może to być najlepsze z trzech. To powiedziawszy, duże modyfikacje nie są świetnym pomysłem w magazynie kolumn, więc pomysł przełączania partycji jest prawie na pewno lepszy. Jeśli poradzisz sobie z długimi czasami kompilacji i dziwacznymi wyborami planów często spotykanymi w przypadku obiektów podzielonych na partycje - zwłaszcza gdy liczba partycji jest duża.
Łączenie wielu stosunkowo nowych funkcji, szczególnie zbliżonych do ich limitów, to świetny sposób na uzyskanie złych planów wykonania. Głębokość obsługi optymalizatora z czasem się poprawia, ale użycie 15 000 partycji magazynu kolumn prawdopodobnie zawsze oznacza, że żyjesz w interesujących czasach.
OPTION (QUERYRULEOFF EnforceHPandAccCard)
szpula zniknie. Zakładam, że HP może być „ochroną Halloween”. Jednak próba użycia tego planu zUSE PLAN
podpowiedzi kończy się niepowodzeniem (podobnie jak próba użycia planu zOPTIMIZE FOR
obejścia)