Struktur data yang memungkinkan pencarian berbasis tag yang efisien

11

Saya mencari struktur data yang sangat efisien untuk penyimpanan data yang mirip dengan yang berikut ini.

Id Tags Order1 Order2 
--------------------------
1 1,2 1 1
2 2,5 2 3
3 1,7 4 7
4 6 3 0

Saya harus dapat menanyakan struktur ini sedemikian rupa sehingga akan memberi saya daftar semua id yang berisi ekspresi tag - mendukung ANDdan ORdan NOToperasi. Misalnya. ((1 atau 2) dan bukan 7)

Saya juga harus dapat menentukan urutan hasil (Order1 atau Order2) dan dapat menentukan baris maksimum yang dikembalikan dengan offset opsional. Kinerja untuk pengambilan 30-100 hasil pertama adalah kuncinya.

Akhirnya, saya membutuhkan cara yang murah untuk mencari "hubungan tag" misalnya saya ingin tahu tag mana yang "berhubungan" dengan tag (1 ATAU 2) dan dalam frekuensi berapa. Berarti tag mana yang muncul dalam set yang sama dengan 1 ATAU 2 ... dipesan berdasarkan frekuensi.

Adakah gagasan tentang struktur data apa (atau sekumpulan struktur) yang sangat efisien untuk jenis pekerjaan ini?

(Saya ingin menggunakan ini sebagai bukti konsep untuk mendesain ulang halaman yang ditandai dari keluarga situs SE)

Sam Saffron
sumber
1
Hanya komentar (mungkin sepele). Mengapa Anda tidak mengandalkan sistem manajemen basis data relasional? Anda dapat mendefinisikan tabel dengan pasangan <id, tag> dan menambahkan indeks pada kolom tag. Kemudian Anda bisa menggunakan kueri SQL standar untuk mengekstraksi data. RDBMS secara efisien akan melakukan pekerjaan "kotor" optimasi permintaan dan penyortiran keluaran.
Marzio De Biasi
@Vor, ekspresinya sangat tidak efisien pada skala tinggi, self joins menjadi query mimpi buruk.
Sam Saffron
@ Sam: ok. Tugas Anda cukup umum sehingga saya pikir RDBMS yang baik (dengan alat penambangan data) dapat melakukan pekerjaan itu. Saya meninggalkan lantai ke ahli struktur data. :-)
Marzio De Biasi
Saya percaya mengizinkan semua kombinasi AND, ATAU, BUKAN akan menyulitkan untuk membuat struktur data yang tidak mencantumkan semua item (mungkin bisa terbatas pada 3-CNF?). Jika tidak ada batasan seperti itu, maka mungkin jalankan melalui catatan (dalam urutan yang ditentukan) sampai Anda menemukan 30-100 yang melewati persyaratan tag Anda. Meskipun, secara umum, saya setuju dengan saran Vor menggunakan database untuk melakukan pekerjaan berat untuk Anda.
bbejot
Bukan ahli, tetapi saya pikir jika Anda tidak membatasi cara Anda dapat bertanya tentang tag maka itu akan sulit. Membatasi mereka ke CNF (seperti yang disarankan bbejot) adalah satu cara, yang lain membatasi jumlah tag berbeda yang dapat ditanyakan oleh sejumlah kecil (mis. 6).
Kaveh

Jawaban:

6

Ini bukan jawaban yang tepat untuk struktur data yang efisien, tetapi lebih merupakan uraian atas komentar @bbejot dan @Kaveh yang memberikan argumen melambaikan tangan untuk alasan mengapa dengan pertanyaan saat ini kita seharusnya tidak mengharapkan sesuatu yang jauh lebih baik daripada mencari di seluruh basis data. Argumen ini didasarkan pada pengurangan dari SAT, hipotesis waktu eksponensial , dan banyak lambaian tangan.

nx|x|=nxj=1jxj=012nkkANDORNOTn2n

Kami seharusnya tidak mengharapkan pencarian efisien dalam panjang kueri (dengan reduksi menjadi SAT). Kita juga seharusnya tidak berharap jauh lebih baik daripada melihat semua item dalam database dengan hipotesis waktu eksponensial.

n1

Artem Kaznatcheev
sumber
Pengamatan yang bagus. Setiap pertanyaan memiliki paling banyak 5 tag, jadi kueri tentang tag setara dengan 5-CNF.
Kaveh
Terima kasih! ya kita dapat mengasumsikan 5-CNF di sini lebih lanjut, perilaku penandaan tidak acak. Secara umum orang akan memberi tag pada barang dengan tag yang paling umum, sehingga akan memungkinkan beberapa pintasan lainnya.
Sam Saffron
1
@ Kaveh, kami akhirnya menggulung struktur memori. Ada beberapa cara pintas non-sepele, sort adalah bottleneck, menggunakan heap sort atau sort cepat yang dimodifikasi memungkinkan Anda untuk secara efisien memilih top N tanpa perlu melakukan sortasi penuh. jenis pra-perhitungan memungkinkan Anda untuk memilih pivot lebih efisien dan menghindari jenis ketika pemindaian penuh diperlukan. multithreading mempercepat pilihan. banyak pekerjaan dapat ditunda ke latar belakang sebelum pengguna berinteraksi dengan struktur. luar biasa struktur dalam-memori kami adalah rata-rata 0ms untuk pencarian pada set data stack overflow.
Sam Saffron
@SamSaffron - Di mana post MSO merinci fitur ini? Kami punya laporan bug di sini .
Kevin Vermeer
5

Ini adalah jawaban yang cukup mudah, tetapi saya pikir efektif:

Map Tag ([Id],[Id])O(log(n))

Map Id (Set Tag)IdO(nlog(m))

sclv
sumber
Saya cenderung setuju bahwa beberapa struktur yang sangat sederhana seperti peta yang digulung beberapa kali mungkin merupakan cara terbaik untuk pergi ke sini. memori murah dan mempertahankan banyak cache tidak terlalu sulit
Sam Saffron