Setiap kali percakapan dimulai tentang menggunakan berbagai basis data sebagai sumber data, topik pengidentifikasi rekaman, objek, atau sesuatu yang lain muncul. Terkadang koordinasi protokol pertukaran dapat dipertimbangkan oleh para peserta selama beberapa bulan. int
- bigint
- guid
, lalu dalam lingkaran. Untuk tugas volume, dengan mempertimbangkan bahwa secara asli di R tidak ada dukungan bigint
(kapasitas ~ 2 ^ 64), pilihan penyajian yang benar dari pengidentifikasi tersebut dapat menjadi penting dalam hal kinerja. Apakah ada solusi yang jelas dan universal? Berikut adalah beberapa pertimbangan praktis yang dapat digunakan dalam proyek sebagai tes lakmus.
Sebagai aturan, pengidentifikasi akan digunakan untuk tiga kelas tugas:
- pengelompokan;
- penyaringan
- asosiasi.
Berdasarkan ini, kami akan mengevaluasi berbagai pendekatan.
Ini adalah kelanjutan dari publikasi sebelumnya .
Simpan sebagai string
Pilihan untuk data kecil cukup bagus. Di sini dan kemampuan untuk mengambil setiap panjang pengidentifikasi, dan kemampuan untuk mendukung tidak hanya numerik, tetapi juga pengidentifikasi alfanumerik. Keuntungan tambahan adalah kemampuan dijamin untuk menerima data dengan benar melalui protokol basis data non-asli, misalnya, melalui API REST gateway.
Kontra juga jelas. Konsumsi memori yang tinggi, peningkatan volume informasi dari database, penurunan kinerja baik pada level jaringan maupun pada level komputasi.
Kami menggunakan paket bit64
Banyak yang hanya mendengar nama paket ini mungkin berpikir bahwa ini dia, solusi yang tepat. Sayangnya, ini tidak sepenuhnya benar. Tidak hanya ini add-on di atas numeric
(kutipan: ' Sekali lagi pilihannya jelas: R hanya memiliki satu tipe data 64 bit: ganda. Dengan menggunakan ganda,
integer64 mewarisi beberapa fungsi seperti is.atomic, panjang, panjang <-, nama, nama <-, redup, redup <-, nama kecil, nama kecil. ' ), jadi masih ada perluasan besar-besaran aritmatika dasar dan tidak ada jaminan bahwa itu tidak akan meledak di mana pun dan tidak akan ada konflik dengan paket lain.
Kami menggunakan tipe numeric
Ini adalah trik yang sepenuhnya benar, yang merupakan kompromi yang baik bagi mereka yang tahu apa yang sebenarnya akan disembunyikan dalam respons int64
dari database. Lagi pula, tidak semua 64 bit benar-benar akan terlibat di sana. Seringkali ada jumlah yang jauh lebih sedikit dari 2 ^ 64.
Solusi semacam itu dimungkinkan karena spesifikasi format floating-point presisi ganda. Detail dapat ditemukan di artikel format floating-point presisi ganda populer.
The 53-bit significand precision gives from 15 to 17 significant decimal digits precision (2−53 ≈ 1.11 × 10−16). If a decimal string with at most 15 significant digits is converted to IEEE 754 double-precision representation, and then converted back to a decimal string with the same number of digits, the final result should match the original string. If an IEEE 754 double-precision number is converted to a decimal string with at least 17 significant digits, and then converted back to double-precision representation, the final result must match the original number.
Jika Anda memiliki 15 atau lebih sedikit angka desimal di pengidentifikasi, Anda dapat menggunakan numeric
dan tidak khawatir.
Trik yang sama baik ketika Anda perlu bekerja dengan data sementara, terutama yang mengandung milidetik. Mentransfer data sementara melalui jaringan dalam bentuk teks memerlukan waktu, selain itu, di sisi penerima, Anda perlu menjalankan parser teks -> POSIXct
, yang juga sangat intensif sumber daya ( POSIXct
kinerja pada waktu tertentu). Transfer dalam bentuk biner bukan fakta bahwa semua driver akan mendukung transfer zona waktu dan milidetik. Tetapi transmisi waktu yang akurat ke milidetik di zona UTC dalam representasi cap waktu unix (13 tempat desimal) sangat baik dan tanpa kehilangan disediakan oleh format numeric
.
Tidak begitu sederhana dan jelas
Jika kita melihat lebih dekat pada versi dengan garis, kejelasan dan kategorisasi dari pernyataan awal sedikit berkurang. Bekerja dengan string dalam R tidak cukup mudah, bahkan menghilangkan nuansa menyelaraskan blok memori dan prefetching. Dilihat oleh buku-buku dan dokumentasi yang mendalam, variabel string tidak disimpan sendiri dalam suatu variabel, tetapi ditempatkan dalam kumpulan string global. Semua garis. Dan kumpulan ini digunakan oleh array string untuk mengurangi konsumsi memori. Yaitu vektor teks akan menjadi kumpulan garis di kumpulan global + vektor tautan ke rekaman dari kumpulan ini.
library(tidyverse) library(magrittr) library(stringi) library(gmp) library(profvis) library(pryr) library(rTRNG) set.seed(46572) RcppParallel::setThreadOptions(numThreads = parallel::detectCores() - 1)
Kita melihat bahwa bahkan tanpa naik ke level C ++, hipotesisnya tidak jauh dari kebenaran. Volume vektor string hampir bersamaan dengan volume pointer 64-bit, dan variabel itu sendiri memakan ruang jauh lebih sedikit daripada file pada disk.
File size: 62M. Constructed from file object's (m2) size: 7.65M. Pure pointer's size: 7.63M
Dan isi vektor sebelum menulis dan setelah membaca identik - resp. elemen vektor merujuk ke blok memori yang sama.
Jadi melihat lebih dekat pada penggunaan string teks sebagai pengidentifikasi tampaknya bukan ide gila. Benchmark untuk pengelompokan, pemfilteran, dan penggabungan, menggunakan dplyr
dan data.table
memberikan bacaan yang hampir sama untuk pengenal numeric
dan character
, yang memberikan konfirmasi tambahan optimasi karena kumpulan global. Lagi pula, pekerjaan sedang dilakukan dengan pointer yang ukurannya baik 32 atau 64 bit, tergantung pada rakitan R (32/64), dan ini tepatnya jenis numeric
.
Omong-omong, ukuran maksimum memori R yang tersedia dapat dilihat dengan perintah fs::fs_bytes(memory.limit())
.
Sejujurnya, perlu dicatat bahwa dplyr
tidak selalu memiliki dplyr
cepat, lihat kasus "Bergabung dengan kolom karakter lambat, dibandingkan dengan bergabung dengan kolom faktor. # 1386 {Closed}" . Utas ini mengusulkan untuk menggunakan kemampuan kumpulan global string dan membandingkan bukan string seperti itu, tetapi pointer ke string.
Rincian Manajemen Memori
Sumber dasar
Kesimpulan
Secara alami, pertanyaan ini selalu ditanyakan dalam satu atau lain bentuk, sejumlah tautan di bawah ini.
Tetapi untuk secara sadar memahami apa yang harus dilakukan dengan benar, apa peluang dan keterbatasannya, yang terbaik adalah turun ke level serendah mungkin. Ternyata, ada massa spesifik tidak jelas. Publikasi bersifat penelitian, karena mempengaruhi aspek-aspek R yang cukup mendasar, yang hanya sedikit digunakan orang dalam pekerjaan sehari-hari mereka. Jika ada tambahan, komentar, atau koreksi yang signifikan, akan sangat menarik untuk mengenal mereka.
Publikasi sebelumnya adalah "Menggunakan R untuk Tugas Utilitas" .