Database
 sql >> Baza danych >  >> RDS >> Database

Zaawansowany SQL:CROSS APPLY i OUTER APPLY

W tym artykule przyjrzymy się operatorowi „ZASTOSUJ” i jego odmianom – ZASTOSUJ KRZYŻOWY i ZASTOSUJ ZEWNĘTRZNY wraz z przykładami ich użycia.

W szczególności dowiemy się:

  • różnica między CROSS APPLY a klauzulą ​​JOIN
  • jak połączyć wyniki zapytań SQL z funkcjami oceniającymi tabele
  • jak identyfikować problemy z wydajnością, odpytując dynamiczne widoki zarządzania i dynamiczne funkcje zarządzania.

Co to jest klauzula ZASTOSUJ

Firma Microsoft wprowadziła operator APPLY w SQL Server 2005. Operator APPLY jest podobny do klauzuli T-SQL JOIN, ponieważ umożliwia również łączenie dwóch tabel – na przykład można połączyć tabelę zewnętrzną z tabelą wewnętrzną. Operator APPLY jest dobrym rozwiązaniem, gdy po jednej stronie mamy wyrażenie obliczane w tabeli, które chcemy obliczyć dla każdego wiersza z tabeli, którą mamy po drugiej stronie. Tak więc tabela po prawej stronie jest przetwarzana dla każdego wiersza tabeli po lewej stronie. Tabela po lewej stronie jest oceniana jako pierwsza, a następnie tabela po prawej stronie jest oceniana względem każdego wiersza tabeli po lewej stronie w celu wygenerowania końcowego zestawu wyników. Ostateczny zestaw wyników zawiera wszystkie kolumny z obu tabel.

Operator APPLY ma dwie odmiany:

  • ZASTOSUJ KRZYŻ
  • ZASTOSOWANIE ZEWNĘTRZNE

ZASTOSUJ KRZYŻ

CROSS APPLY jest podobny do INNER JOIN, ale może być również używany do łączenia funkcji oceniających tabele z tabelami SQL. Ostateczny wynik CROSS APPLY składa się z rekordów dopasowanych między wynikiem funkcji oceniającej tabelę a tabelą SQL.

ZASTOSOWANIE ZEWNĘTRZNE

OUTER APPLY przypomina LEFT JOIN, ale ma możliwość łączenia funkcji oceniających tabele z tabelami SQL. Ostateczny wynik OUTER APPLY zawiera wszystkie rekordy z lewej strony tabeli lub funkcji wartościującej tabelę, nawet jeśli nie pasują one do rekordów w prawej tabeli lub funkcji wartościującej tabelę.

Teraz wyjaśnię obie odmiany na przykładach.

Przykłady użycia

Przygotowywanie konfiguracji demonstracyjnej

Aby przygotować konfigurację demonstracyjną, musisz utworzyć tabele o nazwach „Pracownicy” i „Dział” w bazie danych, którą nazwiemy „Baza danych demo”. Aby to zrobić, uruchom następujący kod:

UŻYJ DEMODATABASE GO CREATE TABLE [DBO].[PRACOWNICY] ( [NAZWA PRACOWNIKA] [VARCHAR](MAX) NULL, [DATA URODZIN] [DATETIME] NULL, [STANOWISKO] [VARCHAR](150) NULL, [IDENTYFIKATOR EMAIL] [ VARCHAR](100) NULL, [PHONENUMBER] [VARCHAR](20) NULL, [HIREDATE] [DATETIME] NULL, [DEPARTMENTID] [INT] NULL ) GO CREATE TABLE [DBO].[DZIAŁ] ( [DEPARTMENTID] INT IDENTITY (1, 1), [NAZWA DZIAŁU] [VARCHAR](MAX) NULL) Idź

Następnie wstawiamy fałszywe dane do obu tabel. Poniższy skrypt wstawi dane do „Pracownika s ” tabela:

[rozwiń tytuł =”PEŁNE ZAPYTANIE „]

