Database
 sql >> Teknologi Basis Data >  >> RDS >> Database

Tindak lanjut dari Summer Performance Palooza 2013

Pada tanggal 27 Juni, PASS Performance Virtual Chapter mengadakan 2013 Summer Performance Palooza – semacam PASS 24 Jam yang diperkecil, tetapi hanya berfokus pada topik yang terkait dengan kinerja. Saya memberikan sesi berjudul, "10 Kebiasaan Buruk yang Dapat Membunuh Kinerja", membahas 10 konsep berikut:

  1. PILIH *
  2. Indeks buta
  3. Tidak ada awalan skema
  4. Opsi kursor default
  5. awalan sp_
  6. Membiarkan cache membengkak
  7. Tipe data lebar
  8. Default SQL Server
  9. Menggunakan fungsi secara berlebihan
  10. "Berfungsi di mesin saya"

Anda mungkin ingat beberapa topik ini dari presentasi seperti ceramah "Kebiasaan Buruk dan Praktik Terbaik" saya atau webinar Penyesuaian Kueri mingguan yang saya selenggarakan bersama Kevin Kline dari awal Juni hingga minggu ini. (Omong-omong, 6 video itu akan tersedia pada awal Agustus di YouTube.)

Sesi saya memiliki 351 peserta, dan saya mendapat umpan balik yang bagus. Saya ingin membahas beberapa di antaranya.

Pertama, masalah konfigurasi:Saya menggunakan mikrofon baru, dan tidak tahu bahwa setiap penekanan tombol akan terdengar seperti guntur. Saya telah mengatasi masalah itu dengan penempatan periferal yang lebih baik, tetapi saya ingin meminta maaf kepada semua orang yang terpengaruh olehnya.

Selanjutnya, unduhan; dek dan sampel diposting ke lokasi acara. Mereka ada di bagian bawah halaman, tetapi Anda juga dapat mengunduhnya di sini.

Akhirnya, berikut ini adalah daftar pertanyaan yang diposting selama sesi, dan saya ingin memastikan bahwa saya menjawab pertanyaan apa pun yang tidak terjawab selama tanya jawab langsung. Saya minta maaf karena saya telah memeras ini hanya dalam waktu kurang dari sebulan , tapi ada ada banyak pertanyaan, dan saya tidak ingin memublikasikannya sebagian.

T:Jika Anda memiliki proc yang dapat memiliki nilai input yang sangat bervariasi untuk parameter yang diberikan dan hasilnya adalah paket yang di-cache tidak optimal untuk sebagian besar kasus, apakah yang terbaik adalah membuat proc WITH RECOMPILE dan mengambil yang kecil kinerja tercapai setiap kali dijalankan?

J: Anda harus mendekati ini berdasarkan kasus per kasus, karena ini akan sangat bergantung pada berbagai faktor (termasuk kerumitan rencana). Perhatikan juga bahwa Anda dapat melakukan kompilasi ulang tingkat pernyataan sehingga hanya pernyataan yang terpengaruh yang harus menerima pukulan, bukan keseluruhan modul. Paul White mengingatkan saya bahwa orang sering 'memperbaiki' parameter sniffing dengan RECOMPILE , tetapi terlalu sering itu berarti WITH RECOMPILE gaya 2000 daripada OPTION (RECOMPILE) yang jauh lebih baik , yang tidak hanya membatasi dirinya pada pernyataan, tetapi juga memungkinkan penyematan parameter, yang WITH RECOMPILE tidak. Jadi, jika Anda akan menggunakan RECOMPILE untuk menggagalkan sniffing parameter, tambahkan ke pernyataan, bukan modul.

T:Jika Anda menggunakan opsi kompilasi ulang pada sql dinamis, apakah Anda akan melihat kinerja yang hebat?

J: Seperti di atas, ini akan tergantung pada biaya dan kerumitan rencana dan tidak ada cara untuk mengatakan, "Ya, akan selalu ada pencapaian kinerja yang besar." Anda juga harus yakin untuk membandingkannya dengan alternatifnya.

Q:Jika ada clustered index pada insertdate, nanti saat kita mengambil data, kita menggunakan fungsi convert, jika menggunakan perbandingan langsung, tanggal query tidak terbaca, di dunia nyata, apa pilihan yang lebih baik

