

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Praktik terbaik untuk menggunakan operasi data massal di DynamoDB
<a name="BestPractices_BulkDataOperations"></a>

DynamoDB mendukung operasi batch `BatchWriteItem` seperti menggunakan yang Anda dapat melakukan hingga `PutItem` 25 `DeleteItem` dan permintaan bersama-sama. Namun, `BatchWriteItem` tidak mendukung `UpdateItem` operasi. Ketika datang ke pembaruan massal, perbedaannya terletak pada persyaratan dan sifat pembaruan. Anda dapat menggunakan APIs DynamoDB lain `TransactWriteItems` seperti untuk ukuran batch hingga 100. Ketika lebih banyak item terlibat, Anda dapat menggunakan layanan seperti AWS Glue, Amazon EMR, AWS Step Functions atau menggunakan skrip dan alat khusus seperti DynamoDB-Shell untuk pembaruan massal.

**Topics**
+ [Pembaruan batch bersyarat](BestPractices_ConditionalBatchUpdate.md)
+ [Operasi massal yang efisien](BestPractices_EfficientBulkOperations.md)

# Pembaruan batch bersyarat
<a name="BestPractices_ConditionalBatchUpdate"></a>

DynamoDB mendukung operasi batch `BatchWriteItem` seperti menggunakan yang dapat Anda lakukan hingga `PutItem` 25 `DeleteItem` dan permintaan dalam satu batch. Namun, `BatchWriteItem` tidak mendukung `UpdateItem` operasi dan tidak mendukung ekspresi kondisi. Sebagai solusinya, Anda dapat menggunakan DynamoDB lain APIs seperti `TransactWriteItems` untuk ukuran batch hingga 100.

Ketika lebih banyak item terlibat, dan sebagian besar data perlu diubah, Anda dapat menggunakan layanan seperti, Amazon EMR AWS Step Functions , atau menggunakan skrip dan alat khusus seperti AWS Glue DynamoDB-Shell untuk pembaruan massal yang efisien.

**Kapan menggunakan pola ini**
+ DynamoDB-shell tidak didukung untuk kasus penggunaan produksi.
+ `TransactWriteItems`— hingga 100 pembaruan individu dengan atau tanpa kondisi, dijalankan sebagai bundel ACID semua atau tidak sama sekali. `TransactWriteItems`panggilan juga dapat diberikan dengan `ClientRequestToken` jika aplikasi Anda memerlukan idempotensi, yang berarti beberapa panggilan identik memiliki efek yang sama dengan satu panggilan tunggal. Ini memastikan Anda tidak melakukan transaksi yang sama beberapa kali dan berakhir dengan status data yang salah.

  Trade-off - Throughput tambahan dikonsumsi. 2 WCUs per 1KB tulis alih-alih standar 1 WGU per 1 KB tulis.
+ `BatchExecuteStatement`PartiQL — hingga 25 pembaruan dengan atau tanpa kondisi. `BatchExecuteStatement`selalu mengembalikan respons sukses terhadap permintaan keseluruhan, dan juga mengembalikan daftar respons operasi individu yang menjaga ketertiban.

  Trade-off — Untuk batch yang lebih besar, logika sisi klien tambahan diperlukan untuk mendistribusikan permintaan dalam batch 25. Respons kesalahan individu perlu dipertimbangkan untuk menentukan strategi coba lagi.

## Contoh kode
<a name="bp-conditional-code-examples"></a>

Contoh kode ini menggunakan pustaka boto3, yang merupakan AWS SDK untuk Python. Contoh mengasumsikan Anda telah menginstal boto3 dan dikonfigurasi dengan kredenal yang sesuai AWS .

Asumsikan database inventaris untuk vendor alat listrik yang memiliki beberapa gudang di kota-kota Eropa. Karena ini adalah akhir musim panas, vendor ingin membersihkan kipas meja untuk memberi ruang bagi stok lainnya. Vendor ingin memberikan diskon harga untuk semua penggemar meja yang dipasok dari gudang di Italia tetapi hanya jika mereka memiliki stok cadangan 20 kipas meja. Tabel DynamoDB **disebut** inventaris, ia memiliki skema kunci sku **kunci** partisi yang merupakan pengidentifikasi unik untuk setiap produk dan gudang **kunci** Sort yang merupakan pengidentifikasi untuk gudang.