WSTAW [DBO].[PRACOWNIKÓW] ([NAZWISKO PRACOWNIKA], [DATA URODZIN], [STANOWISKO PRACY], [IDENTYFIKATOR E-MAIL], [NUMER TELEFONU], [DATA ZATRUDNIENIA], [ID DZIAŁU]) WARTOŚCI (N'KEN J SÁNCHEZ', OBSADZKA (N'1969-01-29T00:00:00.000' JAKO DATA GODZINA), N'DYREKTOR GŁÓWNY', N'[email protected]', N'697-555-0142', CAST(N'2009-01- 14T00:00:00.000' JAKO DATETIME), 1), (N'TERRI LEE DUFFY', CAST(N'1971-08-01T00:00:00.000' JAKO DATETIME), N'VICE PREZES INŻYNIERII', N'przykład @sqldat.com', N'819-555-0175', CAST (N'2008-01-31T00:00:00.000' JAKO DATETIME), NULL), (N'ROBERTO TAMBURELLO', CAST (N'1974-11) -12T00:00:00.000' AS DATETIME), N'ENGINEERING MANAGER', N'[email protected]', N'212-555-0187', CAST(N'2007-11-11T00:00:00.000' AS DATETIME), NULL), (N'ROB WALTERS', CAST (N'1974-12-23T00:00:00.000' JAKO DATETIME), N' SENIOR TOOL DESIGNER', N'[email protected]', N'612-555-0100', CAST(N'2007-12-05T00:00:00.000' JAKO DATETIME), NULL), (N'GAIL A ERICKSON ', CAST(N'1952-09-27T00:00:00.000' JAKO DATETIME), N'DESIGN ENGINEER', N'[email protected]', N'849-555-0139', CAST(N'2008- 01-06T00:00:00.000' JAKO DATETIME), NULL), (N'JOSSEF H GOLDBERG', CAST(N'1959-03-11T00:00:00.000' JAKO DATETIME), N'DESIGN ENGINEER', N'przykład @sqldat.com', N'122-555-0189', CAST (N'2008-01-24T00:00:00.000' JAKO DATETIME), NULL), (N'DYLAN A MILLER', CAST (N'1987- 02-24T00:00:00.000' JAKO DATETIME), N'MENEDŻER BADAŃ I ROZWOJU', N'[email protected]', N'181-555-0156', CAST(N'2009-02-08T00:00:00.000' JAKO DATETIME), 3), (N'DIANE L MARGHEIM', CAST(N'1986-06-05T00:00:00.000' JAKO DATETIME), N'INŻYNIER BADAWCZY I ROZWOJU', N'[email protected]', N'815-555-0138', CAST(N'2008-12-29T00:00:00.000' JAKO DATETIME), 3), (N'GIGI N MATTHEW', CAST(N '1979-01-21T00:00:00.000' JAKO DATETIME), N'INŻYNIER BADAWCZY I ROZWOJU', N'[email protected]', N'185-555-0186', CAST(N'2009-01-16T00 :00:00.000' JAKO DATETIME), 3), (N'MICHAEL RAHEEM', CAST(N'1984-11-30T00:00:00.000' JAKO DATETIME), N'MENEDŻER BADAŃ I ROZWOJU', N'example@sqldat .com ', N'330-555-2568', PRZESYŁANIE (N'2009-05-03T00:00:00.000' JAKO DATETIME), 3)

[/rozwiń]

Aby dodać dane do naszego „Działu ”, uruchom następujący skrypt:

WSTAW [DBO].[DZIAŁ] ([ID WYDZIAŁU], [NAZWA WYDZIAŁU]) WARTOŚCI (1, N'IT'), (2, N'TECHNICZNE'), (3, N'BADANIA I ROZWÓJ')

Teraz, aby zweryfikować dane, wykonaj kod widoczny poniżej:

SELECT [NAZWA PRACOWNIKA], [DATA URODZIN], [STANOWISKO], [IDENTYFIKATOR E-MAIL], [NUMER TELEFONU], [DATA ZATRUDNIENIA], [ID DZIAŁU] Z [PRACOWNIKÓW] GOSELECT [ID DZIAŁU], [NAZWA DZIAŁU] Z [DZIAŁU] GO

Oto pożądany wynik:

Tworzenie i testowanie funkcji z wartościami tabelarycznymi