J: Saya tidak yakin apa artinya "dapat dibaca di dunia nyata". Jika Anda ingin output dalam format tertentu, Anda biasanya lebih baik mengonversi ke string di sisi klien. C# dan sebagian besar bahasa lain yang mungkin Anda gunakan di tingkat presentasi lebih dari mampu memformat keluaran tanggal/waktu dari database dalam format regional apa pun yang Anda inginkan.

T:Bagaimana cara menentukan berapa kali paket yang di-cache digunakan – apakah ada kolom dengan nilai itu atau pertanyaan apa pun di internet yang akan memberikan nilai ini? Terakhir, apakah penghitungan seperti itu hanya relevan sejak pengaktifan ulang terakhir?

J: Sebagian besar DMV hanya berlaku sejak layanan terakhir dimulai, dan bahkan yang lain dapat dihapus lebih sering (bahkan sesuai permintaan – baik secara tidak sengaja maupun sengaja). Cache paket, tentu saja, dalam fluks konstan, dan paket AFAIK yang keluar dari cache tidak mempertahankan jumlah sebelumnya jika mereka muncul kembali. Jadi, bahkan ketika Anda melihat paket di cache, saya tidak 100% yakin Anda dapat mempercayai jumlah penggunaan yang Anda temukan.

Karena itu, yang mungkin Anda cari adalah sys.dm_exec_cached_plans.usecounts dan Anda juga dapat menemukan sys.dm_exec_procedure_stats.execution_count untuk membantu melengkapi informasi untuk prosedur di mana pernyataan individu dalam prosedur tidak ditemukan dalam cache.

T:Apa Masalah saat memutakhirkan mesin db ke versi baru tetapi meninggalkan basis data pengguna dalam mode kompatibilitas yang lebih lama?

J: Perhatian utama seputar ini adalah kemampuan untuk menggunakan sintaks tertentu, seperti OUTER APPLY atau variabel dengan fungsi bernilai tabel. Saya tidak mengetahui adanya kasus di mana menggunakan kompatibilitas yang lebih rendah memiliki dampak langsung pada kinerja, tetapi beberapa hal yang biasanya direkomendasikan adalah untuk membangun kembali indeks dan memperbarui statistik (dan untuk membuat vendor Anda mendukung tingkat kompatibilitas yang lebih baru ASAP). Saya telah melihatnya menyelesaikan penurunan kinerja yang tidak terduga dalam sejumlah besar kasus, tetapi saya juga mendengar beberapa pendapat bahwa hal itu tidak perlu dan bahkan mungkin tidak bijaksana.

T:Pada * apakah penting saat melakukan klausa yang ada