Kode Python berikut menunjukkan cara melakukan pembaruan batch bersyarat ini menggunakan panggilan API. `BatchExecuteStatement`

```
import boto3

client=boto3.client("dynamodb")

before_image=client.query(TableName='inventory', KeyConditionExpression='sku=:pk_val AND begins_with(warehouse, :sk_val)', ExpressionAttributeValues={':pk_val':{'S':'F123'},':sk_val':{'S':'WIT'}}, ProjectionExpression='sku,warehouse,quantity,price')
print("Before update: ", before_image['Items'])

response=client.batch_execute_statement(
        Statements=[
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITTUR1'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITROM1'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITROM2'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITROM5'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITVEN1'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITVEN2'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITVEN3'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
        ],
        ReturnConsumedCapacity='TOTAL'
    )

after_image=client.query(TableName='inventory', KeyConditionExpression='sku=:pk_val AND begins_with(warehouse, :sk_val)', ExpressionAttributeValues={':pk_val':{'S':'F123'},':sk_val':{'S':'WIT'}}, ProjectionExpression='sku,warehouse,quantity,price')
print("After update: ", after_image['Items'])
```

Eksekusi menghasilkan output di bawah ini pada data sampel:

```
Before update:  [{'quantity': {'N': '20'}, 'warehouse': {'S': 'WITROM1'}, 'price': {'N': '40'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '25'}, 'warehouse': {'S': 'WITROM2'}, 'price': {'N': '40'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '28'}, 'warehouse': {'S': 'WITROM5'}, 'price': {'N': '38'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '26'}, 'warehouse': {'S': 'WITTUR1'}, 'price': {'N': '40'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '10'}, 'warehouse': {'S': 'WITVEN1'}, 'price': {'N': '38'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '20'}, 'warehouse': {'S': 'WITVEN2'}, 'price': {'N': '38'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '50'}, 'warehouse': {'S': 'WITVEN3'}, 'price': {'N': '35'}, 'sku': {'S': 'F123'}}]
After update:  [{'quantity': {'N': '20'}, 'warehouse': {'S': 'WITROM1'}, 'price': {'N': '40'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '25'}, 'warehouse': {'S': 'WITROM2'}, 'price': {'N': '35'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '28'}, 'warehouse': {'S': 'WITROM5'}, 'price': {'N': '33'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '26'}, 'warehouse': {'S': 'WITTUR1'}, 'price': {'N': '35'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '10'}, 'warehouse': {'S': 'WITVEN1'}, 'price': {'N': '38'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '20'}, 'warehouse': {'S': 'WITVEN2'}, 'price': {'N': '38'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '50'}, 'warehouse': {'S': 'WITVEN3'}, 'price': {'N': '30'}, 'sku': {'S': 'F123'}}]
```

Karena ini adalah operasi terbatas untuk sistem internal, persyaratan idempotensi belum dipertimbangkan. Dimungkinkan untuk menempatkan pagar tambahan seperti pembaruan harga harus melalui hanya jika harga lebih besar dari 35 dan kurang dari 40 untuk membuat pembaruan lebih kuat.

Atau, kami dapat melakukan operasi pembaruan batch yang sama menggunakan `TransactWriteItems` jika persyaratan idempotensi dan ACID yang lebih ketat. Namun, penting untuk diingat bahwa semua operasi dalam bundel transaksi berjalan atau seluruh bundel gagal.

Mari kita asumsikan kasus di mana ada gelombang panas di Italia dan permintaan untuk penggemar meja telah meningkat tajam. Vendor ingin meningkatkan biaya kipas meja mereka keluar dari setiap gudang di Italia sebesar 20 Euro tetapi badan pengawas hanya mengizinkan kenaikan biaya ini jika biaya saat ini kurang dari 70 Euro di seluruh inventaris mereka. Sangat penting bahwa harga diperbarui di seluruh inventaris sekaligus dan hanya sekali dan hanya jika biayanya kurang dari 70 Euro di masing-masing gudang mereka.

