Saya memiliki algoritma yang harus saya jalankan terhadap setiap baris dalam sebuah tabel dengan 800 ribu baris dan 38 kolom. Algoritme diimplementasikan dalam VBA dan melakukan banyak matematika menggunakan nilai-nilai dari beberapa kolom untuk memanipulasi kolom lain.
Saat ini saya menggunakan Excel (ADO) untuk query SQL dan menggunakan VBA dengan kursor sisi klien untuk menerapkan algoritma dengan loop melalui setiap baris. Ini bekerja tetapi membutuhkan 7 jam untuk berjalan.
Kode VBA cukup kompleks sehingga akan banyak pekerjaan untuk mengode ulang menjadi T-SQL.
Saya telah membaca tentang integrasi CLR dan UDF sebagai rute yang memungkinkan. Saya juga berpikir tentang menempatkan kode VBA dalam tugas skrip SSIS untuk lebih dekat ke database tetapi saya yakin metodologi ahli untuk jenis masalah kinerja ada.
Idealnya, saya dapat menjalankan algoritma terhadap sebanyak mungkin baris (semua?) Sebanyak mungkin dalam cara berbasis paralel.
Setiap bantuan sangat ditentukan tentang cara mendapatkan kinerja terbaik dengan masalah jenis ini.
--Edit
Terima kasih atas komentarnya, saya menggunakan MS SQL 2014 Enterprise, berikut ini beberapa perincian:
Algoritma menemukan pola karakteristik dalam data deret waktu. Fungsi-fungsi dalam algoritma melakukan perataan polinomial, windowing, dan menemukan daerah yang menarik berdasarkan kriteria input, mengembalikan selusin nilai dan beberapa hasil Boolean.
Pertanyaan saya lebih tentang metodologi daripada algoritma yang sebenarnya: Jika saya ingin mencapai komputasi paralel pada banyak baris sekaligus, apa saja pilihan saya.
Saya melihat re-code ke T-SQL direkomendasikan yang banyak pekerjaan tetapi mungkin, namun pengembang algoritma bekerja di VBA dan sering berubah jadi saya harus tetap menyinkronkan dengan versi T-SQL dan memvalidasi ulang setiap perubahan.
Apakah T-SQL satu-satunya cara untuk mengimplementasikan fungsi berbasis set?
sumber
N
kumpulan dan menjalankanN
instance algoritma Anda padaN
prosesor / komputer yang terpisah. Di sisi lain, apa hambatan utama Anda - mentransfer data dari SQL Server ke Excel atau perhitungan aktual? Jika Anda mengubah fungsi VBA untuk mengembalikan beberapa hasil dummy dengan segera, berapa lama seluruh proses? Jika masih membutuhkan waktu berjam-jam, maka bottleneck dalam transfer data. Jika perlu beberapa detik, maka Anda perlu mengoptimalkan kode VBA yang melakukan perhitungan.SELECT AVG([AD_Sensor_Data]) OVER (ORDER BY [RowID] ROWS BETWEEN 5 PRECEDING AND 5 FOLLOWING) as 'AD_Sensor_Data' FROM [AD_Points] WHERE [FileID] = @FileID ORDER BY [RowID] ASC
Di Management Studio fungsi ini yang dipanggil untuk setiap baris membutuhkan 50(FileID, RowID)
.Jawaban:
Berkenaan dengan metodologi, saya percaya Anda menggonggong b-tree yang salah ;-).
Apa yang kita ketahui:
Pertama, mari berkonsolidasi dan tinjau apa yang kita ketahui tentang situasi ini:
Ada Prosedur Tersimpan yang dipanggil untuk setiap baris:
Definisi (setidaknya sebagian) adalah:
Apa yang bisa kita duga:
Selanjutnya, kita dapat melihat semua titik data ini bersama-sama untuk melihat apakah kita dapat mensintesis detail tambahan yang akan membantu kita menemukan satu atau lebih leher botol, dan menunjuk pada suatu solusi, atau setidaknya mengesampingkan beberapa solusi yang mungkin keluar.
Arah pemikiran saat ini dalam komentar adalah bahwa masalah utama adalah transfer data antara SQL Server dan Excel. Apakah benar hal itu merupakan masalahnya? Jika Prosedur Tersimpan dipanggil untuk masing-masing 800.000 baris dan membutuhkan 50 ms per setiap panggilan (yaitu per setiap baris), itu menambah hingga 40.000 detik (bukan ms). Dan itu setara dengan 666 menit (hhmm ;-), atau hanya lebih dari 11 jam. Namun seluruh proses dikatakan hanya memakan waktu 7 jam untuk berjalan. Kami sudah 4 jam dari total waktu, dan kami bahkan telah menambahkan waktu untuk melakukan perhitungan atau menyimpan hasilnya kembali ke SQL Server. Jadi ada sesuatu yang tidak beres di sini.
Melihat definisi Prosedur Tersimpan, hanya ada parameter input untuk
@FileID
; tidak ada filter aktif@RowID
. Jadi saya menduga bahwa salah satu dari dua skenario berikut sedang terjadi:@FileID
, yang tampaknya menjangkau sekitar 4000 baris. Jika 4000 baris yang dikembalikan adalah jumlah yang cukup konsisten, maka hanya ada 200 dari pengelompokan dalam 800.000 baris. Dan 200 eksekusi mengambil 50 ms setiap jumlah hanya 10 detik dari 7 jam itu.@FileID
dilewatkan akan membutuhkan waktu sedikit lebih lama untuk menarik baris baru ke dalam Buffer Pool, tetapi kemudian 3999 eksekusi berikutnya biasanya akan kembali lebih cepat karena sudah menjadi di-cache, kan?Saya pikir fokus pada Prosedur Tersimpan "filter" ini, atau transfer data apa pun dari SQL Server ke Excel, adalah herring merah .
Untuk saat ini, saya pikir indikator yang paling relevan dari kinerja loyo adalah:
Saya menduga bahwa:
UPDATE
pernyataan terpisah , yang merupakan 800.000 transaksi terpisah.Rekomendasi saya (berdasarkan informasi yang tersedia saat ini):
Bidang peningkatan terbesar Anda adalah memperbarui beberapa baris sekaligus (yaitu dalam satu transaksi). Anda harus memperbarui proses Anda agar berfungsi dalam hal masing-masing
FileID
alih-alih masing-masingRowID
. Begitu:FileID
ke dalam arrayFileID
) telah dihitung:RowID
Jika indeks cluster Anda belum didefinisikan
(FileID, RowID)
maka Anda harus mempertimbangkan itu (seperti yang disarankan @MikaelEriksson dalam komentar pada Pertanyaan). Ini tidak akan membantu UPDATE tunggal ini, tetapi setidaknya akan sedikit meningkatkan operasi agregat, seperti apa yang Anda lakukan dalam prosedur tersimpan "filter" karena semuanya didasarkan padaFileID
.Anda harus mempertimbangkan untuk memindahkan logika ke bahasa yang dikompilasi. Saya akan menyarankan membuat aplikasi .NET WinForms atau bahkan Aplikasi Konsol. Saya lebih suka Aplikasi Konsol karena mudah menjadwalkan melalui SQL Agent atau Tugas Terjadwal Windows. Seharusnya tidak masalah apakah itu dilakukan dalam VB.NET atau C #. VB.NET mungkin lebih cocok untuk pengembang Anda, tetapi masih ada beberapa kurva belajar.
Saya tidak melihat alasan pada saat ini untuk pindah ke SQLCLR. Jika algoritma sering berubah, itu akan mengganggu harus menggunakan kembali Majelis sepanjang waktu. Membangun kembali aplikasi konsol dan menempatkan .exe ditempatkan di folder bersama yang tepat di jaringan sehingga Anda hanya menjalankan program yang sama dan kebetulan selalu up-to-date, harus cukup mudah dilakukan.
Saya tidak berpikir memindahkan pemrosesan sepenuhnya ke T-SQL akan membantu jika masalahnya adalah apa yang saya duga dan Anda hanya melakukan satu PEMBARUAN sekaligus.
Jika pemrosesan dipindahkan ke .NET, Anda kemudian dapat menggunakan Table-Valued Parameters (TVPs) sehingga Anda akan meneruskan array ke Prosedur Tersimpan yang akan memanggil seorang
UPDATE
yang BERGABUNG ke variabel tabel TVP dan karenanya merupakan satu transaksi . TVP harus lebih cepat daripada melakukan 4000INSERT
yang dikelompokkan ke dalam satu transaksi. Tetapi keuntungan yang didapat dari menggunakan TVPs lebih dari 4000INSERT
detik dalam 1 transaksi kemungkinan tidak akan sama pentingnya dengan peningkatan yang terlihat ketika beralih dari 800.000 transaksi terpisah menjadi hanya 200 transaksi masing-masing dari 4000 baris.Opsi TVP tidak tersedia secara native untuk sisi VBA, tetapi seseorang datang dengan solusi yang mungkin layak untuk diuji:
Bagaimana cara meningkatkan kinerja basis data saat beralih dari VBA ke SQL Server 2008 R2?
JIKA proc filter hanya menggunakan
FileID
dalamWHERE
klausa, dan JIKA proc itu benar-benar dipanggil per setiap baris, maka Anda dapat menghemat waktu pemrosesan dengan cache hasil run pertama dan menggunakannya untuk sisa baris per ituFileID
, Baik?Setelah Anda menyelesaikan pemrosesan per FileID , maka kita dapat mulai berbicara tentang pemrosesan paralel. Tapi itu mungkin tidak perlu pada saat itu :). Mengingat bahwa Anda berurusan dengan 3 bagian non-ideal yang cukup besar: transaksi Excel, VBA, dan 800 ribu, pembicaraan SSIS, atau jajaran genjang, atau siapa yang tahu apa, adalah pengoptimalan dini / jenis barang sebelum kuda . Jika kita bisa mendapatkan proses 7 jam ini menjadi 10 menit atau kurang, apakah Anda masih memikirkan cara lain untuk membuatnya lebih cepat? Apakah ada target waktu penyelesaian yang Anda pikirkan? Perlu diingat bahwa setelah pemrosesan dilakukan pada per FileID dasar, jika Anda memiliki VB.NET Console App (yaitu command-line .EXE), tidak akan ada yang menghentikan Anda dari menjalankan beberapa FileID tersebut sekaligus :), baik melalui langkah SQL Agent CmdExec atau Windows Scheduled Tasks, dll.
DAN, Anda selalu dapat mengambil pendekatan "bertahap" dan melakukan beberapa peningkatan sekaligus. Seperti memulai dengan melakukan pembaruan per
FileID
dan karenanya menggunakan satu transaksi untuk grup itu. Kemudian, lihat apakah Anda bisa membuat TVP berfungsi. Kemudian lihat tentang mengambil kode itu dan memindahkannya ke VB.NET (dan TVPs bekerja di .NET sehingga akan port dengan baik).Apa yang kita tidak tahu yang masih bisa membantu:
PEMBARUAN 1:
** Tampaknya ada beberapa kebingungan tentang apa yang VBA (Visual Basic for Applications) dan apa yang dapat dilakukan dengannya, jadi ini hanya untuk memastikan kita semua berada di halaman web yang sama:
PEMBARUAN 2:
Satu hal lagi yang perlu dipertimbangkan: Bagaimana koneksi ditangani? Apakah kode VBA membuka dan menutup Koneksi per setiap operasi, atau apakah itu membuka koneksi pada awal proses dan menutupnya pada akhir proses (yaitu 7 jam kemudian)? Bahkan dengan penyatuan koneksi (yang, secara default, harus diaktifkan untuk ADO), masih harus ada dampak yang cukup antara membuka dan menutup sekali sebagai lawan membuka dan menutup baik 800.200 atau 1.600.000 kali. Nilai-nilai tersebut didasarkan pada setidaknya 800.000 UPDATE ditambah 200 atau 800k EXEC (tergantung pada seberapa sering prosedur yang tersimpan filter sebenarnya dieksekusi).
Masalah terlalu banyak koneksi ini secara otomatis dikurangi dengan rekomendasi yang saya uraikan di atas. Dengan membuat transaksi dan melakukan semua UPDATE dalam transaksi itu, Anda akan menjaga agar koneksi tetap terbuka dan menggunakannya kembali untuk masing-masingnya
UPDATE
. Apakah koneksi tetap terbuka dari panggilan awal untuk mendapatkan 4000 baris per yang ditentukanFileID
, atau ditutup setelah operasi "dapatkan" dan dibuka lagi untuk UPDATE, jauh lebih tidak berdampak karena kita sekarang berbicara tentang perbedaan antara keduanya 200 atau 400 total koneksi di seluruh proses.PEMBARUAN 3:
Saya melakukan beberapa pengujian cepat. Perlu diingat bahwa ini adalah tes skala yang agak kecil, dan bukan operasi yang sama persis (INSERT murni vs EXEC + PEMBARUAN). Namun, perbedaan waktu terkait dengan bagaimana koneksi dan transaksi ditangani masih relevan, maka informasi tersebut dapat diekstrapolasi untuk memiliki dampak yang relatif sama di sini.
Parameter uji:
Meja:
Operasi:
TRUNCATE TABLE dbo.ManyInserts;
(mengingat sifat dari tes ini, melakukan FREEPROCCACHE, FREESYSTEMCACHE, dan DROPCLEANBUFFERS tampaknya tidak menambah banyak nilai.)Hasil:
Seperti yang Anda lihat, bahkan jika koneksi ADO ke DB sudah dibagikan di semua operasi, pengelompokan mereka ke dalam batch menggunakan transaksi eksplisit (objek ADO harus dapat menangani ini) dijamin secara signifikan (yaitu lebih dari 2x peningkatan) mengurangi waktu proses keseluruhan.
sumber
IMHO dan bekerja dari asumsi bahwa tidak layak untuk kembali kode sub VBA ke dalam SQL, sudahkah Anda mempertimbangkan untuk membiarkan skrip VBA selesai mengevaluasi dalam file Excel dan kemudian menulis hasilnya kembali ke SQL server melalui SSIS?
Anda bisa membuat sub VBA mulai dan berakhir dengan membalik indikator baik dalam objek sistem file atau di server (jika Anda sudah mengkonfigurasi koneksi untuk menulis kembali ke server) dan kemudian menggunakan ekspresi SSIS untuk memeriksa indikator ini untuk
disable
properti dari tugas yang diberikan dalam solusi SSIS Anda (sehingga proses impor menunggu sampai sub VBA selesai jika Anda khawatir tentang hal itu melampaui jadwalnya).Selain itu, Anda dapat membuat skrip VBA mulai terprogram (sedikit miring, tetapi saya telah menggunakan
workbook_open()
properti untuk memicu tugas "memecat dan melupakan" jenis ini di masa lalu).Jika waktu evaluasi skrip VB mulai menjadi masalah, Anda bisa melihat apakah pengembang VB Anda bersedia dan mampu mem-port-kan kodenya ke dalam tugas skrip VB dalam solusi SSIS - dalam pengalaman saya aplikasi Excel menarik banyak overhead saat bekerja dengan data pada volume ini.
sumber