J: Tidak, setidaknya dalam hal kinerja, satu pengecualian di mana SELECT * tidak masalah adalah ketika digunakan di dalam EXISTS ayat. Tapi mengapa Anda menggunakan * di sini? Saya lebih suka menggunakan EXISTS (SELECT 1 ... – pengoptimal akan memperlakukannya dengan cara yang sama, tetapi pengoptimal mendokumentasikan kode sendiri dan memastikan bahwa pembaca memahami subkueri tidak mengembalikan data apa pun (bahkan jika mereka melewatkan EXISTS besar di luar). Beberapa orang menggunakan NULL , dan saya tidak tahu mengapa saya mulai menggunakan 1, tetapi saya menemukan NULL sedikit tidak intuitif juga.

*Catatan* Anda harus berhati-hati, jika Anda mencoba menggunakan EXISTS (SELECT * di dalam modul yang terikat skema:

CREATE VIEW dbo.ThisWillNotWork
WITH SCHEMABINDING
AS
  SELECT BusinessEntityID
    FROM Person.Person AS p
	WHERE EXISTS (SELECT * FROM Sales.SalesOrderHeader AS h
	  WHERE h.SalesPersonID = p.BusinessEntityID);

Anda mendapatkan kesalahan ini:

Msg 1054, Level 15, Status 6, Prosedur ThisWillNotWork, Baris 6
Sintaks '*' tidak diizinkan di objek terikat skema.

Namun mengubahnya menjadi SELECT 1 bekerja dengan baik. Jadi mungkin itu argumen lain untuk menghindari SELECT * bahkan dalam skenario itu.

T:Apakah ada tautan sumber daya untuk standar pengkodean terbaik?

J: Mungkin ada ratusan dalam berbagai bahasa. Seperti konvensi penamaan, standar pengkodean adalah hal yang sangat subjektif. Tidak masalah konvensi apa yang Anda putuskan paling cocok untuk Anda; jika Anda suka tbl awalan, gila! Lebih suka Pascal daripada bigEndian, lakukanlah. Ingin mengawali nama kolom Anda dengan tipe data, seperti intCustomerID , aku tidak akan menghentikanmu. Yang lebih penting adalah Anda mendefinisikan konvensi dan menggunakannya *secara konsisten.*

Yang mengatakan, jika Anda menginginkan pendapat saya, saya tidak akan kekurangannya.

T:Apakah XACT_ABORT sesuatu yang dapat digunakan di SQL Server 2008 dan seterusnya?

J: Saya tidak tahu ada rencana untuk menghentikan XACT_ABORT jadi itu harus terus bekerja dengan baik. Terus terang saya tidak melihat ini sering digunakan sekarang karena kami memiliki TRY / CATCH (dan THROW pada SQL Server 2012).

T:Bagaimana penerapan Fungsi Tabel Sebaris pada tanda silang dibandingkan dengan fungsi skalar yang disebut 1.000x?

J: Saya tidak menguji ini, tetapi dalam banyak kasus mengganti fungsi skalar dengan fungsi bernilai tabel sebaris dapat berdampak besar pada kinerja. Masalah yang saya temukan adalah bahwa membuat sakelar ini dapat menjadi pekerjaan besar pada sistem yang ditulis sebelum APPLY ada, atau masih dikelola oleh orang-orang yang belum menganut pendekatan yang lebih baik ini.

T:Saya memiliki kueri yang berjalan sangat lambat pertama kali (~1 menit) dan cepat (~3 detik) setiap saat. Di mana saya harus mulai melihat dari mana masalah kinerja pertama kali muncul?

J: Dua hal yang terlintas dalam pikiran:(1) penundaan berkaitan dengan waktu kompilasi atau (2) penundaan berkaitan dengan jumlah data yang dimuat untuk memenuhi kueri, dan pertama kali harus berasal dari disk dan bukan memori. Untuk (1) Anda dapat menjalankan kueri di SQL Sentry Plan Explorer dan bilah status akan menunjukkan kepada Anda waktu kompilasi untuk pemanggilan pertama dan selanjutnya (meskipun satu menit tampaknya agak berlebihan untuk ini, dan tidak mungkin). Jika Anda tidak menemukan perbedaan apa pun, mungkin itu hanya sifat sistem:memori tidak cukup untuk mendukung jumlah data yang Anda coba muat dengan kueri ini dalam kombinasi dengan data lain yang sudah ada di kumpulan buffer. Jika Anda tidak yakin salah satu dari ini adalah masalahnya, lihat apakah dua eksekusi yang berbeda benar-benar menghasilkan rencana yang berbeda – jika ada perbedaan, poskan rencana tersebut ke answer.sqlperformance.com dan kami akan dengan senang hati memeriksanya . Bahkan menangkap rencana aktual untuk kedua eksekusi menggunakan Plan Explorer dalam kasus apa pun juga dapat memberi tahu Anda tentang perbedaan dalam I/O dan dapat mengarah ke tempat SQL Server menghabiskan waktunya pada proses pertama yang lebih lambat.

T:Saya mendapatkan parameter sniffing menggunakan sp_executesql, akankah Optimize untuk beban kerja ad hoc menyelesaikan ini karena hanya rintisan paket yang ada di cache?

J: Tidak, menurut saya pengaturan Optimize for ad hoc beban kerja tidak akan membantu skenario ini, karena sniffing parameter menyiratkan bahwa eksekusi berikutnya dari rencana yang sama digunakan untuk parameter yang berbeda dan dengan perilaku kinerja yang sangat berbeda. Optimalkan untuk beban kerja ad hoc digunakan untuk meminimalkan dampak drastis pada cache paket yang dapat terjadi jika Anda memiliki banyak pernyataan SQL yang berbeda. Jadi, kecuali jika Anda berbicara tentang dampak pada cache paket dari banyak pernyataan berbeda yang Anda kirim ke sp_executesql – yang tidak akan dicirikan sebagai parameter sniffing – saya rasa bereksperimen dengan OPTION (RECOMPILE) mungkin memiliki hasil yang lebih baik atau, jika Anda mengetahui nilai parameter yang *melakukan* menghasilkan hasil yang baik di berbagai kombinasi parameter, gunakan OPTIMIZE FOR . Jawaban dari Paul White ini dapat memberikan wawasan yang jauh lebih baik.

T:Apakah ada cara untuk menjalankan SQL dinamis dan TIDAK menyimpan paket kueri?

J: Tentu, cukup sertakan OPTION (RECOMPILE) dalam teks SQL dinamis:

DBCC FREEPROCCACHE;
 
USE AdventureWorks2012;
GO
SET NOCOUNT ON;
GO
 
EXEC sp_executesql 
  N'SELECT TOP (1) * INTO #x FROM Sales.SalesOrderHeader;';
GO
EXEC sp_executesql 
  N'SELECT TOP (1) * INTO #x FROM Sales.SalesOrderDetail OPTION (RECOMPILE);'
GO
 
SELECT t.[text], p.usecounts
FROM sys.dm_exec_cached_plans AS p
CROSS APPLY sys.dm_exec_sql_text(p.[plan_handle]) AS t
WHERE t.[text] LIKE N'%Sales.' + 'SalesOrder%';

Hasil:1 baris menampilkan Sales.SalesOrderHeader pertanyaan.

Sekarang, jika ada pernyataan dalam kumpulan TIDAK menyertakan OPTION (RECOMPILE) , paket mungkin masih di-cache, hanya saja tidak dapat digunakan kembali.

T:Dapatkah Anda menggunakan BETWEEN pada contoh tanggal dari #9 sebagai gantinya jika>=dan

J: Nah, BETWEEN secara semantik tidak setara dengan >= AND < , melainkan >= AND <= , dan mengoptimalkan dan melakukan dengan cara yang sama persis. Bagaimanapun, saya sengaja tidak menggunakan BETWEEN pada kueri rentang tanggal – selamanya – karena tidak ada cara untuk menjadikannya rentang terbuka. Dengan BETWEEN , kedua ujungnya inklusif, dan ini bisa sangat bermasalah tergantung pada tipe data yang mendasarinya (sekarang atau karena beberapa perubahan di masa mendatang yang mungkin tidak Anda ketahui). Judulnya mungkin tampak agak kasar, tetapi saya akan membahasnya secara mendetail di postingan blog berikut:

Apa kesamaan ANTARA dan iblis?

T:Di kursor, apa sebenarnya fungsi "local fast_forward"?

J: FAST_FORWARD sebenarnya adalah kependekan dari READ_ONLY dan FORWARD_ONLY . Inilah yang mereka lakukan:

  • LOCAL membuatnya sedemikian rupa sehingga cakupan luar (secara default kursor adalah GLOBAL kecuali Anda telah mengubah opsi tingkat instans).
  • READ_ONLY membuatnya sehingga Anda tidak dapat memperbarui kursor secara langsung, mis. menggunakan WHERE CURRENT OF .
  • FORWARD_ONLY mencegah kemampuan untuk menggulir, mis. menggunakan FETCH PRIOR atau FETCH ABSOLUTE alih-alih FETCH NEXT .

Menyetel opsi ini, seperti yang saya tunjukkan (dan telah saya buat di blog), dapat berdampak signifikan pada kinerja. Sangat jarang saya melihat kursor dalam produksi yang sebenarnya perlu menyimpang dari kumpulan fitur ini, tetapi biasanya kursor tersebut ditulis untuk menerima default yang jauh lebih mahal.

T:mana yang lebih efisien, kursor atau loop while?

J: Sebuah WHILE loop mungkin akan lebih efisien daripada kursor yang setara dengan opsi default, tetapi saya menduga Anda akan menemukan sedikit jika ada perbedaan jika Anda menggunakan LOCAL FAST_FORWARD . Secara umum, sebuah WHILE loop *adalah* kursor tanpa disebut kursor, dan saya menantang beberapa rekan yang sangat terhormat untuk membuktikan bahwa saya salah tahun lalu. WHILE loop tidak berjalan dengan baik.

T:Anda tidak merekomendasikan awalan usp untuk prosedur tersimpan pengguna, apakah ini memiliki dampak negatif yang sama?

J: Sebuah usp_ awalan (atau awalan apa pun selain sp_ , atau tanpa awalan dalam hal ini) *tidak* memiliki dampak yang sama seperti yang saya tunjukkan. Saya menemukan sedikit nilai meskipun dalam menggunakan awalan pada prosedur tersimpan karena sangat jarang ada keraguan bahwa ketika saya menemukan kode yang mengatakan EXEC something , bahwa sesuatu adalah prosedur tersimpan – jadi ada sedikit nilai di sana (tidak seperti, katakanlah, awalan tampilan untuk membedakannya dari tabel, karena dapat digunakan secara bergantian). Memberikan setiap prosedur awalan yang sama juga membuat lebih sulit untuk menemukan objek yang Anda cari, katakanlah, Object Explorer. Bayangkan jika setiap nama belakang di buku telepon diawali dengan LastName_ – dalam hal apa itu membantu Anda?

T:Apakah ada cara untuk membersihkan paket yang di-cache di mana ada banyak salinan?

J: Ya! Nah, jika Anda menggunakan SQL Server 2008 atau lebih tinggi. Setelah Anda mengidentifikasi dua paket yang identik, mereka akan tetap memiliki plan_handle yang terpisah nilai-nilai. Jadi, identifikasi yang Anda *tidak* ingin simpan, salin plan_handle , dan taruh di dalam DBCC perintah:

DBCC FREEPROCCACHE(0x06.....);
T:Apakah menggunakan if else dll dalam proc menyebabkan rencana yang buruk, apakah itu dioptimalkan untuk menjalankan pertama dan hanya mengoptimalkan untuk jalur itu? Jadi, apakah bagian kode di setiap JIKA perlu dibuat menjadi prosedur terpisah?

J: Karena SQL Server sekarang dapat melakukan pengoptimalan tingkat pernyataan, hal ini memiliki efek yang tidak terlalu drastis saat ini dibandingkan dengan versi yang lebih lama, di mana seluruh prosedur harus dikompilasi ulang sebagai satu unit.

Q:Terkadang saya menemukan bahwa menulis sql dinamis bisa lebih baik karena menghilangkan masalah parameter sniffing untuk sp. Apakah ini benar ? Apakah ada pengorbanan atau pertimbangan lain yang harus dilakukan terkait skenario ini?

J: Ya, SQL dinamis sering kali dapat menggagalkan sniffing parameter, terutama dalam kasus di mana kueri "kitchen sink" besar-besaran memiliki banyak parameter opsional. Saya membahas beberapa pertimbangan lain dalam pertanyaan di atas.

T:Jika saya memiliki kolom terhitung di tabel saya sebagai DATEPART(mycolumn, year) dan dalam indeks di atasnya, apakah server SQL akan menggunakan ini dengan SEEK?

J: Seharusnya, tetapi tentu saja itu tergantung pada permintaan. Indeks mungkin tidak cocok untuk menutupi kolom keluaran atau memenuhi filter lain dan parameter yang Anda gunakan mungkin tidak cukup selektif untuk membenarkan pencarian.

T:apakah paket dibuat untuk SETIAP kueri? Apakah rencana dibuat bahkan untuk yang sepele?

J: Sejauh yang saya tahu, rencana dibuat untuk setiap kueri yang valid, bahkan rencana sepele, kecuali ada kesalahan yang mencegah rencana dibuat (ini bisa terjadi dalam beberapa skenario, seperti petunjuk yang tidak valid). Apakah mereka di-cache atau tidak (dan berapa lama mereka tinggal di cache) tergantung pada berbagai faktor lain, beberapa di antaranya telah saya bahas di atas.

T:Apakah panggilan ke sp_executesql menghasilkan (dan menggunakan kembali) paket yang di-cache?

J: Ya, jika Anda mengirim teks kueri yang sama persis, tidak masalah jika Anda mengeluarkannya secara langsung atau mengirimkannya melalui sp_executesql , SQL Server akan menyimpan dan menggunakan kembali paket tersebut.

T:Apakah boleh menerapkan aturan (untuk lingkungan dev) di mana semua mesin dev menggunakan inisialisasi file instan?

J: Saya tidak mengerti mengapa tidak. Satu-satunya kekhawatiran yang saya miliki adalah bahwa dengan inisialisasi file instan, pengembang mungkin tidak melihat sejumlah besar peristiwa autogrow, yang dapat mencerminkan pengaturan pertumbuhan otomatis yang buruk yang dapat memiliki dampak yang sangat berbeda pada lingkungan produksi (terutama jika salah satu dari server tersebut *tidak) * telah mengaktifkan IFI).

T:Dengan fungsi dalam klausa SELECT, apakah benar untuk mengatakan bahwa lebih baik menggandakan kode?

J: Secara pribadi, saya akan mengatakan ya. Saya mendapatkan banyak jarak tempuh kinerja dengan mengganti fungsi skalar di SELECT list dengan padanan sebaris, bahkan dalam kasus di mana saya harus mengulangi kode itu. Namun, seperti disebutkan di atas, dalam beberapa kasus, Anda mungkin menemukan bahwa menggantinya dengan fungsi bernilai tabel sebaris dapat memberi Anda penggunaan kembali kode tanpa penalti kinerja yang buruk.

T:Bisakah kita menggunakan generator data untuk mendapatkan ukuran data yang sama untuk penggunaan pengembangan daripada menggunakan data produksi (sulit didapat)? Apakah kemiringan data penting untuk rencana yang dihasilkan?

J: Kecondongan data dapat memiliki faktor, dan saya menduga itu tergantung pada jenis data yang Anda hasilkan/simulasikan dan seberapa jauh kemiringannya. Jika Anda memiliki, katakanlah, kolom varchar(100) yang dalam produksi biasanya panjangnya 90 karakter dan pembuatan data Anda menghasilkan data yang rata-rata 50 (yang akan diasumsikan oleh SQL Server), Anda akan menemukan dampak yang jauh berbeda pada jumlah halaman dan pengoptimalan, dan mungkin pengujian yang tidak terlalu realistis.

Tapi saya akan jujur:aspek khusus ini bukanlah sesuatu yang telah saya investasikan banyak waktu, karena saya biasanya dapat menggertak cara saya untuk mendapatkan data nyata. :-)

