Mam proces, który pobiera kilka rekordów (1000) i działa na nich, a kiedy skończę, muszę oznaczyć ich dużą liczbę jako przetworzonych. Mogę to wskazać za pomocą dużej listy identyfikatorów. Staram się unikać wzorca „aktualizacji w pętli”, dlatego chciałbym znaleźć bardziej skuteczny sposób na przesłanie tego worka identyfikatorów do przechowywanego proc. MS SQL Server 2008.
Propozycja 1 - Parametry wyceniane w tabeli. Mogę zdefiniować typ tabeli z polem identyfikatora i wysłać tabelę zawierającą identyfikatory do aktualizacji.
Propozycja 2 - parametr XML (varchar) z OPENXML () w treści proc.
Propozycja nr 3 - parsowanie listy. Wolę raczej tego unikać, jeśli to możliwe, ponieważ wydaje się to nieporęczne i podatne na błędy.
Jakieś preferencje wśród nich lub pomysły, które przegapiłem?
źródło
Odpowiedzi:
Najlepsze w historii artykuły na ten temat są autorstwa Erlanda Sommarskoga:
Obejmuje wszystkie opcje i całkiem dobrze wyjaśnia.
Przepraszam za krótką odpowiedź, ale artykuł Erlanda na temat tablic jest jak książki Joe Celko o drzewach i innych smakołykach SQL :)
źródło
Jest świetna dyskusja na ten temat na StackOverflow, która obejmuje wiele podejść. Ten, który preferuję w SQL Server 2008+, to używanie parametrów o wartościach przechowywanych w tabeli . Jest to zasadniczo rozwiązanie problemu dla programu SQL Server - przekazanie listy wartości do procedury składowanej.
Zaletami tego podejścia są:
Jednak zwróć uwagę: jeśli wywołasz procedurę składowaną, która korzysta z TVP za pośrednictwem ADO.NET lub ODBC i spojrzysz na działanie za pomocą SQL Server Profiler, zauważysz, że SQL Server otrzymuje kilka
INSERT
instrukcji do załadowania TVP, po jednej dla każdego wiersza w TVP , a następnie wezwanie do zabiegu. Jest to zgodne z projektem . Ta partiaINSERT
s musi być kompilowana za każdym razem, gdy wywoływana jest procedura, i stanowi niewielki narzut. Jednak nawet z tym narzutem TVP nadal odrzucają inne podejścia pod względem wydajności i użyteczności w większości przypadków użycia.Jeśli chcesz dowiedzieć się więcej, Erland Sommarskog ma pełną wiedzę na temat działania parametrów wycenianych w tabeli i podaje kilka przykładów.
Oto inny przykład, który wymyśliłem:
źródło
CREATE TYPE
instrukcja na początku działała poprawnie? Jaką wersję programu SQL Server używasz?@customer_list
chodzi@param1
. Przykład pokazuje po prostu, że można mieszać różne typy parametrów.Cały temat omawiany jest w ostatecznym artykule Erlanda Sommarskoga: „Tablice i listy w SQL Server” . Wybierz wersję, którą chcesz wybrać.
Podsumowanie, dla wersji wcześniejszych niż SQL Server 2008, w których TVP przebijają resztę
Ten artykuł i tak warto przeczytać, aby zobaczyć inne techniki i sposób myślenia.
Edycja: późna odpowiedź dla ogromnych list w innym miejscu: Przekazywanie parametrów tablicy do procedury składowanej
źródło
Wiem, że spóźniłem się na tę imprezę, ale miałem taki problem w przeszłości, musiałem wysłać do 100 tysięcy bigintów i wykonałem kilka testów porównawczych. Ostatecznie wysłaliśmy je w formacie binarnym, jako obraz - to było szybsze niż wszystko inne dla liczb do 100 000.
Oto mój stary kod (SQL Server 2005):
Poniższy kod upakowuje liczby całkowite do binarnego obiektu blob. Odwracam tutaj kolejność bajtów:
źródło
Jestem rozdarty między odsyłaniem cię do SO lub odpowiedzeniem tutaj, bo to jest prawie pytanie programistyczne. Ale skoro mam już rozwiązanie, którego używam ... opublikuję to;)
Działa to w ten sposób, że podajesz ciąg rozdzielany przecinkami (prosty podział, nie robi podziałów w stylu CSV) do procedury składowanej jako varchar (4000), a następnie podajesz tę listę do tej funkcji i dostajesz poręczną tabelę, stół tylko varcharów.
Pozwala to na przesłanie wartości tylko identyfikatorów, które chcesz przetworzyć, i możesz w tym momencie wykonać proste łączenie.
Alternatywnie możesz zrobić coś z CLR DataTable i zasilić to, ale to trochę więcej narzutów do wsparcia i każdy rozumie listy CSV.
źródło
Regularnie otrzymuję zestawy 1000 wierszy i 10000 wierszy wysyłanych z naszej aplikacji do przetworzenia przez różne procedury składowane programu SQL Server.
Aby sprostać wymaganiom dotyczącym wydajności, korzystamy z TVP, ale musisz zaimplementować własny streszczenie dbDataReader, aby rozwiązać niektóre problemy z wydajnością w domyślnym trybie przetwarzania. Nie będę wchodził w hows i dlaczego, ponieważ są poza zakresem tej prośby.
Nie zastanawiałem się nad przetwarzaniem XML, ponieważ nie znalazłem implementacji XML, która pozostaje wydajna z ponad 10.000 „wierszy”.
Przetwarzanie list może być obsługiwane przez przetwarzanie tabel liczb jednowymiarowych i dwuwymiarowych (liczb). Wykorzystaliśmy je z powodzeniem w różnych obszarach, ale dobrze zarządzani TVP są bardziej wydajni, gdy jest ich więcej niż kilkaset „wierszy”.
Podobnie jak w przypadku wszystkich opcji dotyczących przetwarzania programu SQL Server, musisz dokonać wyboru na podstawie modelu użytkowania.
źródło
W końcu dostałem szansę na wykonanie TableValuedParameters i działają one świetnie, więc wkleję cały kod lotta, który pokazuje, jak ich używam, wraz z próbką z mojego bieżącego kodu: (uwaga: używamy ADO .NETTO)
Uwaga: piszę kod dla usługi i mam wiele predefiniowanych bitów kodu w drugiej klasie, ale piszę to jako aplikację konsolową, dzięki czemu mogę debugować, więc zgarnąłem wszystko z aplikacja konsoli. Przepraszam za mój styl kodowania (jak na stałe parametry połączenia), ponieważ było to coś w rodzaju „zbuduj jeden, aby go wyrzucić”. Chciałem pokazać, jak korzystam z a,
List<customObject>
i łatwo wepchnąć do bazy danych jako tabelę, której mogę użyć w procedurze przechowywanej. Kod C # i TSQL poniżej:Będę również konstruktywnie krytykować mój styl kodowania, jeśli masz to do zaoferowania (wszystkim czytelnikom, którzy napotkają to pytanie), ale proszę, zachowaj konstruktywność;) ... Jeśli naprawdę mnie chcesz, znajdź mnie na czacie tutaj . Mam nadzieję, że dzięki temu fragmentowi kodu można zobaczyć, jak mogą korzystać z tego,
List<Current>
co ja zdefiniowałem jako tabelę w bazie danych iwList<T>
aplikacji.źródło
Wybrałbym propozycję nr 1 lub, alternatywnie, stworzyłem tabelę scratch, która po prostu przechowuje przetworzone identyfikatory. Wstaw do tej tabeli podczas przetwarzania, a po zakończeniu wywołaj procedurę podobną do poniższej:
Zrobisz wiele wstawek, ale będą przy małym stoliku, więc powinno być szybko. Możesz także wsadowo wstawiać swoje wkładki za pomocą ADO.net lub dowolnego adaptera danych, którego używasz.
źródło
Tytuł pytania obejmuje zadanie przesyłania danych z aplikacji do procedury składowanej. Ta część jest wykluczona przez pytanie, ale spróbuję też na to odpowiedzieć.
W kontekście sql-server-2008, jak określono w tagach, jest kolejny świetny artykuł autorstwa E. Sommarskog Tablice i listy w SQL Server 2008 . BTW znalazłem to w artykule, do którego Marian odniósł się w swojej odpowiedzi.
Zamiast podawać link, cytuję jego listę treści:
Poza wymienionymi tam technikami mam wrażenie, że w niektórych przypadkach zbiorcze kopiowanie i wkładka zbiorcza zasługują na uwzględnienie w ogólnym przypadku.
źródło
Dla najnowszej wersji MS SQL 2016
W MS SQL 2016 wprowadzono nową funkcję: SPLIT_STRING () do analizowania wielu wartości.
To może łatwo rozwiązać twój problem.
Dla starszej wersji MS SQL
Jeśli używasz starszej wersji, wykonaj następujące czynności:
Najpierw Wykonaj jedną funkcję:
Po wykonaniu tej czynności, po prostu przekaż swój ciąg do tej funkcji za pomocą separatora.
Mam nadzieję, że ci to pomoże. :-)
źródło
Użyj tego, aby utworzyć „tabelę typów”. prosty przykład dla użytkownika
źródło