Kode Python berikut menunjukkan cara melakukan pembaruan batch ini menggunakan `TransactWriteItems` panggilan API.

```
import boto3

client=boto3.client("dynamodb")

before_image=client.query(TableName='inventory', KeyConditionExpression='sku=:pk_val AND begins_with(warehouse, :sk_val)', ExpressionAttributeValues={':pk_val':{'S':'F123'},':sk_val':{'S':'WIT'}}, ProjectionExpression='sku,warehouse,quantity,price')
print("Before update: ", before_image['Items'])

response=client.transact_write_items(
        ClientRequestToken='UUIDAWS124',
        TransactItems=[
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITTUR1'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITROM1'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITROM2'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITROM5'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITVEN1'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITVEN2'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITVEN3'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
        ],
        ReturnConsumedCapacity='TOTAL'
    )

after_image=client.query(TableName='inventory', KeyConditionExpression='sku=:pk_val AND begins_with(warehouse, :sk_val)', ExpressionAttributeValues={':pk_val':{'S':'F123'},':sk_val':{'S':'WIT'}}, ProjectionExpression='sku,warehouse,quantity,price')
print("After update: ", after_image['Items'])
```

Eksekusi menghasilkan output di bawah ini pada data sampel:

```
Before update:  [{'quantity': {'N': '20'}, 'warehouse': {'S': 'WITROM1'}, 'price': {'N': '60'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '25'}, 'warehouse': {'S': 'WITROM2'}, 'price': {'N': '55'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '28'}, 'warehouse': {'S': 'WITROM5'}, 'price': {'N': '53'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '26'}, 'warehouse': {'S': 'WITTUR1'}, 'price': {'N': '55'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '10'}, 'warehouse': {'S': 'WITVEN1'}, 'price': {'N': '58'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '20'}, 'warehouse': {'S': 'WITVEN2'}, 'price': {'N': '58'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '50'}, 'warehouse': {'S': 'WITVEN3'}, 'price': {'N': '50'}, 'sku': {'S': 'F123'}}]
After update:  [{'quantity': {'N': '20'}, 'warehouse': {'S': 'WITROM1'}, 'price': {'N': '80'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '25'}, 'warehouse': {'S': 'WITROM2'}, 'price': {'N': '75'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '28'}, 'warehouse': {'S': 'WITROM5'}, 'price': {'N': '73'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '26'}, 'warehouse': {'S': 'WITTUR1'}, 'price': {'N': '75'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '10'}, 'warehouse': {'S': 'WITVEN1'}, 'price': {'N': '78'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '20'}, 'warehouse': {'S': 'WITVEN2'}, 'price': {'N': '78'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '50'}, 'warehouse': {'S': 'WITVEN3'}, 'price': {'N': '70'}, 'sku': {'S': 'F123'}}]
```

Ada beberapa pendekatan untuk melakukan pembaruan batch di DynamoDB. Pendekatan yang sesuai tergantung pada faktor-faktor seperti persyaratan and/or idempotensi ACID, jumlah item yang akan diperbarui, dan keakraban. APIs

# Operasi massal yang efisien
<a name="BestPractices_EfficientBulkOperations"></a>

**Kapan menggunakan pola ini**

Pola-pola ini berguna untuk secara efisien melakukan pembaruan massal pada item DynamoDB.
+ DynamoDB-shell tidak didukung untuk kasus penggunaan produksi.
+ `TransactWriteItems`— hingga 100 pembaruan individu dengan atau tanpa kondisi, dijalankan sebagai bundel ACID semua atau tidak sama sekali 

  Trade-off — Throughput tambahan dikonsumsi, 2 WCUs per 1 KB tulis.
