Dalam artikel ini, kita akan melihat operator “APPLY” dan variasinya – CROSS APPLY dan OUTER APPLY beserta contoh penggunaannya.
Secara khusus, kita akan belajar:
- perbedaan antara CROSS APPLY dan klausa JOIN
- cara menggabungkan keluaran kueri SQL dengan fungsi yang dievaluasi tabel
- cara mengidentifikasi masalah kinerja dengan menanyakan tampilan manajemen dinamis dan fungsi manajemen dinamis.
Apa itu Klausul APPLY
Microsoft memperkenalkan operator APPLY di SQL Server 2005. Operator APPLY mirip dengan klausa T-SQL JOIN karena juga memungkinkan Anda untuk menggabungkan dua tabel – misalnya, Anda dapat menggabungkan tabel luar dengan tabel dalam. Operator APPLY adalah pilihan yang baik ketika, di satu sisi, kita memiliki ekspresi yang dievaluasi tabel yang ingin kita evaluasi untuk setiap baris dari tabel yang kita miliki di sisi lain. Jadi, tabel sisi kanan diproses untuk setiap baris tabel sisi kiri. Tabel sisi kiri dievaluasi terlebih dahulu, kemudian tabel sisi kanan dievaluasi terhadap setiap baris tabel sisi kiri untuk menghasilkan himpunan hasil akhir. Kumpulan hasil akhir mencakup semua kolom dari kedua tabel.
Operator APPLY memiliki dua variasi:
- LINTAS BERLAKU
- BERLAKU LUAR
LINTAS BERLAKU
CROSS APPLY mirip dengan INNER JOIN, tetapi juga dapat digunakan untuk menggabungkan fungsi yang dievaluasi tabel dengan SQL Tables. Keluaran akhir CROSS APPLY terdiri dari catatan yang cocok antara keluaran fungsi yang dievaluasi tabel dan Tabel SQL.
BERLAKU LUAR
OUTER APPLY menyerupai LEFT JOIN, tetapi memiliki kemampuan untuk menggabungkan fungsi yang dievaluasi tabel dengan Tabel SQL. Keluaran akhir OUTER APPLY berisi semua catatan dari tabel sisi kiri atau fungsi yang dievaluasi tabel, meskipun tidak cocok dengan catatan di tabel sisi kanan atau fungsi bernilai tabel.
Sekarang, izinkan saya menjelaskan kedua variasi dengan contoh.
Contoh penggunaan
Menyiapkan Pengaturan Demo
Untuk menyiapkan pengaturan demo, Anda perlu membuat tabel bernama "Karyawan" dan "Departemen" dalam database yang akan kami sebut "DemoDatabase". Untuk melakukannya, jalankan kode berikut:
GUNAKAN DEMODATABASE GO CREATE TABLE [DBO].[EMPLOYEES] ( [EMPLOYEENAME] [VARCHAR](MAX) NULL, [BIRTHDATE] [DATETIME] NULL, [JOBTITLE] [VARCHAR](150) NULL, [EMAILID] [ VARCHAR](100) NULL, [PHONENUMBER] [VARCHAR](20) NULL, [HIREDATE] [DATETIME] NULL, [DEPARTMENTID] [INT] NULL ) GO CREATE TABLE [DBO].[DEPARTMENT] ( [DEPARTMENTID] INT IDENTITY (1, 1), [DEPARTMENTNAME] [VARCHAR](MAX) NULL ) GO
Selanjutnya, masukkan beberapa data dummy ke kedua tabel. Script berikut akan memasukkan data ke dalam “Karyawan s ” tabel:
[expand title =”PERTANYAAN LENGKAP “]
MASUKKAN [DBO].[EMPLOYEES] ([NAMA EMPLOYEE], [ULANG TAHUN], [JOBTITLE], [EMAILID], [PHONENUMBER], [HIREDATE], [DEPARTMENTID]) NILAI (N'KEN J SÁNCHEZ', CAST (N'1969-01-29T00:00:00.000' AS DATETIME), N'CHIEF EXECUTIVE OFFICER', N'[email protected]', N'697-555-0142', CAST(N'2009-01- 14T00:00:00.000' AS DATETIME), 1), (N'TERRI LEE DUFFY', CAST(N'1971-08-01T00:00:00.000' AS DATETIME), N'VICE PRESIDENT OF ENGINEERING', N'example @sqldat.com', N'819-555-0175', CAST(N'2008-01-31T00:00:00.000' AS DATETIME), NULL), (N'ROBERTO TAMBUELLO', 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' SEBAGAI DATETIME), N' SENIOR TOOL DESIGNER', N'[email protected]', N'612-555-0100', CAST(N'2007-12-05T00:00:00.000' AS DATETIME), NULL), (N'GAIL A ERICKSON ', CAST(N'1952-09-27T00:00:00.000' AS DATETIME), N'DESIGN ENGINEER', N'[email protected]', N'849-555-0139', CAST(N'2008- 01-06T00:00:00.000' AS DATETIME), NULL), (N'JOSSEF H GOLDBERG', CAST(N'1959-03-11T00:00:00.000' AS DATETIME), N'DESIGN ENGINEER', N'example @sqldat.com', N'122-555-0189', CAST(N'2008-01-24T00:00:00.000' AS DATETIME), NULL), (N'DYLAN A MILLER', CAST(N'1987- 02-24T00:00:00.000' AS DATETIME), N'RESEARCH AND DEVELOPMENT MANAGER', N'[email protected]', N'181-555-0156', CAST(N'2009-02-08T00:00:00.000' AS DATETIME), 3), (N'DIANE L MARGHEIM', CAST(N'1986-06-05T00:00:00.000' AS DATETIME), N'RESEARCH AND DEVELOPMENT ENGINEER', N'[email protected]', N'815-555-0138', CAST(N'2008-12-29T00:00:00.000' AS DATETIME), 3), (N'GIGI N MATTHEW', CAST(N '1979-01-21T00:00:00.000' AS DATETIME), N'RESEARCH AND DEVELOPMENT ENGINEER', N'[email protected]', N'185-555-0186', CAST(N'2009-01-16T00 :00:000.000' AS DATETIME), 3), (N'MICHAEL RAHEEM', CAST(N'1984-11-30T00:00:00.000' AS DATETIME), N'RESEARCH AND DEVELOPMENT MANAGER', N'example@sqldat .com', N'330-555-2568', CAST(N'2009-05-03T00:00:00.000' AS DATETIME), 3)
[/expand]
Untuk menambahkan data ke “Departemen . kami ”, jalankan script berikut:
MASUKKAN [DBO].[DEPARTMENT] ([DEPARTMENTID], [DEPARTMENTNAME]) NILAI (1, N'IT'), (2, N'TECHNICAL'), (3, N'RESEARCH AND DEVELOPMENT')Sekarang, untuk memverifikasi data, jalankan kode yang Anda lihat di bawah ini:
PILIH [NAMA EMPLOYEE], [TANGGAL ULANG], [PEKERJAAN], [EMAILID], [NOMOR TELEPON], [PEMPEKERJAAN], [DEPARTMENTID] FROM [EMPLOYEES] GOSELECT [DEPARTMENTID], [DEPARTMENTNAME] FROM [DEPARTMENT] GOInilah hasil yang diinginkan:
Membuat dan menguji fungsi yang dievaluasi tabel
Seperti yang telah saya sebutkan, “LINTAS BERLAKU ” dan “BERLAKU LUAR ” digunakan untuk menggabungkan Tabel SQL dengan fungsi yang dievaluasi tabel. Untuk mendemonstrasikannya, mari buat fungsi yang dievaluasi tabel bernama “getEmployeeData .” Fungsi ini akan menggunakan nilai dari DepartmentID kolom sebagai parameter input dan mengembalikan semua karyawan dari departemen koresponden.
Untuk membuat fungsi, jalankan skrip berikut:
BUAT FUNGSI Getemployeesbydepartment (@DEPARTMENTID INT) RETURNS @EMPLOYEES TABLE ( EMPLOYEENAME VARCHAR (MAX), TANGGAL TANGGAL, JOBTITLE VARCHAR(150), EMAILID VARCHAR(100), NOMOR TELEPON WAKTU VARCHAR(20), HIDRATE )) SEBAGAI MULAI MASUKKAN KE @EMPLOYEES PILIH A.EMPLOYEENAME, A.BIRTHDATE, A.JOBTITLE, A.EMAILID, A.PHONENUMBER, A.HIREDATE, A.DEPARTMENTID FROM [EMPLOYEES] A WHERE A.DEPARTMENTID =@DEPARTMENTID RETURNSekarang, untuk menguji fungsinya, kita akan melewati “1 ” sebagai “departmentID ” ke “Getemployeesbydepartment " fungsi. Untuk melakukannya, jalankan skrip yang disediakan di bawah ini:
GUNAKAN DEMODATABASEGOSELECT EMPLOYEENAME, ULANG TAHUN, JOBTITLE, EMAILID, PHONENUMBER, HIREDATE, DEPARTMENTIDFROM GETEMPLOYEESBYDEPARTMENT (1)Outputnya harus sebagai berikut:
Menggabungkan tabel dengan fungsi yang dievaluasi tabel menggunakan CROSS APPLY
Sekarang, mari kita coba gabungkan tabel Karyawan dengan “Getemployeesbydepartment ” fungsi evaluasi tabel menggunakan CROSS APPLY . Seperti yang saya sebutkan, LINTAS BERLAKU operator mirip dengan klausa Gabung. Ini akan mengisi semua catatan dari “Karyawan ” tabel yang memiliki baris yang cocok dalam output “Getemployeesbydepartment ”.
Jalankan skrip berikut:
PILIH A.[NAMA EMPLOYEE], A.[TANGGAL ULANG], A.[JOBTITLE], A.[EMAILID], A.[NOMOR TELEPON], A.[HIREDATE], B.[NAMA DEPARTEMEN] DARI DEPARTEMEN B LINTAS BERLAKU GETEMPLOYEESBYDEPARTMENT(B.DEPARTMENTID) AOutputnya harus sebagai berikut:
Menggabungkan Tabel dengan fungsi yang dievaluasi Tabel menggunakan OUTER APPLY
Sekarang, Mari kita coba gabungkan tabel Karyawan dengan "Getemployeesbydepartment ” fungsi evaluasi tabel menggunakan OUTER APPLY . Seperti yang saya sebutkan sebelumnya, OUTER BERLAKU operator menyerupai “OUTER JOIN klausa. Ini mengisi semua catatan dari “Karyawan ” dan output dari “Getemployeesbydepartment ” fungsi.
Jalankan skrip berikut:
PILIH A.[NAMA EMPLOYEE], A.[TANGGAL ULANG], A.[JOBTITLE], A.[EMAILID], A.[PHONENUMBER], A.[HIREDATE], B.[DEPARTMENTNAME] FROM DEPARTMENT B OUTER APPLY GETEMPLOYEESBYDEPARTMENT(B.DEPARTMENTID) AInilah output yang akan Anda lihat sebagai hasilnya:
Mengidentifikasi masalah kinerja dengan menggunakan fungsi dan tampilan manajemen dinamis
Mari saya tunjukkan contoh yang berbeda. Di sini, kita akan melihat cara mendapatkan rencana kueri dan teks kueri terkait dengan menggunakan fungsi manajemen dinamis dan tampilan manajemen dinamis.
Untuk tujuan demonstrasi, saya telah membuat tabel bernama “SmokeTestResults ” di “DemoDatabase”. Ini berisi hasil tes asap aplikasi. Mari kita bayangkan bahwa, secara tidak sengaja, pengembang mengeksekusi SQL Query untuk mengisi data dari “SmokeTestResults ” tanpa menambahkan filter, yang secara signifikan mengurangi kinerja database.
Sebagai DBA, kami perlu mengidentifikasi kueri yang membutuhkan banyak sumber daya. Untuk melakukan ini, kita akan menggunakan “sys.dm_exec_requests ” dan tampilan “sys.dm_exec_sql_text ” fungsi.
“Sys.dm_exec_requests ” adalah tampilan manajemen dinamis yang memberikan detail penting berikut yang dapat kita gunakan untuk mengidentifikasi kueri yang memakan sumber daya:
- ID Sesi
- Waktu CPU
- Jenis Tunggu
- ID Basis Data
- Membaca (Fisik)
- Tulisan (Fisik)
- Bacaan logis
- Pegangan SQL
- Pegangan Rencana
- Status Kueri
- Perintah
- ID Transaksi
“sys.dm_exec_sql_text ” adalah fungsi manajemen dinamis yang menerima pengangan SQL sebagai parameter input dan memberikan detail berikut:
- ID Basis Data
- ID Objek
- Dienkripsi
- Teks Kueri SQL
Sekarang, mari kita jalankan kueri berikut untuk menghasilkan beberapa tekanan pada database ASAP. Jalankan kueri berikut:
GUNAKAN ASAP GO SELECT TSID, USERID, EXECUTIONID, EX_RESULTFILE, EX_TESTDATAFILE, EX_ZIPFILE, EX_STARTTIME, EX_ENDTIME, EX_REMARKS FROM [ASAP].[DBO].[SMOKETESTRESULTS]SQL Server mengalokasikan ID sesi "66" dan memulai eksekusi kueri. Lihat gambar berikut:
Sekarang, untuk memecahkan masalah, kami memerlukan ID Database, Pembacaan Logis, SQL Kueri, Perintah, ID Sesi, Jenis tunggu dan SQL Handle . Seperti yang saya sebutkan, kita bisa mendapatkan Database ID, Logical Reads, Command, Session ID, wait Type dan SQL menangani dari “sys.dm_exec_requests.” Untuk mendapatkan SQL Query , kita harus menggunakan “sys.dm_exec_sql_text. ” Ini adalah fungsi manajemen dinamis, jadi harus bergabung dengan “sys.dm_exec_requests ” dengan “sys.dm_exec_sql_text ” dengan menggunakan CROSS APPLY.
Di jendela Editor kueri baru, jalankan kueri berikut:
SELECT B.TEXT, 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_REQUESTS A LINTAS BERLAKU SYS.SQL_TEXT_EXEC_SQL_TEXT_EXEC_ /pra>Ini harus menghasilkan output berikut:
Seperti yang Anda lihat pada tangkapan layar di atas, kueri mengembalikan semua informasi yang diperlukan untuk mengidentifikasi masalah kinerja.
Sekarang, selain teks kueri, kami ingin mendapatkan rencana eksekusi yang digunakan untuk mengeksekusi kueri tersebut. Untuk melakukannya, kita akan menggunakan “sys.dm_exec_query_plan” fungsi.
“sys.dm_exec_query_plan ” adalah fungsi manajemen dinamis yang menerima pegangan rencana sebagai parameter input dan memberikan detail berikut:
- ID Basis Data
- ID Objek
- Dienkripsi
- Paket Kueri SQL dalam format XML
Untuk mengisi rencana eksekusi kueri, kita harus menggunakan CROSS APPLY untuk bergabung dengan “sys.dm_exec_requests ” dan “sys.dm_exec_query_plan. ”
Buka jendela editor Kueri Baru dan jalankan kueri berikut:
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 DARI SYS.DM_EXEC_REQUESTS A CROSS APPLY SQL_HANDLE) B CROSS APPLY SYS.DM_EXEC_QUERY_PLAN (A.PLAN_HANDLE) COutputnya harus sebagai berikut:
Sekarang, seperti yang Anda lihat, rencana kueri dibuat dalam format XML secara default. Untuk membukanya sebagai representasi grafis, klik pada keluaran XML di query_plan kolom seperti pada gambar di atas. Setelah Anda mengklik output XML, rencana eksekusi akan dibuka di jendela baru seperti yang ditunjukkan pada gambar berikut:
Mendapatkan daftar tabel dengan indeks yang sangat terfragmentasi dengan menggunakan tampilan dan fungsi manajemen dinamis
Mari kita lihat satu contoh lagi. Saya ingin mendapatkan daftar tabel dengan indeks yang memiliki 50% atau lebih fragmentasi dalam database yang diberikan. Untuk mengambil tabel ini, kita perlu menggunakan “sys.dm_db_index_physical_stats ” dan tampilan “sys.tables ” fungsi.
“Tabel Sistem ” adalah tampilan manajemen dinamis yang mengisi daftar tabel pada database tertentu.
“sys.dm_db_index_physical_stats ” adalah fungsi manajemen dinamis yang menerima parameter input berikut:
- ID Basis Data
- ID Objek
- ID Indeks
- Nomor Partisi
- Modus
Ini mengembalikan informasi rinci tentang status fisik dari indeks yang ditentukan.
Sekarang, untuk mengisi daftar indeks yang terfragmentasi, kita harus bergabung dengan “sys.dm_db_index_physical_stats ” dan “sys.tables ” menggunakan CROSS APPLY. Jalankan kueri berikut:
PILIH TABLES.NAME, INDEXSTATISTICS.ALLOC_UNIT_TYPE_DESC, CONVERT(NUMERIC(10, 2), INDEXSTATISTICS.AVG_FRAGMENTATION_IN_PERCENT) SEBAGAI PERCENTAGEFRAGMENTATION, INDEXSTATISTICS.PAGE_COUNT FROM SYSID_TABLES_PHSID_PERCENT SEBAGAI PERCENTAGEFRAGMENTASI , NULL, NULL, NULL) SEBAGAI INDEXSTATISTICS WHERE INDEXSTATISTICS.DATABASE_ID =DB_ID() AND AVG_FRAGMENTATION_IN_PERCENT>=50 ORDER BY INDEXSTATISTICS.AVG_FRAGMENTATION_IN_PERCENT DESCKueri harus menghasilkan output berikut:
Ringkasan
Dalam artikel ini, kami membahas operator APPLY, variasinya – CROSS APPLY dan OUTER APPLY dan cara kerja Anda. Kami juga telah melihat bagaimana Anda dapat menggunakannya untuk mengidentifikasi masalah kinerja SQL menggunakan tampilan manajemen dinamis dan fungsi manajemen dinamis.