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

Hasilkan satu set atau urutan tanpa loop – bagian 2

Dalam posting saya sebelumnya, saya berbicara tentang cara untuk menghasilkan urutan angka yang berdekatan dari 1 hingga 1.000. Sekarang saya ingin berbicara tentang tingkat skala berikutnya:menghasilkan kumpulan 50.000 dan 1.000.000 angka.

Menghasilkan kumpulan 50.000 angka

Saat memulai seri ini, saya benar-benar penasaran bagaimana pendekatan yang berbeda akan menskalakan ke kumpulan angka yang lebih besar. Di bagian bawah, saya sedikit kecewa menemukan bahwa pendekatan favorit saya – menggunakan sys.all_objects – bukanlah metode yang paling efisien. Tapi bagaimana teknik yang berbeda ini bisa mencapai 50.000 baris?

    Tabel angka

    Karena kita telah membuat tabel Numbers dengan 1.000.000 baris, kueri ini hampir sama:

    PILIH ATAS (50000) n DARI dbo.Nomor ORDER OLEH n;

    Rencana:

    spt_values

    Karena hanya ada ~2.500 baris di spt_values , kita perlu sedikit lebih kreatif jika ingin menggunakannya sebagai sumber generator set kita. Salah satu cara untuk mensimulasikan tabel yang lebih besar adalah dengan CROSS JOIN itu melawan dirinya sendiri. Jika kami melakukannya mentah, kami akan mendapatkan ~ 2.500 baris kuadrat (lebih dari 6 juta). Hanya membutuhkan 50.000 baris, kita membutuhkan sekitar 224 baris kuadrat. Jadi kita bisa melakukan ini:

    ;DENGAN x AS ( SELECT TOP (224) angka FROM [master]..spt_values)SELECT TOP (50000) n =ROW_NUMBER() OVER (ORDER BY x.number) FROM x CROSS JOIN x AS yORDER BY n; 

    Perhatikan bahwa ini setara dengan, tetapi lebih ringkas daripada, variasi ini:

    SELECT TOP (50000) n =ROW_NUMBER() OVER (ORDER BY x.number) FROM (SELECT TOP (224) number FROM [master]..spt_values) AS xCROSS JOIN(SELECT TOP (224) number FROM [master ]..spt_values) SEBAGAI ORDER OLEH n;

    Dalam kedua kasus, rencananya terlihat seperti ini:

    sys.all_objects

    Seperti spt_values , sys.all_objects tidak cukup memenuhi persyaratan 50.000 baris kami sendiri, jadi kami perlu melakukan CROSS JOIN yang serupa .

    ;;DENGAN x AS ( SELECT TOP (224) [object_id] FROM sys.all_objects)SELECT TOP (50000) n =ROW_NUMBER() OVER (ORDER BY x.[object_id]) FROM x CROSS JOIN x AS y ORDER OLEH n;

    Rencana:

    CTE bertumpuk

    Kami hanya perlu melakukan sedikit penyesuaian pada CTE bertumpuk untuk mendapatkan tepat 50.000 baris:

    ;DENGAN e1(n) AS( SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1) , -- 10e2(n) AS (PILIH 1 FROM e1 CROSS GABUNG e1 AS b), -- 10*10e3(n) AS (PILIH 1 FROM e2 CROSS GABUNG e2 AS b), -- 100*100e4(n) AS (PILIH 1 DARI e3 CROSS JOIN (PILIH TOP 5 n DARI e1) AS b) -- 5*10000 SELECT n =ROW_NUMBER() OVER (ORDER BY n) FROM e4 ORDER BY n;

    Rencana:

    CTE Rekursif

    Perubahan yang lebih kecil lagi diperlukan untuk mendapatkan 50.000 baris dari CTE rekursif kami:ubah WHERE klausa menjadi 50.000 dan ubah MAXRECURSION opsi ke nol.

    ;DENGAN n(n) AS( SELECT 1 UNION ALL SELECT n+1 FROM n WHERE n <50000)SELECT n FROM n ORDER BY nOPTION (MAXRECURSION 0);

    Rencana:

    Dalam hal ini ada ikon peringatan pada pengurutan – ternyata, pada sistem saya, pengurutan perlu ditumpahkan ke tempdb. Anda mungkin tidak melihat tumpahan di sistem Anda, tetapi ini seharusnya menjadi peringatan tentang sumber daya yang diperlukan untuk teknik ini.

    Kinerja

    Seperti rangkaian pengujian terakhir, kami akan membandingkan setiap teknik, termasuk tabel Numbers dengan cache dingin dan hangat, dan keduanya terkompresi dan tidak terkompresi:


    Waktu proses, dalam milidetik, untuk menghasilkan 50.000 angka yang berurutan

    Untuk mendapatkan visual yang lebih baik, mari kita hapus CTE rekursif, yang merupakan anjing total dalam pengujian ini dan yang mencondongkan hasilnya:


    Waktu proses, dalam milidetik, untuk menghasilkan 50.000 angka yang berdekatan (tidak termasuk rekursif CTE)

    Pada 1.000 baris, perbedaan antara terkompresi dan tidak terkompresi sangat kecil, karena kueri hanya perlu membaca masing-masing 8 dan 9 halaman. Pada 50.000 baris, celahnya sedikit melebar:74 halaman vs. 113. Namun, biaya keseluruhan untuk mendekompresi data tampaknya lebih besar daripada penghematan dalam I/O. Jadi, pada 50.000 baris, tabel angka yang tidak terkompresi tampaknya merupakan metode paling efisien untuk menurunkan himpunan yang berdekatan – meskipun, memang, keuntungannya kecil.

Menghasilkan satu set 1.000.000 angka