Jak już wspomniałem, „ZASTOSUJ KRZYŻOWY ” i „ZASTOSOWANIE ZEWNĘTRZNE ” służą do łączenia tabel SQL z funkcjami oceniającymi tabele. Aby to zademonstrować, utwórzmy funkcję obliczającą tabelę o nazwie „getEmployeeData ”. Ta funkcja użyje wartości z ID działu kolumna jako parametr wejściowy i zwróć wszystkich pracowników z działu korespondentów.

Aby utworzyć funkcję, uruchom następujący skrypt:

CREATE FUNCTION Getemployeesbydepartment (@DEPARTMENTID INT) ZWRACA @EMPLOYEES TABELA (NAZWA PRACOWNIKA VARCHAR (MAX), DATA URODZENIA DATETIME, JOBTITLE VARCHAR(150), EMAILID VARCHAR (100), NUMER TELEFONU VARCHAR(20), WYNAJMUJ DATE GODZINA, WYJAZD )) NA POCZĄTKU WSTAWIĆ W @EMPLOYEES SELECT A.NAZWISKO PRACOWNIKA, A.DATA URODZIN, A.JOBTITLE, A.EMAILID, A.PHONENUMBER, A.HIREDATE, A.DEPARTMENTID FROM [PRACOWNIKI] A WHERE A.DEPARTMENTID =@DEPARTMENTID RETURN END 

Teraz, aby przetestować funkcję, przekażemy „1 ” jako „ID wydziału ” do „Getemployeesbydepartment funkcja. Aby to zrobić, wykonaj poniższy skrypt:

UŻYJ DEMODATABASEGOSELECT NAZWISKO PRACOWNIKA, DATA URODZENIA, NAZWA STANOWISKA, ID E-MAIL, NUMER TELEFONU, DATA ZATRUDNIENIA, ID DZIAŁU OD ZATRUDNIONYCH Z DZIAŁU (1)

Dane wyjściowe powinny wyglądać następująco:

Dołączanie do tabeli za pomocą funkcji oceniającej tabelę za pomocą CROSS APPLY

Spróbujmy teraz dołączyć do stołu Pracownicy z „Getemployeesbydepartment ” funkcja oceniana w tabeli przy użyciu CROSS APPLY . Jak wspomniałem, ZASTOSUJ KRZYŻ operator jest podobny do klauzuli Join. Wypełni wszystkie rekordy od „Pracownika ” tabela, dla której w danych wyjściowych „Getemployeesbydepartment znajdują się pasujące wiersze ”.

Uruchom następujący skrypt:

WYBIERZ A.[NAZWISKO PRACOWNIKA], A.[DATA URODZIN], A.[NAZWA PRACY], A.[IDENTYFIKATOR E-MAIL], A.[NUMER TELEFONU], A.[DATA ZATRUDNIENIA], B.[NAZWA DZIAŁU] Z DZIAŁU B KRZYŻYK ZASTOSUJ ZATRUDNIENIZDZIAŁU(B.DEPARTMENTID) A

Dane wyjściowe powinny wyglądać następująco:

Dołączanie do tabeli z funkcją oceny tabeli za pomocą funkcji OUTER APPLY

Teraz spróbujmy dołączyć do stołu Pracownicy z „Getemployeesbydepartment ” funkcja oceniana w tabeli przy użyciu OUTER APPLY . Jak wspomniałem wcześniej, ZASTOSOWANIE ZEWNĘTRZNE operator przypomina „POŁĄCZENIE ZEWNĘTRZNE ” klauzula. Wypełnia wszystkie rekordy od „Pracownika ” i dane wyjściowe „Getemployeesbydepartment funkcja.

Uruchom następujący skrypt:

WYBIERZ A.[NAZWISKO PRACOWNIKA], A.[DATA URODZIN], A.[NAZWA PRACY], A.[IDENTYFIKATOR E-MAIL], A.[NUMER TELEFONU], A.[DATA ZATRUDNIENIA], B.[NAZWA DZIAŁU] Z DZIAŁU B ZASTOSOWANIE ZEWNĘTRZNE ZATRUDNIENIZDZIAŁU(B.DEPARTMENTID) A

