Saya memiliki tabel yang dapat dibuat dan diisi dengan kode berikut:
CREATE TABLE dbo.Example(GroupKey int NOT NULL, RecordKey varchar(12) NOT NULL);
ALTER TABLE dbo.Example
ADD CONSTRAINT iExample PRIMARY KEY CLUSTERED(GroupKey ASC, RecordKey ASC);
INSERT INTO dbo.Example(GroupKey, RecordKey)
VALUES (1, 'Archimedes'), (1, 'Newton'), (1, 'Euler'), (2, 'Euler'), (2, 'Gauss'),
(3, 'Gauss'), (3, 'Poincaré'), (4, 'Ramanujan'), (5, 'Neumann'),
(5, 'Grothendieck'), (6, 'Grothendieck'), (6, 'Tao');
Untuk semua baris yang memiliki jarak kolaborasi terbatas berdasarkan RecordKey
dengan baris lain, saya ingin menetapkan nilai unik — saya tidak peduli bagaimana atau tipe data apa nilai uniknya.
Rangkaian hasil yang benar yang memenuhi apa yang saya minta dapat dihasilkan dengan kueri berikut:
SELECT 1 AS SupergroupKey, GroupKey, RecordKey
FROM dbo.Example
WHERE GroupKey IN(1, 2, 3)
UNION ALL
SELECT 2 AS SupergroupKey, GroupKey, RecordKey
FROM dbo.Example
WHERE GroupKey = 4
UNION ALL
SELECT 3 AS SupergroupKey, GroupKey, RecordKey
FROM dbo.Example
WHERE GroupKey IN(5, 6)
ORDER BY SupergroupKey ASC, GroupKey ASC, RecordKey ASC;
Untuk lebih membantu apa yang saya minta, saya akan menjelaskan mengapa GroupKey
1–3 memiliki hal yang sama SupergroupKey
:
GroupKey
1 berisiRecordKey
Euler yang pada gilirannya terkandung dalamGroupKey
2; jadiGroupKey
s 1 dan 2 harus memiliki yang samaSupergroupKey
.- Karena Gauss terkandung dalam
GroupKey
s 2 dan 3, mereka juga harus memiliki yang samaSupergroupKey
. Ini mengarah keGroupKey
s 1-3 memiliki hal yang samaSupergroupKey
. - Karena
GroupKey
s 1–3 tidak membagikan apa punRecordKey
dengan yang tersisaGroupKey
, mereka adalah satu-satunya yang diberiSupergroupKey
nilai 1.
Saya harus menambahkan bahwa solusinya harus generik. Tabel di atas dan set hasil hanyalah sebuah contoh.
Tambahan
Saya menghapus persyaratan agar solusi tidak berulang. Sementara saya lebih suka solusi seperti itu, saya percaya itu adalah kendala yang tidak masuk akal. Sayangnya, saya tidak dapat menggunakan solusi berbasis CLR; tetapi jika Anda ingin memasukkan solusi seperti itu, jangan ragu untuk melakukannya. Saya kemungkinan tidak akan menerimanya sebagai jawaban.
Jumlah baris di meja saya yang sebenarnya adalah sebesar 5 juta, tetapi ada hari-hari ketika jumlah baris "hanya" akan sekitar sepuluh ribu. Rata-rata ada 8 RecordKey
detik per GroupKey
dan 4 GroupKey
detik per RecordKey
. Saya membayangkan bahwa suatu solusi akan memiliki kompleksitas waktu yang eksponensial, tetapi saya tetap tertarik pada suatu solusi.
sumber
Masalah ini adalah tentang mengikuti tautan antar item. Ini menempatkannya dalam ranah grafik dan pemrosesan grafik. Secara khusus, seluruh dataset membentuk grafik dan kami sedang mencari komponen dari grafik itu. Ini dapat diilustrasikan oleh sebidang data sampel dari pertanyaan.
Pertanyaannya mengatakan kita bisa mengikuti GroupKey atau RecordKey untuk menemukan baris lain yang berbagi nilai itu. Jadi kita bisa memperlakukan keduanya sebagai simpul dalam grafik. Pertanyaan selanjutnya menjelaskan bagaimana GroupKeys 1–3 memiliki SupergroupKey yang sama. Ini dapat dilihat sebagai gugusan di sebelah kiri yang bergabung dengan garis tipis. Gambar juga menunjukkan dua komponen lain (SupergroupKey) yang dibentuk oleh data asli.
SQL Server memiliki beberapa kemampuan pemrosesan grafik yang dibangun ke T-SQL. Namun, saat ini cukup sedikit, dan tidak membantu dengan masalah ini. SQL Server juga memiliki kemampuan untuk memanggil R dan Python, dan paket yang kaya & kuat tersedia untuk mereka. Salah satunya adalah igraph . Ini ditulis untuk "penanganan cepat grafik besar, dengan jutaan simpul dan tepi ( tautan )."
Menggunakan R dan igraph saya dapat memproses satu juta baris dalam 2 menit 22 detik dalam pengujian lokal 1 . Inilah perbandingannya dengan solusi terbaik saat ini:
Saat memproses baris 1M, 1m40 digunakan untuk memuat & memproses grafik, dan memperbarui tabel. Diperlukan 42s untuk mengisi tabel hasil SSMS dengan output.
Pengamatan Task Manager sementara 1M baris diproses menunjukkan sekitar 3GB memori kerja diperlukan. Ini tersedia di sistem ini tanpa paging.
Saya bisa mengkonfirmasi penilaian Ypercube tentang pendekatan CTE rekursif. Dengan beberapa ratus tombol rekam, ia menghabiskan 100% CPU dan semua RAM yang tersedia. Akhirnya tempdb tumbuh lebih dari 80GB dan SPID jatuh.
Saya menggunakan meja Paul dengan kolom SupergroupKey sehingga ada perbandingan yang adil antara solusi.
Untuk beberapa alasan R keberatan dengan aksen pada Poincaré. Mengubahnya menjadi "e" biasa memungkinkannya untuk berjalan. Saya tidak menyelidiki karena itu tidak berhubungan dengan masalah yang dihadapi. Saya yakin ada solusinya.
Ini kodenya
Inilah yang dilakukan kode R
@input_data_1
adalah cara SQL Server mentransfer data dari tabel ke kode R dan menerjemahkannya ke bingkai data R yang disebut InputDataSet.library(igraph)
mengimpor perpustakaan ke lingkungan eksekusi R.df.g <- graph.data.frame(d = InputDataSet, directed = FALSE)
memuat data ke objek igraph. Ini adalah grafik yang tidak diarahkan karena kita dapat mengikuti tautan dari grup ke record atau record ke group. InputDataSet adalah nama default SQL Server untuk dataset yang dikirim ke R.cpts <- components(df.g, mode = c("weak"))
proses grafik untuk menemukan sub-grafik terpisah (komponen) dan langkah-langkah lainnya.OutputDataSet <- data.frame(cpts$membership)
SQL Server mengharapkan bingkai data kembali dari R. Nama default-nya adalah OutputDataSet. Komponen disimpan dalam vektor yang disebut "keanggotaan". Pernyataan ini menerjemahkan vektor ke bingkai data.OutputDataSet$VertexName <- V(df.g)$name
V () adalah vektor simpul dalam grafik - daftar GroupKeys dan RecordKeys. Ini menyalinnya ke dalam bingkai data ouput, membuat kolom baru bernama VertexName. Ini adalah kunci yang digunakan untuk mencocokkan dengan tabel sumber untuk memperbarui SupergroupKey.Saya bukan ahli R. Kemungkinan ini bisa dioptimalkan.
Data Uji
Data OP digunakan untuk validasi. Untuk tes skala saya menggunakan skrip berikut.
Saya baru saja menyadari bahwa saya mendapatkan rasio yang salah dari definisi OP. Saya tidak percaya ini akan mempengaruhi timing. Catatan & Grup simetris dengan proses ini. Untuk algoritme mereka semua hanya simpul dalam grafik.
Dalam pengujian data selalu membentuk komponen tunggal. Saya percaya ini karena distribusi data yang seragam. Jika alih-alih rasio statis 1: 8 yang dikodekan ke dalam rutinitas pembangkitan, saya telah membiarkan rasionya bervariasi, lebih mungkin ada komponen lebih lanjut.
1 Spesifikasi mesin: Microsoft SQL Server 2017 (RTM-CU12), Edisi Pengembang (64-bit), Windows 10 Home. RAM 16GB, SSD, 4 core hyperthreaded i7, 2,8GHz nominal. Pengujian adalah satu-satunya item yang berjalan pada saat itu, selain aktivitas sistem normal (sekitar 4% CPU).
sumber
Metode CTE rekursif - yang cenderung sangat tidak efisien dalam tabel besar:
Diuji dalam dbfiddle.uk
sumber