Meskipun saya tidak dapat membayangkan banyak kasus penggunaan di mana Anda memerlukan kumpulan angka yang berdekatan sebesar ini, saya ingin memasukkannya untuk kelengkapan, dan karena saya membuat beberapa pengamatan menarik pada skala ini.

    Tabel angka

    Tidak ada kejutan di sini, kueri kami sekarang:

    PILIH TOP 1000000 n FROM dbo.NUMBER ORDER OLEH n;

    TOP tidak sepenuhnya diperlukan, tetapi itu hanya karena kita tahu bahwa tabel Numbers dan output yang kita inginkan memiliki jumlah baris yang sama. Rencananya masih sangat mirip dengan tes sebelumnya:

    spt_values

    Untuk mendapatkan CROSS JOIN yang menghasilkan 1.000.000 baris, kita perlu mengambil 1.000 baris kuadrat:

    ;DENGAN x AS ( SELECT TOP (1000) nomor FROM [master]..spt_values)SELECT n =ROW_NUMBER() OVER (ORDER BY x.number) FROM x CROSS JOIN x AS y ORDER BY n;

    Rencana:

    sys.all_objects

    Sekali lagi, kita membutuhkan perkalian silang dari 1.000 baris:

    ;DENGAN x AS ( SELECT TOP (1000) [object_id] FROM sys.all_objects)SELECT n =ROW_NUMBER() OVER (ORDER BY x.[object_id]) FROM x CROSS JOIN x AS y ORDER BY n; 

    Rencana:

    CTE bertumpuk

    Untuk CTE bertumpuk, kita hanya membutuhkan kombinasi CROSS JOIN yang sedikit berbeda s untuk mencapai 1.000.000 baris:

    ;DENGAN e1(n) AS( SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1) , -- 10e2(n) AS (PILIH 1 DARI e1 CROSS GABUNG e1 AS b), -- 10*10e3(n) AS (PILIH 1 FROM e1 CROSS GABUNG e2 AS b), -- 10*100e4(n) AS (PILIH 1 DARI e3 CROSS GABUNG e3 AS b) -- 1000*1000 SELECT n =ROW_NUMBER() OVER (ORDER BY n) FROM e4 ORDER BY n;

    Rencana:

    Pada ukuran baris ini, Anda dapat melihat bahwa solusi CTE yang ditumpuk berjalan paralel. Jadi saya juga menjalankan versi dengan MAXDOP 1 untuk mendapatkan bentuk denah yang serupa seperti sebelumnya, dan untuk melihat apakah paralelisme benar-benar membantu:

    CTE Rekursif

    CTE rekursif sekali lagi hanya memiliki sedikit perubahan; hanya WHERE klausa perlu diubah:

    ;DENGAN n(n) AS( SELECT 1 UNION ALL SELECT n+1 FROM n WHERE n <1000000)SELECT n FROM n ORDER BY nOPTION (MAXRECURSION 0);

    Rencana:

    Kinerja

    Sekali lagi kami melihat kinerja CTE rekursif sangat buruk:


    Waktu proses, dalam milidetik, untuk menghasilkan 1.000.000 angka yang berurutan

    Menghapus outlier itu dari grafik, kami mendapatkan gambaran yang lebih baik tentang kinerja:


    Waktu proses, dalam milidetik, untuk menghasilkan 1.000.000 angka yang berdekatan (tidak termasuk rekursif CTE)

    Sekali lagi kita melihat tabel Numbers yang tidak terkompresi (setidaknya dengan cache hangat) sebagai pemenang, perbedaan bahkan pada skala ini tidak terlalu mencolok.

Bersambung…

Sekarang setelah kita benar-benar menjelajahi beberapa pendekatan untuk menghasilkan urutan angka, kita akan beralih ke tanggal. Di postingan terakhir seri ini, kita akan membahas konstruksi rentang tanggal sebagai satu set, termasuk penggunaan tabel kalender, dan beberapa kasus penggunaan yang berguna.

[ Bagian 1 | Bagian 2 | Bagian 3 ]

Lampiran :Jumlah baris

Anda mungkin tidak mencoba menghasilkan jumlah baris yang tepat; Anda mungkin hanya menginginkan cara langsung untuk menghasilkan banyak baris. Berikut adalah daftar kombinasi tampilan katalog yang akan memberi Anda berbagai jumlah baris jika Anda cukup SELECT tanpa WHERE ayat. Perhatikan bahwa angka-angka ini akan bergantung pada apakah Anda berada di RTM atau paket layanan (karena beberapa objek sistem ditambahkan atau dimodifikasi), dan juga apakah Anda memiliki database kosong.

Sumber Jumlah baris
SQL Server 2008 R2 SQL Server 2012 SQL Server 2014
master..spt_values

2,508

2,515 2,519
master..spt_values ​​CROSS JOIN master..spt_values

6.290.064

6.325.225 6.345.361
sys.all_objects

1,990

2.089 2.165
sys.all_columns

5,157

7.276 8.560
sys.all_objects LINTAS GABUNG sys.all_objects

3.960.100

4.363.921 4.687.225
sys.all_objects LINTAS GABUNG sys.all_columns

10.262.430

15.199.564 18.532.400
sys.all_columns LINTAS GABUNG sys.all_columns

26.594.649

52.940.176 73,273,600

Tabel 1:Jumlah baris untuk berbagai kueri tampilan katalog


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Relasional vs basis data non-relasional - Part 3

  2. 4 Cara Mendapatkan Definisi Stored Procedure menggunakan Transact-SQL

  3. Memfilter Data dengan JDBC RowSet

  4. Peningkatan Showplan untuk UDF

  5. Parameterisasi Sederhana dan Rencana Trivial — Bagian 1