Oto wynik, który powinieneś zobaczyć w wyniku:

Identyfikowanie problemów z wydajnością za pomocą funkcji i widoków dynamicznego zarządzania

Pokażę ci inny przykład. Tutaj zobaczymy, jak uzyskać plan zapytania i odpowiadający mu tekst zapytania, korzystając z funkcji dynamicznego zarządzania i dynamicznych widoków zarządzania.

W celach demonstracyjnych stworzyłem tabelę o nazwie „SmokeTestResults ” w „Bazie DemoData”. Zawiera wyniki testu dymu aplikacyjnego. Wyobraźmy sobie, że przez pomyłkę programista wykonuje zapytanie SQL, aby wypełnić dane z „SmokeTestResults ” bez dodawania filtra, co znacznie zmniejsza wydajność bazy danych.

Jako administrator baz danych musimy zidentyfikować zapytanie wymagające dużej ilości zasobów. Aby to zrobić, użyjemy „sys.dm_exec_requests ” i „sys.dm_exec_sql_text funkcja.

Sys.dm_exec_requests ” to dynamiczny widok zarządzania, który zawiera następujące ważne szczegóły, których możemy użyć do zidentyfikowania zapytania pochłaniającego zasoby:

  1. Identyfikator sesji
  2. Czas procesora
  3. Typ oczekiwania
  4. Identyfikator bazy danych
  5. Odczyty (fizyczne)
  6. Zapisuje (fizyczne)
  7. Odczyty logiczne
  8. Uchwyt SQL
  9. Obsługa planu
  10. Stan zapytania
  11. Polecenie
  12. Identyfikator transakcji

sys.dm_exec_sql_text ” to dynamiczna funkcja zarządzania, która akceptuje dojście SQL jako parametr wejściowy i zawiera następujące szczegóły:

  1. Identyfikator bazy danych
  2. Identyfikator obiektu
  3. Jest zaszyfrowany
  4. Tekst zapytania SQL

Teraz uruchommy następujące zapytanie, aby wygenerować trochę stresu w bazie danych ASAP. Wykonaj następujące zapytanie:

UŻYJ ASAP GO SELECT TSID, USERID, EXECUTIONID, EX_RESULTFILE, EX_TESTDATAFILE, EX_ZIPFILE, EX_STARTTIME, EX_ENDTIME, EX_REMARKS FROM [ASAP].[DBO].[SMOKETESTRESULTS]

SQL Server przydziela identyfikator sesji „66” i rozpoczyna wykonywanie zapytania. Zobacz następujący obraz:

Teraz, aby rozwiązać ten problem, potrzebujemy identyfikatora bazy danych, odczytów logicznych SQL Zapytanie, polecenie, identyfikator sesji, typ oczekiwania iuchwyt SQL . Jak wspomniałem, możemy uzyskać ID bazy danych, odczyty logiczne, polecenie, identyfikator sesji, typ oczekiwania i uchwyt SQL z „sys.dm_exec_requests”. Aby uzyskać zapytanie SQL , musimy użyć „sys.dm_exec_sql_text. ” Jest to funkcja dynamicznego zarządzania, więc trzeba by dołączyć do „sys.dm_exec_requests ” z „sys.dm_exec_sql_text ” za pomocą CROSS APPLY.

W oknie edytora nowych zapytań uruchom następujące zapytanie:

WYBIERZ B.TEKST, A.WAIT_TYPE, A.LAST_WAIT_TYPE, A.COMMAND, A.SESSION_ID, CPU_TIME, A.BLOCKING_SESSION_ID, A.LOGICAL_READS FROM SYS.DM_EXEC_REQUES A CROSS APPLY SYS.DM_EXEC_SQL_TEXANDLEA. /pre> 

Powinno to dać następujący wynik:

Jak widać na powyższym zrzucie ekranu, zapytanie zwróciło wszystkie informacje wymagane do zidentyfikowania problemu z wydajnością.

Teraz oprócz tekstu zapytania chcemy uzyskać plan wykonania, który został użyty do wykonania zapytania. Aby to zrobić, użyjemy „sys.dm_exec_query_plan” funkcja.