T:Apakah semua fungsi dibuat sama saat memeriksa kinerja kueri? Jika tidak, apakah ada daftar fungsi yang diketahui yang harus Anda hindari jika memungkinkan?

J: Tidak, tidak semua fungsi diciptakan sama dalam hal kinerja. Ada tiga jenis fungsi berbeda yang dapat kita buat (mengabaikan fungsi CLR untuk saat ini):

  • Fungsi skalar multi-pernyataan
  • Fungsi bernilai tabel multi-pernyataan
  • Fungsi bernilai tabel sebaris
    Fungsi skalar sebaris disebutkan dalam dokumentasi, tetapi itu hanyalah mitos dan, pada SQL Server Setidaknya 2014, mungkin juga disebutkan bersama Sasquatch dan Monster Loch Ness.

Secara umum, dan saya akan memasukkannya ke dalam font 80pt jika saya bisa, fungsi bernilai tabel sebaris adalah baik, dan yang lainnya harus dihindari jika memungkinkan, karena lebih sulit untuk dioptimalkan.

Fungsi juga dapat memiliki properti berbeda yang memengaruhi kinerjanya, seperti apakah fungsi tersebut deterministik dan apakah terikat skema.

Untuk banyak pola fungsi, pasti ada pertimbangan kinerja yang perlu Anda buat, dan Anda juga harus mengetahui item Connect ini yang bertujuan untuk mengatasinya.

