Saya berasal dari latar belakang database relasional dan mencoba bekerja dengan DynamoDB amazon
Saya memiliki tabel dengan kunci hash "DataID" dan rentang "CreatedAt" dan banyak item di dalamnya.
Saya mencoba untuk mendapatkan semua item yang dibuat setelah tanggal tertentu dan diurutkan berdasarkan tanggal. Yang cukup mudah dalam database relasional.
Di DynamoDB, hal terdekat yang bisa saya temukan adalah kueri dan menggunakan kunci rentang yang lebih besar dari filter. Satu-satunya masalah adalah bahwa untuk melakukan kueri saya memerlukan kunci hash yang mengalahkan tujuan tersebut.
Jadi apa yang saya lakukan salah? Apakah skema tabel saya salah, bukankah kunci hash harus unik? atau adakah cara lain untuk menanyakan?
sumber
CreatedAt
lebih besar dari titik tertentu.Mengingat struktur tabel Anda saat ini, hal ini saat ini tidak mungkin dilakukan di DynamoDB. Tantangan terbesarnya adalah untuk memahami bahwa kunci Hash dari tabel (partisi) harus diperlakukan seperti membuat tabel terpisah. Dalam beberapa hal, ini benar-benar hebat (pikirkan kunci partisi seperti membuat tabel baru untuk setiap pengguna atau pelanggan, dll ...).
Permintaan hanya dapat dilakukan di satu partisi. Itu benar-benar akhir dari cerita ini. Ini berarti jika Anda ingin melakukan kueri berdasarkan tanggal (Anda ingin menggunakan msec sejak epoch), maka semua item yang ingin Anda ambil dalam satu kueri harus memiliki Hash (kunci partisi) yang sama.
Saya harus memenuhi syarat ini. Anda benar-benar bisa
scan
berdasarkan kriteria yang Anda cari, itu tidak masalah, tetapi itu berarti Anda akan melihat setiap baris dalam tabel Anda, dan kemudian memeriksa apakah baris itu memiliki tanggal yang sesuai dengan parameter Anda. Ini sangat mahal, terutama jika Anda berada di bisnis menyimpan acara berdasarkan tanggal di tempat pertama (yaitu Anda memiliki banyak baris.)Anda mungkin tergoda untuk meletakkan semua data dalam satu partisi untuk menyelesaikan masalah, dan Anda benar-benar bisa, namun throughput Anda akan sangat rendah, mengingat setiap partisi hanya menerima sebagian kecil dari jumlah total yang ditetapkan.
Hal terbaik yang harus dilakukan adalah menentukan partisi yang lebih berguna untuk dibuat guna menyimpan data:
Apakah Anda benar-benar perlu melihat semua baris, atau hanya baris oleh pengguna tertentu?
Apakah boleh mempersempit daftar berdasarkan Bulan, dan melakukan beberapa kueri (satu untuk setiap bulan)? Atau menurut tahun?
Jika Anda melakukan analisis deret waktu, ada beberapa opsi, ubah kunci partisi menjadi sesuatu yang dihitung
PUT
agarquery
lebih mudah, atau gunakan produk aws lain seperti kinesis yang cocok untuk pencatatan hanya-tambahan.sumber
yyyy
dan hash itu, tetapi juga buatcreated
tanggal yang dapat Anda gunakan sebagai kunci rentang Anda. Kemudian Anda mendapatkan 10GB data per tahun (27 MB per hari) yang mungkin bagus untuk lebih banyak situasi. Ini berarti bahwa Anda harus membuat kueri per tahun ketika kueri tanggal melewati batas tahun, tetapi setidaknya itu akan berfungsi dan itu lebih aman daripada membuat kunci hash tiruan.Pendekatan yang saya ikuti untuk mengatasi masalah ini adalah dengan membuat Indeks Sekunder Global seperti di bawah ini. Tidak yakin apakah ini pendekatan terbaik tapi semoga bermanfaat bagi seseorang.
Batasan diberlakukan pada pengguna HTTP API untuk menentukan jumlah hari untuk mengambil data, defaultnya adalah 24 jam.
Dengan cara ini, saya selalu dapat menentukan HashKey sebagai hari tanggal saat ini dan RangeKey dapat menggunakan operator> dan <saat mengambil. Dengan cara ini, data juga tersebar di beberapa bagian.
sumber
Kunci Hash Anda (jenis primer) harus unik (kecuali Anda memiliki rentang seperti yang dinyatakan oleh orang lain).
Dalam kasus Anda, untuk menanyakan tabel Anda, Anda harus memiliki indeks sekunder.
Hash Key Anda adalah ID Indeks sekunder Anda didefinisikan sebagai: DataID-Created-index (itulah nama yang akan digunakan DynamoDB)
Kemudian, Anda dapat membuat kueri seperti ini:
Pada dasarnya kueri Anda terlihat seperti:
Indeks sekunder akan meningkatkan unit kapasitas baca / tulis yang diperlukan sehingga Anda perlu mempertimbangkannya. Masih jauh lebih baik daripada melakukan pemindaian, yang akan mahal dalam pembacaan dan pada waktunya (dan saya dibatasi hingga 100 item).
Ini mungkin bukan cara terbaik untuk melakukannya, tetapi bagi seseorang yang terbiasa dengan RD (saya juga terbiasa dengan SQL), ini adalah cara tercepat untuk menjadi produktif. Karena tidak ada batasan terkait skema, Anda dapat menyiapkan sesuatu yang berfungsi dan setelah Anda memiliki bandwidth untuk bekerja dengan cara yang paling efisien, Anda dapat mengubah berbagai hal.
sumber
Anda dapat membuat kunci Hash menjadi sesuatu di sepanjang baris id 'kategori produk', kemudian kunci rentang sebagai kombinasi cap waktu dengan id unik yang ditambahkan di akhir. Dengan cara itu Anda mengetahui kunci hash dan masih dapat menanyakan tanggal dengan lebih dari.
sumber
Anda dapat memiliki beberapa kunci hash yang identik; tetapi hanya jika Anda memiliki kunci rentang yang bervariasi. Anggap saja seperti format file; Anda dapat memiliki 2 file dengan nama yang sama di folder yang sama selama formatnya berbeda. Jika formatnya sama, namanya harus berbeda. Konsep yang sama berlaku untuk kunci hash / range DynamoDB; anggap saja hash sebagai nama dan rentang sebagai formatnya.
Juga, saya tidak ingat apakah mereka memiliki ini pada saat OP (saya tidak percaya mereka memilikinya), tetapi mereka sekarang menawarkan Indeks Sekunder Lokal.
Pemahaman saya tentang ini adalah bahwa sekarang memungkinkan Anda untuk melakukan kueri yang diinginkan tanpa harus melakukan pemindaian penuh. Sisi negatifnya adalah indeks ini harus ditentukan saat pembuatan tabel, dan juga (saya yakin) tidak boleh kosong saat membuat item. Selain itu, mereka membutuhkan throughput tambahan (meskipun biasanya tidak sebanyak pemindaian) dan penyimpanan, jadi ini bukan solusi sempurna, tetapi alternatif yang layak, untuk beberapa.
Saya masih merekomendasikan jawaban Mike Brant sebagai metode yang disukai dalam menggunakan DynamoDB; dan menggunakan metode itu sendiri. Dalam kasus saya, saya hanya memiliki tabel pusat dengan hanya kunci hash sebagai ID saya, kemudian tabel sekunder yang memiliki hash dan rentang yang dapat ditanyakan, lalu item tersebut menunjukkan kode ke "item yang diminati" di tabel pusat, secara langsung .
Data tambahan terkait indeks sekunder dapat ditemukan di dokumentasi DynamoDB Amazon di sini bagi mereka yang tertarik.
Bagaimanapun, semoga ini akan membantu orang lain yang terjadi pada utas ini.
sumber
Jawaban yang Diperbarui Tidak ada cara mudah untuk melakukan ini menggunakan Kueri DB Dynamo dengan hasil yang dapat diprediksi. Satu opsi (sub optimal) adalah menggunakan GSI dengan HashKey & CreatedAt buatan. Kemudian kueri dengan HashKey saja dan sebutkan ScanIndexForward untuk memesan hasilnya. Jika Anda dapat membuat HashKey alami (katakanlah kategori item, dll.) Maka metode ini adalah pemenangnya. Di sisi lain, jika Anda menyimpan HashKey yang sama untuk semua item, maka itu akan memengaruhi throughput sebagian besar ketika kumpulan data Anda tumbuh melebihi 10GB (satu partisi)
Jawaban Asli: Anda dapat melakukannya sekarang di DynamoDB dengan menggunakan GSI. Jadikan kolom "CreatedAt" sebagai GSI dan masalah kueri seperti (GT some_date). Simpan tanggal sebagai angka (mdet sejak masa) untuk jenis kueri ini.
Detail tersedia di sini: Indeks Sekunder Global - Amazon DynamoDB: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html#GSI.
Ini adalah fitur yang sangat kuat. Ketahuilah bahwa kueri terbatas pada (EQ | LE | LT | GE | GT | BEGINS_WITH | BETWEEN) Kondisi - Amazon DynamoDB: http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html
sumber
CreatedAt
seharusnya itu adalah kunci rentang GSI, Anda harus memilih kunci hash - dan kemudian Anda kembali ke tempat Anda memulai, karena Anda hanya dapat meminta GTCreatedAt
untuk nilai tertentu dari kunci hash.