sys.dm_exec_query_plan ” to dynamiczna funkcja zarządzania, która akceptuje uchwyt planu jako parametr wejściowy i zawiera następujące szczegóły:

  1. Identyfikator bazy danych
  2. Identyfikator obiektu
  3. Jest zaszyfrowany
  4. Plan zapytań SQL w formacie XML

Aby wypełnić plan wykonania zapytania, musimy użyć CROSS APPLY, aby dołączyć do „sys.dm_exec_requests ” i „sys.dm_exec_query_plan.

Otwórz okno edytora nowych zapytań i wykonaj następujące zapytanie:

 SELECT B.TEXT, A.WAIT_TYPE, A.LAST_WAIT_TYPE, A.COMMAND, A.SESSION_ID, CPU_TIME, A.BLOCKING_SESSION_ID, A.LOGICAL_READS, C.QUERY_PLAN FROM SYS.DM_EXEC_REQUES A CROSS APPLY SYS_DM_EXEC SQL_HANDLE) B KRZYŻ ZASTOSUJ SYS.DM_EXEC_QUERY_PLAN (A.PLAN_HANDLE) C

Dane wyjściowe powinny wyglądać następująco:

Teraz, jak widać, plan zapytania jest domyślnie generowany w formacie XML. Aby otworzyć go jako reprezentację graficzną, kliknij wynik XML w query_plan kolumna, jak pokazano na powyższym obrazku. Po kliknięciu wyniku XML plan wykonania zostanie otwarty w nowym oknie, jak pokazano na poniższym obrazku:

Uzyskiwanie listy tabel z wysoce rozdrobnionymi indeksami za pomocą dynamicznych widoków i funkcji zarządzania

Zobaczmy jeszcze jeden przykład. Chcę otrzymać listę tabel z indeksami, które w danej bazie danych mają fragmentację 50% lub większą. Aby pobrać te tabele, będziemy musieli użyć „sys.dm_db_index_physical_stats ” i „sys.tables funkcja.

Tabele Sys. ” to dynamiczny widok zarządzania, który wypełnia listę tabel w określonej bazie danych.

sys.dm_db_index_physical_stats ” to dynamiczna funkcja zarządzania, która akceptuje następujące parametry wejściowe:

  1. Identyfikator bazy danych
  2. Identyfikator obiektu
  3. Identyfikator indeksu
  4. Numer partycji
  5. Tryb

Zwraca szczegółowe informacje o stanie fizycznym określonego indeksu.

Teraz, aby wypełnić listę pofragmentowanych indeksów, musimy dołączyć do „sys.dm_db_index_physical_stats ” i „sys.tables ” używając CROSS APPLY. Uruchom następujące zapytanie:

SELECT TABLES.NAME, INDEXSTATISTICS.ALLOC_UNIT_TYPE_DESC, CONVERT(NUMERIC(10, 2), INDEXSTATISTICS.AVG_FRAGMENTATION_IN_PERCENT) AS PERCENTAGEFRAGMENTATION, INDEXSTATISTICS.PAGE_COUNT FROM SYS.TABLES AS TABLES_DMOSS_PHOSS APPS TABLES_DMOSS_DB() , NULL, NULL, NULL) JAKO INDEXSTATISTICS GDZIE INDEXSTATISTICS.DATABASE_ID =DB_ID() AND AVG_FRAGMENTATION_IN_PERCENT>=50 ORDER BY INDEXSTATISTICS.AVG_FRAGMENTATION_IN_PERCENT DESC

Zapytanie powinno dać następujący wynik:

Podsumowanie

W tym artykule omówiliśmy operator APPLY, jego odmiany – CROSS APPLY i OUTER APPLY oraz sposób, w jaki pracujesz. Zobaczyliśmy również, jak można ich używać do identyfikowania problemów z wydajnością SQL za pomocą dynamicznych widoków zarządzania i dynamicznych funkcji zarządzania.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. ETL kontra ELT:zakładamy, ty sędzio

  2. Jak połączyć bazę danych z Amazon VPC

  3. Wszystko, co musisz wiedzieć o operatorze LIKE w SQL

  4. Konstruowanie modelu danych dla systemu zarządzania parkingami

  5. Dell Boomi