+ `BatchExecuteStatement`PartiQL - hingga 25 pembaruan dengan atau tanpa kondisi

  Trade-off — Logika tambahan diperlukan untuk mendistribusikan permintaan dalam batch 25.
+ AWS Step Functions — operasi massal terbatas tarif untuk pengembang yang akrab dengannya. AWS Lambda

  Trade-off — Waktu eksekusi berbanding terbalik dengan rate-limit. Dibatasi oleh batas waktu fungsi Lambda maksimum. Fungsionalitas mensyaratkan bahwa perubahan data yang terjadi antara baca dan tulis dapat ditimpa. Untuk info selengkapnya, lihat [Mengisi ulang atribut Amazon DynamoDB Time to Live menggunakan Amazon EMR](https://aws.amazon.com/blogs/database/part-2-backfilling-an-amazon-dynamodb-time-to-live-attribute-using-amazon-emr/): Bagian 2.
+ AWS Glue dan Amazon EMR — operasi massal terbatas tarif dengan paralelisme terkelola. Untuk aplikasi atau pembaruan yang tidak sensitif terhadap waktu, opsi ini dapat berjalan di latar belakang hanya menghabiskan sebagian kecil throughput. Kedua layanan menggunakan emr-dynamodb-connector untuk melakukan operasi DynamoDB. Layanan ini melakukan pembacaan besar diikuti dengan penulisan besar item yang diperbarui dengan opsi untuk membatasi nilai.

  Trade-off — Waktu eksekusi berbanding terbalik dengan rate-limit. Fungsionalitas mencakup bahwa perubahan data yang terjadi antara baca dan tulis dapat ditimpa. Anda tidak dapat membaca dari Global Secondary Indexes (GSIs). Lihat, [Mengisi ulang atribut Amazon DynamoDB Time to Live menggunakan Amazon EMR](https://aws.amazon.com/blogs/database/part-2-backfilling-an-amazon-dynamodb-time-to-live-attribute-using-amazon-emr/): Bagian 2.
+ DynamoDB Shell — operasi massal terbatas kecepatan menggunakan kueri mirip SQL. Anda dapat membaca dari GSIs untuk efisiensi yang lebih baik.

  Trade-off — Waktu eksekusi berbanding terbalik dengan rate-limit. Lihat [Menilai operasi massal terbatas di DynamoDB Shell](https://aws.amazon.com/blogs/database/rate-limited-bulk-operations-in-dynamodb-shell/).

## Menggunakan pola
<a name="BestPractices_EfficientBulkOperations_UsingThePattern"></a>

Pembaruan massal dapat memiliki implikasi biaya yang signifikan terutama jika Anda menggunakan mode throughput sesuai permintaan. Ada trade-off antara kecepatan dan biaya jika Anda menggunakan mode throughput yang disediakan. Mengatur parameter batas laju dengan sangat ketat dapat menyebabkan waktu pemrosesan yang sangat besar. Anda dapat secara kasar menentukan kecepatan pembaruan menggunakan ukuran item rata-rata dan batas tarif.

Atau, Anda dapat menentukan jumlah throughput yang diperlukan untuk proses berdasarkan durasi yang diharapkan dari proses pembaruan dan ukuran item rata-rata. Referensi blog yang dibagikan dengan setiap pola memberikan rincian tentang strategi, implementasi, dan batasan penggunaan pola. Untuk informasi selengkapnya, lihat [Pemrosesan massal hemat biaya dengan Amazon DynamoDB](https://aws.amazon.com/blogs/database/cost-effective-bulk-processing-with-amazon-dynamodb/).

Ada beberapa pendekatan untuk melakukan pembaruan massal terhadap tabel DynamoDB langsung. Pendekatan yang sesuai tergantung pada faktor-faktor seperti persyaratan and/or idempotensi ACID, jumlah item yang akan diperbarui dan keakraban. APIs Penting untuk mempertimbangkan trade-off biaya versus waktu, sebagian besar pendekatan yang dibahas di atas memberikan opsi untuk membatasi tingkat throughput yang digunakan oleh pekerjaan pembaruan massal.