T:Bisakah kita tetap menjalankan total tanpa kursor?

J: Ya kita bisa; ada beberapa metode selain kursor (seperti yang dirinci dalam posting blog saya, Pendekatan terbaik untuk menjalankan total – diperbarui untuk SQL Server 2012):

  • Subquery dalam daftar PILIH
  • CTE rekursif
  • Bergabung sendiri
  • "Pembaruan yang unik"
  • Hanya SQL Server 2012+:SUM() OVER() (menggunakan default / RANGE)
  • Hanya SQL Server 2012+:SUM() OVER() (menggunakan ROWS)

Opsi terakhir sejauh ini merupakan pendekatan terbaik jika Anda menggunakan SQL Server 2012; jika tidak, ada batasan pada opsi non-kursor lainnya yang akan sering membuat kursor menjadi pilihan yang lebih menarik. Misalnya, metode pembaruan unik tidak didokumentasikan dan tidak dijamin berfungsi sesuai urutan yang Anda harapkan; CTE rekursif mengharuskan tidak ada celah dalam mekanisme sekuensial apa pun yang Anda gunakan; dan pendekatan subquery dan self-join tidak berskala.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Apakah Kunci Kandidat dalam Desain Basis Data?

  2. NoSQL:hidup tanpa skema

  3. Mengukur "Observer Overhead" dari SQL Trace vs. Acara yang Diperpanjang

  4. Kebiasaan buruk:Menghitung baris dengan cara yang sulit

  5. Masalah Halloween – Bagian 4