

# Paso 4: ejecutar un ejemplo de aplicación
<a name="DAX.client.run-application"></a>

Para ayudarle a probar la funcionalidad de Amazon DynamoDB Accelerator (DAX), puede ejecutar una de las aplicaciones de ejemplo disponibles en la instancia de Amazon EC2.

**Topics**
+ [Node.js y DAX](DAX.client.run-application-nodejs-3.md)
+ [SDK para Go de DAX](DAX.client.run-application-go-2.md)
+ [Java y DAX](DAX.client.run-application-java.md)
+ [.NET y DAX](DAX.client.run-application-dotnet.md)
+ [Python y DAX](DAX.client.run-application-python.md)

# Node.js y DAX
<a name="DAX.client.run-application-nodejs-3"></a>

# Configuración predeterminada de cliente para Node.js
<a name="DAX-client-config-JS"></a>

Al configurar el cliente del SDK de JavaScript de DAX, puede personalizar varios parámetros para optimizar el rendimiento, la gestión de la conexión y la resiliencia a errores. En la siguiente tabla se describe la configuración predeterminada que controla la forma en que el cliente interactúa con el clúster de DAX, incluidos los valores de tiempo de espera, los mecanismos de reintento, la administración de credenciales y las opciones de supervisión del estado. Para obtener más información, consulte [Operaciones de DynamoDBClient](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/dynamodb/).


**Valores predeterminados del cliente del SDK de JS de DAX**  

| Parámetro | Tipo | Descripción | 
| --- | --- | --- | 
|  `region` opcional  |  `string`  |  La Región de AWS que se debe usar para el cliente de DAX (por ejemplo, “us-east-1”). Este parámetro es obligatorio si no se proporciona a través de la variable de entorno.  | 
|  `endpoint` obligatorio  |  `string`  | El punto de conexión del clúster al que se conecta el SDK. Ejemplos: No cifrado: dax-cluster-name.region.amazonaws.com Cifrado: daxs://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com  | 
|  `requestTimeout` predeterminado: 6000 ms  |  `number`  | Esto define el tiempo máximo que el cliente esperará una respuesta de DAX.  | 
|  `writeRetries` predeterminado: 1  |  `number`  | El número de reintentos que se realizarán para las solicitudes de escritura que fallan.  | 
|  `readRetries` predeterminado: 1  |  `number`  | El número de reintentos que se realizarán para las solicitudes de lectura que fallan.  | 
|  `maxRetries` predeterminado: 1  |  `number`  | El número máximo de reintentos para las solicitudes fallidas. Si se establecen readRetries/writeRetries, la configuración establecida en readRetries y writeRetries tiene prioridad sobre maxRetries.  | 
|  `connectTimeout` predeterminado: 10000 ms  |  `number`  | El tiempo de espera (en milisegundos) para establecer una conexión con cualquiera de los nodos del clúster.  | 
|  `maxConcurrentConnections` predeterminado: 100  |  `number`  | Limita el número total de conexiones simultáneas que una instancia de cliente puede crear por nodo en un clúster de DAX.  | 
|  `maxRetryDelay` predeterminado: 7000 ms  |  `number`  | Cuando el servidor DAX indica que es necesaria una recuperación estableciendo el indicador `waitForRecoveryBeforeRetrying` en verdadero, el cliente hará una pausa antes de reintentar los intentos. Durante estos periodos de recuperación, el parámetro `maxRetryDelay` determina el tiempo máximo de espera entre reintentos. Esta configuración específica de recuperación solo se aplica cuando el servidor DAX está en modo de recuperación. Para todos los demás escenarios, el comportamiento de reintentos sigue uno de dos patrones: o bien un retraso exponencial basado en el recuento de reintentos (regido por los parámetros `writeRetries`, `readRetries` o `maxRetries`), o bien un reintento inmediato dependiendo del tipo de excepción.  | 
|  `credentials` opcional  |  `[AwsCredentialIdentity](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-credential-providers/)` \$1 `[AwsCredentialIdentityProvider](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-credential-providers/)`  |  Las credenciales de AWS que se utilizarán para la autenticación de solicitudes. Esto puede proporcionarse como AwsCredentialIdentity o AwsCredentialIdentityProvider. Si no se proporciona, el AWS SDK utilizará automáticamente la cadena de proveedores de credenciales predeterminada. Ejemplo: `\$1 accessKeyId: 'AKIA...', secretAccessKey: '...', sessionToken: '...' \$1` \$1 @default Usa la cadena del proveedor de credenciales de AWS predeterminada.  | 
|  `healthCheckInterval` predeterminado: 5000 ms  |  `number`  | El intervalo (en milisegundos) entre las comprobaciones de estado del clúster. Con un intervalo más bajo se realizarán las comprobaciones con mayor frecuencia.  | 
|  `healthCheckTimeout` predeterminado: 1000 ms  |  `number`  | El tiempo de espera (en milisegundos) para que se complete la comprobación de estado.  | 
|  `skipHostnameVerification` predeterminado: false  |  `boolean`  |  Omitir la verificación del nombre de host de las conexiones TLS. Esto no tiene ningún impacto en los clústeres sin cifrar. De forma predeterminada, se realiza la verificación del nombre de host; si se establece en True, se omitirá la verificación. Asegúrese de comprender las implicaciones de desactivar esta opción, que es la imposibilidad de autenticar el clúster al que se está conectando.   | 
|  `unhealthyConsecutiveErrorCount` predeterminado: 5  |  `number`  | Establece el número de errores consecutivos necesarios para indicar que el nodo se encuentra en un estado incorrecto en el intervalo de comprobación de estado.  | 
|  `clusterUpdateInterval` predeterminado: 4000 ms  |  `number`  | Devuelve el intervalo entre sondeos de miembros del clúster para buscar cambios de pertenencia.  | 
|  `clusterUpdateThreshold` predeterminado: 125  |  `number`  | Devuelve el umbral por debajo del cual no se sondeará el clúster para buscar cambios de pertenencia.  | 
|  `credentailProvider` opcional \$1 predeterminado: nulo  |  `[AwsCredentialIdentityProvider](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-credential-providers/)`  | Proveedor definido por el usuario para las credenciales de AWS utilizadas para autenticar solicitudes a DAX.  | 


**Configuración de paginación para DaxDocument**  

| Nombre | Tipo | Detalle | 
| --- | --- | --- | 
|  `client`  |  DaxDocument  |  Instancia del tipo de DaxDocument.  | 
|  `pageSize`  |  número  |  Determina el número de elementos por página.  | 
|  `startingToken` Opcional  |  any  |  LastEvaluatedKey de la respuesta anterior se puede utilizar para solicitudes posteriores.  | 

Para obtener información sobre el uso de la paginación, consulte [TryDax.js](DAX.client.tutorial-TryDax.md).

# Migración al SDK de Node.js de DAX V3
<a name="DAX.client.run-application-nodejs-3-migrating"></a>

Esta guía de migración lo ayudará en la transición de las aplicaciones Node.js de DAX existentes. El nuevo SDK requiere Node.js 18 o superior e introduce varios cambios importantes en la forma en que estructurará el código de DynamoDB Accelerator. Esta guía lo guiará a través de las diferencias clave, incluidos los cambios de sintaxis, los nuevos métodos de importación y los patrones de programación asincrónica actualizados.

## Uso de DAX de Node.js V2
<a name="DAX.client.run-application-nodejs-3-migrating-V2-usage"></a>

```
const AmazonDaxClient = require('amazon-dax-client');
const AWS = require('aws-sdk');

var region = "us-west-2";

AWS.config.update({
  region: region,
});

var client = new AWS.DynamoDB.DocumentClient();

if (process.argv.length > 2) {
  var dax = new AmazonDaxClient({
    endpoints: [process.argv[2]],
    region: region,
  });
  client = new AWS.DynamoDB.DocumentClient({ service: dax });
}

// Make Get Call using Dax
var params = {
    TableName: 'TryDaxTable',
    pk: 1,
    sk: 1
}
client.get(params, function (err, data) {
    if (err) {
        console.error(
            "Unable to read item. Error JSON:",
            JSON.stringify(err, null, 2)
          );
    } else {
        console.log(data);
    }
});
```

## Uso de DAX de Node.js V3
<a name="DAX.client.run-application-nodejs-3-migrating-V3-dax-usage"></a>

Para utilizar Node.js V3 de DAX, la versión 18 o superior de Node es la versión preferida. Para cambiar a Node 18, utilice lo siguiente:

```
import { DaxDocument } from '@amazon-dax-sdk/lib-dax';
import { DynamoDBDocument } from '@aws-sdk/lib-dynamodb';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';

let client: DynamoDBDocument | DaxDocument = DynamoDBDocument.from(
  new DynamoDBClient({ region: 'us-west-2' })
);

if (process.argv.length > 2) {
  client = new DaxDocument({
    endpoints: [process.argv[2]],
    region: 'us-west-2',
  });
}

const params = {
  TableName: 'TryDaxTable',
  Key: { pk: 1, sk: 1 },
};

try {
  const results = await client.get(params);
  console.log(results);
} catch (err) {
  console.error(err);
}
```

El SDK de DAX para Node.js v3.x es compatible con el [AWS SDK para Node.js v3.x](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/introduction/). El SDK de DAX para Node.js v3.x admite el uso de clientes [agregados](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/introduction/#high-level-concepts). Tenga en cuenta que DAX no admite la creación de clientes básicos. Para obtener más información sobre las características no admitidas, consulte [Características que no están en paridad con AWS SDK V3](#DAX.client.run-application-nodejs-3-not-in-parity).

Siga estos pasos para ejecutar la aplicación de ejemplo de Node.js en su instancia de Amazon EC2.

**Para ejecutar el ejemplo de Node.js para DAX**

1. Configure Node.js en su instancia ,de Amazon EC2 de la siguiente manera:

   1. Instale el administrador de la versión de nodo (`nvm`).

      ```
      curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
      ```

   1. Use nvm para instalar Node.js.

      ```
      nvm install 18
      ```

   1. Uso de nvm para utilizar Node 18

      ```
      nvm use 18
      ```

   1. Compruebe que Node.js está instalado y se ejecuta correctamente.

      ```
      node -e "console.log('Running Node.js ' + process.version)"
      ```

      Esto debería mostrar el mensaje siguiente.

      `Running Node.js v18.x.x`

1. Instale el cliente Node.js de DaxDocument mediante el administrador del paquete de Node (`npm`).

   ```
   npm install @amazon-dax-sdk/lib-dax
   ```

## Código de muestra TryDax
<a name="DAX.client.run-application-nodejs-3-TryDax-sample-code"></a>

Para evaluar las ventajas de rendimiento de DynamoDB Accelerator (DAX), siga estos pasos para ejecutar una prueba de muestra que compare los tiempos de operación de lectura entre DynamoDB estándar y un clúster de DAX.

1. Después de configurar el espacio de trabajo y agregar `lib-dax` como dependencia, copie [TryDax.js](DAX.client.tutorial-TryDax.md) en el proyecto.

1. Ejecute el programa en el clúster de DAX. Para determinar el punto de enlace del clúster de DAX, elija una de las opciones siguientes: 
   +  **En la consola de DynamoDB**: elija su clúster de DAX. El punto de enlace del clúster se muestra en la consola, como en el siguiente ejemplo.

     ```
     dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
     ```
   + **En la AWS CLI**: ingrese el siguiente comando.

     ```
     aws dax describe-clusters --query "Clusters[*].ClusterDiscoveryEndpoint"
     ```

     El punto de enlace del clúster se muestra en el resultado, como en el siguiente ejemplo.

     ```
     {
         "Address": "my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com",
         "Port": 8111,
         "URL": "dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com"
     }
     ```

1. Ahora ejecute el programa; para ello, especifique el punto de conexión del clúster como parámetro de línea de comandos.

   ```
   node TryDax.js dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
   ```

   Debería ver una salida similar a esta:

   ```
   Attempting to create table; please wait...
   Successfully created table. Table status: ACTIVE
   Writing data to the table...
   Writing 20 items for partition key:  1
   Writing 20 items for partition key:  2
   Writing 20 items for partition key:  3
   ...
   Running GetItem Test
           Total time: 153555.10 µs - Avg time: 383.89 µs
           Total time: 44679.96 µs - Avg time: 111.70 µs
           Total time: 36885.86 µs - Avg time: 92.21 µs
           Total time: 32467.25 µs - Avg time: 81.17 µs
           Total time: 32202.60 µs - Avg time: 80.51 µs
   Running Query Test
           Total time: 14869.25 µs - Avg time: 2973.85 µs
           Total time: 3036.31 µs - Avg time: 607.26 µs
           Total time: 2468.92 µs - Avg time: 493.78 µs
           Total time: 2062.53 µs - Avg time: 412.51 µs
           Total time: 2178.22 µs - Avg time: 435.64 µs
   Running Scan Test
           Total time: 2395.88 µs - Avg time: 479.18 µs
           Total time: 2207.16 µs - Avg time: 441.43 µs
           Total time: 2443.14 µs - Avg time: 488.63 µs
           Total time: 2038.24 µs - Avg time: 407.65 µs
           Total time: 1972.17 µs - Avg time: 394.43 µs
   Running Pagination Test
   Scan Pagination
   [
     { pk: 1, sk: 1, someData: 'XXXXXXXXXX' },
     { pk: 1, sk: 2, someData: 'XXXXXXXXXX' },
     { pk: 1, sk: 3, someData: 'XXXXXXXXXX' }
   ]
   [
     { pk: 1, sk: 4, someData: 'XXXXXXXXXX' },
     { pk: 1, sk: 5, someData: 'XXXXXXXXXX' },
     { pk: 1, sk: 6, someData: 'XXXXXXXXXX' }
   ]
   ...
   Query Pagination
   [
     { pk: 1, sk: 1, someData: 'XXXXXXXXXX' },
     { pk: 1, sk: 2, someData: 'XXXXXXXXXX' },
     { pk: 1, sk: 3, someData: 'XXXXXXXXXX' }
   ]
   [
     { pk: 1, sk: 4, someData: 'XXXXXXXXXX' },
     { pk: 1, sk: 5, someData: 'XXXXXXXXXX' },
     { pk: 1, sk: 6, someData: 'XXXXXXXXXX' }
   ]
   ...
   Attempting to delete table; please wait...
   Successfully deleted table.
   ```

   Anote la información de tiempo. El número de microsegundos necesarios para las pruebas de `GetItem`, `Query` y `Scan`.

1. En este caso, ha ejecutado los programas en el clúster de DAX. Ahora, volverá a ejecutar el programa, esta vez en DynamoDB.

1. Ahora ejecute el programa de nuevo, pero esta vez, sin la URL del punto de conexión del clúster como parámetro de la línea de comandos.

   ```
   node TryDax.js
   ```

   Fíjese en el resultado y tome nota de la información sobre tiempos. Los tiempos transcurridos para las operaciones `GetItem`, `Query` y `Scan` deberían ser significativamente menores con DAX en comparación con DynamoDB.

## Características que no están en paridad con AWS SDK V3
<a name="DAX.client.run-application-nodejs-3-not-in-parity"></a>
+ [Clientes básicos](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/introduction/#high-level-concepts): Node.js de Dax V3 no admite clientes básicos. 

  ```
  const dynamoDBClient = new DynamoDBClient({ region: 'us-west-2' });
  const regularParams = {
      TableName: 'TryDaxTable',
      Key: {
          pk: 1,
          sk: 1
      }
  };
  // The DynamoDB client supports the send operation.
  const dynamoResult = await dynamoDBClient.send(new GetCommand(regularParams));
  
  // However, the DaxDocument client does not support the send operation.
  const daxClient = new DaxDocument({
      endpoints: ['your-dax-endpoint'],
      region: 'us-west-2',
  });
  
  const params = {
      TableName: 'TryDaxTable',
      Key: {
          pk: 1,
          sk: 1
      }
  };
  
  // This will throw an error - send operation is not supported for DAX. Please refer to documentation.
  const result = await daxClient.send(new GetCommand(params));
  console.log(result);
  ```
+ [Pila de middleware](https://aws.amazon.com/blogs/developer/middleware-stack-modular-aws-sdk-js/): Node.js de Dax V3 no admite el uso de funciones de middleware.

  ```
  const dynamoDBClient = new DynamoDBClient({ region: 'us-west-2' });
  // The DynamoDB client supports the middlewareStack.
  dynamoDBClient.middlewareStack.add(
    (next, context) =>> async (args) => {
      console.log("Before operation:", args);
      const result = await next(args);
      console.log("After operation:", result);
      return result;
    },
    {
      step: "initialize", // or "build", "finalizeRequest", "deserialize"
      name: "loggingMiddleware",
    }
  );
  
  // However, the DaxDocument client does not support the middlewareStack.
  const daxClient = new DaxDocument({
      endpoints: ['your-dax-endpoint'],
      region: 'us-west-2',
  });
  
  // This will throw an error - custom middleware and middlewareStacks are not supported for DAX. Please refer to documentation.
  daxClient.middlewareStack.add(
    (next, context) => async (args) => {
      console.log("Before operation:", args);
      const result = await next(args);
      console.log("After operation:", result);
      return result;
    },
    {
      step: "initialize", // or "build", "finalizeRequest", "deserialize"
      name: "loggingMiddleware",
    }
  );
  ```

# TryDax.js
<a name="DAX.client.tutorial-TryDax"></a>

```
import { DynamoDB, waitUntilTableExists, waitUntilTableNotExists } from "@aws-sdk/client-dynamodb";
import { DaxDocument, daxPaginateScan, daxPaginateQuery } from "@amazon-dax-sdk/lib-dax";
import { DynamoDBDocument, paginateQuery, paginateScan } from "@aws-sdk/lib-dynamodb";

const region = "us-east-1";
const tableName = "TryDaxTable";

// Determine the client (DynamoDB or DAX)
let client = DynamoDBDocument.from(new DynamoDB({ region }));
if (process.argv.length > 2) {
  client = new DaxDocument({ region, endpoint: process.argv[2] });
}

// Function to create table
async function createTable() {
  const dynamodb = new DynamoDB({ region });
  const params = {
    TableName: tableName,
    KeySchema: [
      { AttributeName: "pk", KeyType: "HASH" },
      { AttributeName: "sk", KeyType: "RANGE" },
    ],
    AttributeDefinitions: [
      { AttributeName: "pk", AttributeType: "N" },
      { AttributeName: "sk", AttributeType: "N" },
    ],
    ProvisionedThroughput: { ReadCapacityUnits: 25, WriteCapacityUnits: 25 },
  };

  try {
    console.log("Attempting to create table; please wait...");
    await dynamodb.createTable(params);
    await waitUntilTableExists({ client: dynamodb, maxWaitTime: 30 }, { TableName: tableName });
    console.log("Successfully created table. Table status: ACTIVE");
  } catch (err) {
    console.error("Error in table creation:", err);
  }
}

// Function to insert data
async function writeData() {
  console.log("Writing data to the table...");
  const someData = "X".repeat(10);
  for (let ipk = 1; ipk <= 20; ipk++) {
    console.log("Writing 20 items for partition key: ", ipk)
    for (let isk = 1; isk <= 20; isk++) {
      try {
        await client.put({ TableName: tableName, Item: { pk: ipk, sk: isk, someData } });
      } catch (err) {
        console.error("Error inserting data:", err);
      }
    }
  }
}

// Function to test GetItem
async function getItemTest() {
  console.log("Running GetItem Test");
  for (let i = 0; i < 5; i++) {
    const startTime = performance.now();
    const promises = [];
    for (let ipk = 1; ipk <= 20; ipk++) {
      for (let isk = 1; isk <= 20; isk++) {
        promises.push(client.get({ TableName: tableName, Key: { pk: ipk, sk: isk } }));
      }
    }
    await Promise.all(promises);
    const endTime = performance.now();
    const iterTime = (endTime - startTime) * 1000;
    const totalTime = iterTime.toFixed(2).padStart(3, ' ');
    const avgTime = (iterTime / 400).toFixed(2).padStart(3, ' ');
    console.log(`\tTotal time: ${totalTime} \u00B5s - Avg time: ${avgTime} \u00B5s`);
  }
}

// Function to test Query
async function queryTest() {
  console.log("Running Query Test");
  for (let i = 0; i < 5; i++) {
    const startTime = performance.now();
    const promises = [];
    for (let pk = 1; pk <= 5; pk++) {
      const params = {
        TableName: tableName,
        KeyConditionExpression: "pk = :pkval and sk between :skval1 and :skval2",
        ExpressionAttributeValues: { ":pkval": pk, ":skval1": 1, ":skval2": 2 },
      };
      promises.push(client.query(params));
    }
    await Promise.all(promises);
    const endTime = performance.now();
    const iterTime = (endTime - startTime) * 1000;
    const totalTime = iterTime.toFixed(2).padStart(3, ' ');
    const avgTime = (iterTime / 5).toFixed(2).padStart(3, ' ');
    console.log(`\tTotal time: ${totalTime} \u00B5s - Avg time: ${avgTime} \u00B5s`);
  }
}

// Function to test Scan
async function scanTest() {
  console.log("Running Scan Test");
  for (let i = 0; i < 5; i++) {
    const startTime = performance.now();
    const promises = [];
    for (let pk = 1; pk <= 5; pk++) {
      const params = {
        TableName: tableName,
        FilterExpression: "pk = :pkval and sk between :skval1 and :skval2",
        ExpressionAttributeValues: { ":pkval": pk, ":skval1": 1, ":skval2": 2 },
      };
      promises.push(client.scan(params));
    }
    await Promise.all(promises);
    const endTime = performance.now();
    const iterTime = (endTime - startTime) * 1000;
    const totalTime = iterTime.toFixed(2).padStart(3, ' ');
    const avgTime = (iterTime / 5).toFixed(2).padStart(3, ' ');
    console.log(`\tTotal time: ${totalTime} \u00B5s - Avg time: ${avgTime} \u00B5s`);
  }
}

// Function to test Pagination
async function paginationTest() {
  console.log("Running Pagination Test");
  console.log("Scan Pagination");
  const scanParams = { TableName: tableName };
  const paginator = process.argv.length > 2 ? daxPaginateScan : paginateScan;
  for await (const page of paginator({ client, pageSize: 3 }, scanParams)) {
    console.log(page.Items);
  }

  console.log("Query Pagination");
  const queryParams = {
    TableName: tableName,
    KeyConditionExpression: "pk = :pkval and sk between :skval1 and :skval2",
    ExpressionAttributeValues: { ":pkval": 1, ":skval1": 1, ":skval2": 10 },
  };
  const queryPaginator = process.argv.length > 2 ? daxPaginateQuery : paginateQuery;
  for await (const page of queryPaginator({ client, pageSize: 3 }, queryParams)) {
    console.log(page.Items);
  }
}

// Function to delete the table
async function deleteTable() {
  const dynamodb = new DynamoDB({ region });
  console.log("Attempting to delete table; please wait...")
  try {
    await dynamodb.deleteTable({ TableName: tableName });
    await waitUntilTableNotExists({ client: dynamodb, maxWaitTime: 30 }, { TableName: tableName });
    console.log("Successfully deleted table.");
  } catch (err) {
    console.error("Error deleting table:", err);
  }
}

// Execute functions sequentially
(async function () {
  await createTable();
  await writeData();
  await getItemTest();
  await queryTest();
  await scanTest();
  await paginationTest();
  await deleteTable();
})();
```

# SDK para Go de DAX
<a name="DAX.client.run-application-go-2"></a>

Siga este procedimiento para ejecutar la aplicación de ejemplo de SDK para Go de Amazon DynamoDB Accelerator (DAX) en su instancia de Amazon EC2.

**Para ejecutar la muestra de SDK para Go para DAX**

1. Configure SDK para Go en su instancia de Amazon EC2:

   1. Instale el lenguaje de programación Go (`Golang`).

      ```
      sudo yum install -y golang
      ```

   1. Compruebe que Golang está instalado y se ejecuta correctamente.

      ```
      go version
      ```

      Debería aparecer un mensaje como este.

      ```
      go version go1.23.4 linux/amd64
      ```

1. Instale la aplicación Golang de ejemplo.

   ```
   go get github.com/aws-samples/sample-aws-dax-go-v2
   ```

1. Ejecute los siguientes programas de Golang. El primer programa crea una tabla de DynamoDB denominada `TryDaxGoTable`. El segundo programa escribe datos en la tabla.

   ```
   go run ~/go/pkg/mod/github.com/aws-samples/sample-aws-dax-go-v2@v1.0.0/try_dax.go -service dynamodb -command create-table
   ```

   ```
   go run ~/go/pkg/mod/github.com/aws-samples/sample-aws-dax-go-v2@v1.0.0/try_dax.go -service dynamodb -command put-item
   ```

1. Ejecute los siguientes programas de Golang.

   ```
   go run ~/go/pkg/mod/github.com/aws-samples/sample-aws-dax-go-v2@v1.0.0/try_dax.go -service dynamodb -command get-item
   ```

   ```
   go run ~/go/pkg/mod/github.com/aws-samples/sample-aws-dax-go-v2@v1.0.0/try_dax.go -service dynamodb -command query
   ```

   ```
   go run ~/go/pkg/mod/github.com/aws-samples/sample-aws-dax-go-v2@v1.0.0/try_dax.go -service dynamodb -command scan
   ```

   Tome nota de la información de tiempo; es decir, del número de milisegundos necesarios para realizar las pruebas de `GetItem`, `Query` y `Scan`.

1. En el paso anterior, ha ejecutado los programas en el punto de enlace de DynamoDB. Ahora, ejecute los programas de nuevo, pero, esta vez, las operaciones `GetItem`, `Query` y `Scan` se procesan en el clúster de DAX.

   Para determinar el punto de enlace del clúster de DAX, elija una de las opciones siguientes:
   + **En la consola de DynamoDB**: elija su clúster de DAX. El punto de enlace del clúster se muestra en la consola, como en el siguiente ejemplo.

     ```
     dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
     ```
   + **En la AWS CLI**: ingrese el siguiente comando.

     ```
     aws dax describe-clusters --query "Clusters[*].ClusterDiscoveryEndpoint"
     ```

     El punto de enlace del clúster se muestra en el resultado, como en el siguiente ejemplo.

     ```
     {
         "Address": "my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com",
         "Port": 8111,
         "URL": "dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com"
     }
     ```

   Ahora, vuelva a ejecutar los programas, pero, esta vez, especifique el punto de enlace del clúster como parámetro en la línea de comandos.

   ```
   go run ~/go/pkg/mod/github.com/aws-samples/sample-aws-dax-go-v2@v1.0.0/try_dax.go -service dax -command get-item -endpoint my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com:8111
   ```

   ```
   go run ~/go/pkg/mod/github.com/aws-samples/sample-aws-dax-go-v2@v1.0.0/try_dax.go -service dax -command query -endpoint my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com:8111
   ```

   ```
   go run ~/go/pkg/mod/github.com/aws-samples/sample-aws-dax-go-v2@v1.0.0/try_dax.go -service dax -command scan -endpoint my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com:8111
   ```

   ```
   go run ~/go/pkg/mod/github.com/aws-samples/sample-aws-dax-go-v2@v1.0.0/try_dax.go -service dax -command paginated-scan -endpoint my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com:8111
   ```

   ```
   go run ~/go/pkg/mod/github.com/aws-samples/sample-aws-dax-go-v2@v1.0.0/try_dax.go -service dax -command paginated-query -endpoint my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com:8111
   ```

   ```
   go run ~/go/pkg/mod/github.com/aws-samples/sample-aws-dax-go-v2@v1.0.0/try_dax.go -service dax -command paginated-batch-get -endpoint my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com:8111
   ```

   Fíjese en el resto del resultado y tome nota de la información sobre tiempos. Los tiempos transcurridos para las operaciones `GetItem`, `Query` y `Scan` deberían ser significativamente menores con DAX que con DynamoDB.

1. Ejecute el siguiente programa de Golang para eliminar `TryDaxGoTable`.

   ```
   go run ~/go/pkg/mod/github.com/aws-samples/sample-aws-dax-go-v2@v1.0.0/try_dax.go -service dynamodb -command delete-table
   ```

## Características que no están en paridad con AWS SDK para Go SDK V2
<a name="DAX.client.run-application-go-features-not-in-parity"></a>

Pila de middleware: Go de DAX V2 no admite el uso de pilas de middleware a través de opciones de la API. Para obtener más información, consulte [Personalización de las solicitudes de cliente de AWS SDK para Go v2 con middleware](https://docs.aws.amazon.com/sdk-for-go/v2/developer-guide/middleware.html#:~:text=You%20can%20customize%20AWS%20SDK,step's%20input%20and%20output%20types).

Ejemplo:

```
// Custom middleware implementation
type customSerializeMiddleware struct{}
// ID returns the identifier for the middleware
func (m *customSerializeMiddleware) ID() string {
    return "CustomMiddleware"
}
// HandleSerialize implements the serialize middleware handler
func (m *customSerializeMiddleware) HandleSerialize(
    ctx context.Context,
    in middleware.SerializeInput,
    next middleware.SerializeHandler,
) (
    out middleware.SerializeOutput,
    metadata middleware.Metadata,
    err error,
) {
    // Add your custom logic here before the request is serialized
    fmt.Printf("Executing custom middleware for request: %v\n", in)
    // Call the next handler in the middleware chain
    return next.HandleSerialize(ctx, in)
}

func executeGetItem(ctx context.Context) error {
    client, err := initItemClient(ctx)
    if err != nil {
        os.Stderr.WriteString(fmt.Sprintf("failed to initialize client: %v\n", err))
        return err
    }

    st := time.Now()
    for c := 0; c < iterations; c++ {
        for i := 0; i < pkMax; i++ {
            for j := 0; j < skMax; j++ {
                // Create key using attributevalue.Marshal for type safety
                pk, err := attributevalue.Marshal(fmt.Sprintf("%s_%d", keyPrefix, i))
                if err != nil {
                    return fmt.Errorf("error marshaling pk: %v", err)
                }
                sk, err := attributevalue.Marshal(fmt.Sprintf("%d", j))
                if err != nil {
                    return fmt.Errorf("error marshaling sk: %v", err)
                }
                key := map[string]types.AttributeValue{
                    "pk": pk,
                    "sk": sk,
                }
                in := &dynamodb.GetItemInput{
                    TableName: aws.String(table),
                    Key:       key,
                }

                // Custom middleware option
                customMiddleware := func(o *dynamodb.Options) {
                    o.APIOptions = append(o.APIOptions, func(stack *middleware.Stack) error {
                        // Add custom middleware to the stack
                        return stack.Serialize.Add(&customSerializeMiddleware{}, middleware.After)
                    })
                }

                // Apply options to the GetItem call
                out, err := client.GetItem(ctx, in, customMiddleware)
                if err != nil {
                    return err
                }
                writeVerbose(out)
            }
        }
    }
    d := time.Since(st)
    os.Stdout.WriteString(fmt.Sprintf("Total Time: %v, Avg Time: %v\n", d, d/iterations))
    return nil
}
```

Salida:

```
failed to execute command: custom middleware through APIOptions is not supported in DAX client
exit status 1
```

# Configuración predeterminada de cliente para Go
<a name="DAX-client-config-Go"></a>

Esta guía lo guiará a través de las opciones de configuración que le permiten afinar el rendimiento del cliente de DAX, la administración de conexiones y el comportamiento de registro. Al comprender la configuración predeterminada y cómo personalizarla, puede optimizar la interacción de la aplicación Go con DAX.

**Topics**
+ [Valores predeterminados del cliente del SDK de Go de DAX](#DAX-client-config-Go-sdk-client-defaults)
+ [Creación del cliente](#DAX-client-config-Go-client-creation)

## Valores predeterminados del cliente del SDK de Go de DAX
<a name="DAX-client-config-Go-sdk-client-defaults"></a>


| Parámetro | Tipo | Descripción | 
| --- | --- | --- | 
|  `Region` obligatorio  |  `string`  |  La Región de AWS que se debe usar para el cliente de DAX (ejemplo: “us-east-1”). Este parámetro es obligatorio si no se proporciona a través del entorno.  | 
|  `HostPorts` obligatorio  |  `[] string`  |  Lista de puntos de conexión del clúster de DAX a los que se conecta el SDK.  Por ejemplo: Sin cifrar: dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com Cifrado: daxs://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com  | 
|  `MaxPendingConnectionsPerHost` predeterminado: 10  |  `number`  | Número de intentos de conexión simultáneos. (Las conexiones pueden estar en proceso de establecerse simultáneamente).  | 
|  `ClusterUpdateThreshold` predeterminado: 125 \$1 time.Millisecond  |  `time.Duration`  | El tiempo mínimo que debe transcurrir entre las actualizaciones del clúster.  | 
|  `ClusterUpdateInterval` predeterminado: 4 \$1 time.Second  |  `time.Duration`  | El intervalo en el que el cliente actualizará automáticamente la información del clúster de DAX.  | 
|  `IdleConnectionsReapDelay` predeterminado: 30 \$1 time.Second  |  `time.Duration`  | El intervalo en el que el cliente cerrará las conexiones inactivas en el cliente de DAX.  | 
|  `ClientHealthCheckInterval` predeterminado: 5 \$1 time.Second  |  `time.Duration`  | El intervalo en el que el cliente realizará comprobaciones de estado en los puntos de conexión del clúster de DAX.  | 
|  `Credentials` predeterminado  |  `aws.CredentialsProvider`  | Las credenciales de AWS utilizadas por el cliente de DAX para autenticar las solicitudes al servicio de DAX. Consulte [Credenciales y proveedores de credenciales](https://docs.aws.amazon.com/sdk-for-go/v2/developer-guide/migrate-gosdk.html#credentials--credential-providers).  | 
|  `DialContext` predeterminado  |  `func`  | Una función personalizada utilizada por el cliente de DAX para establecer conexiones con el clúster de DAX.  | 
|  `SkipHostnameVerification` predeterminado: false  |  bool  |  Omitir la verificación del nombre de host de las conexiones TLS. Esta configuración solo afecta a los clústeres cifrados. Cuando se establece en True, desactiva la verificación del nombre de host. Deshabilitar la verificación significa que no puede autenticar la identidad del clúster al que se está conectando, lo que plantea riesgos de seguridad. De forma predeterminada, la verificación del nombre de host está habilitada.  | 
|  `RouteManagerEnabled` predeterminado: false  |  `bool`  | Este indicador se utiliza para eliminar las rutas que enfrentan errores de red.  | 
|  `RequestTimeout` predeterminado: 60 \$1 time.Second  |  `time.Duration`  | Esto define el tiempo máximo que el cliente esperará una respuesta de DAX. Prioridad: tiempo de espera del contexto (si está establecido) > `RequestTimmeout` (si está establecido) > predeterminado 60 s `RequestTimeout`.  | 
|  `WriteRetries` predeterminado: 2  |  `number`  |  El número de reintentos que se realizarán para las solicitudes de escritura que fallan.  | 
|  `ReadRetries` predeterminado: 2  |  `number`  | El número de reintentos que se realizarán para las solicitudes de lectura que fallan.  | 
|  `RetryDelay` predeterminado: 0  |  `time.Duration`  | El retraso para errores sin limitación (en segundos) de los reintentos cuando falla una solicitud.  | 
|  `Logger` opcional  |  `logging.Logger`  | El registrador es una interfaz para registrar entradas en determinadas clasificaciones.  | 
|  `LogLevel` predeterminado: utils.LogOff  |  `number`  | Este nivel de registro se define solo para DAX. Se puede importar con [github.com/aws/aws-dax-go-v2/tree/main/dax/utils](https://github.com/aws/aws-dax-go-v2/tree/main/dax/utils).  <pre>const (    <br /> LogOff LogLevelType = 0   <br /> LogDebug LogLevelType = 1   <br /> LogDebugWithRequestRetries<br /> LogLevelType = 2<br />)</pre>  | 

**nota**  
Para `time.Duration`, la unidad predeterminada es el nanosegundo. Si no especificamos ninguna unidad para ningún parámetro, se considerará que es nanosegundos: `daxCfg.ClusterUpdateInterval = 10` significa 10 nanosegundos. (`daxCfg.ClusterUpdateInterval = 10 * time.Millisecond` significa 10 milisegundos).

## Creación del cliente
<a name="DAX-client-config-Go-client-creation"></a>

**Para crear un cliente de DAX:**
+ Cree la configuración de DAX y, a continuación, cree el cliente de DAX mediante la configuración de DAX. Con esto, puede sobrescribir una configuración de DAX si es necesario.

  ```
  import (
  "github.com/aws/aws-dax-go-v2/dax/utils"
  "github.com/aws/aws-dax-go-v2/dax"
  )
  
  // Non - Encrypted : 'dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com'.
  // Encrypted : daxs://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com'.
  
  config := dax.DefaultConfig()
  config.HostPorts = []string{endpoint}
  config.Region = region
  config.LogLevel = utils.LogDebug
  daxClient, err := dax.New(config)
  ```

# Migración al SDK de Go de DAX V2
<a name="DAX.client.run-application-go-migrating"></a>

Esta guía de migración lo ayudará en la transición de las aplicaciones Go de DAX existentes.

## Uso del SDK de Go de DAX V1
<a name="DAX.client.run-application-go-V1-usage"></a>

```
package main

import (
    "fmt"
    "os"

    "github.com/aws/aws-dax-go/dax"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/dynamodb"
)

func main() {
    region := "us-west-2"
    endpoint := "dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com"
    
    // Create session
    sess, err := session.NewSession(&aws.Config{
        Region: aws.String(region),
    })
    if err != nil {
        fmt.Printf("Failed to create session: %v\n", err)
        os.Exit(1)
    }
    
    // Configure DAX client
    cfg := dax.DefaultConfig()
    cfg.HostPorts = []string{endpoint} 
    cfg.Region = region

    // Create DAX client
    daxClient, err := dax.New(cfg)
    if err != nil {
        fmt.Printf("Failed to create DAX client: %v\n", err)
        os.Exit(1)
    }
    defer daxClient.Close() // Don't forget to close the client

    // Create GetItem input
    input := &dynamodb.GetItemInput{
        TableName: aws.String("TryDaxTable"),
        Key: map[string]*dynamodb.AttributeValue{
            "pk": {
                N: aws.String("1"),
            },
            "sk": {
                N: aws.String("1"),
            },
        },
    }

    // Make the GetItem call
    result, err := daxClient.GetItem(input)
    if err != nil {
        fmt.Printf("Failed to get item: %v\n", err)
        os.Exit(1)
    }

    // Print the result
    fmt.Printf("GetItem succeeded: %+v\n", result)
}
```

## Uso del SDK de Go de DAX V2
<a name="DAX.client.run-application-go-V2-usage"></a>

```
package main

import (
    "context"
    "fmt"
    "os"

    "github.com/aws/aws-dax-go-v2/dax"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/dynamodb"
    "github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
    "github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue"
    "github.com/aws/aws-sdk-go-v2/aws"
)

func main() {
    ctx := context.Background()
    region := "us-west-2"
    endpoint := "dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com"
   
    // Create DAX config
    config := dax.DefaultConfig()
    // Specify Endpoint and Region
    config.HostPorts = []string{endpoint}
    config.Region = region
    // Enabling logging
    config.LogLevel = utils.LogDebug
    // Create DAX client
    daxClient, err := dax.New(config) 
    if err != nil {
        fmt.Printf("Failed to create DAX client: %v\n", err)
        os.Exit(1)
    }
    defer daxClient.Close() // Don't forget to close the client

    // Create key using attributevalue.Marshal for type safety
    pk, err := attributevalue.Marshal(fmt.Sprintf("%s_%d", keyPrefix, i))
    if err != nil {
        return fmt.Errorf("error marshaling pk: %v", err)
    }
    sk, err := attributevalue.Marshal(fmt.Sprintf("%d", j))
    if err != nil {
        return fmt.Errorf("error marshaling sk: %v", err)
    }
                
    // Create GetItem input
    input := &dynamodb.GetItemInput{
        TableName: aws.String("TryDaxTable"),
        Key: map[string]types.AttributeValue{
             "pk": pk,
             "sk": sk,
        },
    }

    // Make the GetItem call
    result, err := daxClient.GetItem(ctx, input)
    if err != nil {
        fmt.Printf("Failed to get item: %v\n", err)
        os.Exit(1)
    }

    // Print the result
    fmt.Printf("GetItem succeeded: %+v\n", result)
}
```

Para obtener más detalles sobre el uso de la API, consulte las [muestras de AWS](https://github.com/aws-samples/sample-aws-dax-go-v2).

# Java y DAX
<a name="DAX.client.run-application-java"></a>

SDK para Java 2.x de DAX es compatible con [SDK para Java 2.x de AWS](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/). Está construido sobre Java 8\$1 e incluye el soporte para E/S no bloqueado. Para obtener información sobre el uso de DAX con AWS SDK para Java 1.x, consulte [Uso de DAX con SDK de AWS para Java 1.x](DAX.client.java-sdk-v1.md).

## Uso del cliente como una dependencia de Maven
<a name="DAX.client.run-application-java.maven"></a>

Siga estos pasos para utilizar el cliente para el SDK de DAX para Java en su aplicación como una dependencia.

1. Descargue e instale Apache Maven. Para obtener más información, consulte [Downloading Apache Maven](https://maven.apache.org/download.cgi) e [Installing Apache Maven](https://maven.apache.org/install.html).

1. Agregue la dependencia de Maven del cliente al archivo POM (Project Object Model) de la aplicación. En este ejemplo, sustituya *x.x.x* por el número de versión real del cliente.

   ```
   <!--Dependency:-->
   <dependencies>
       <dependency>
           <groupId>software.amazon.dax</groupId>
           <artifactId>amazon-dax-client</artifactId>
           <version>x.x.x</version>
       </dependency>
   </dependencies>
   ```

## Código de muestra TryDax
<a name="DAX.client.run-application-java.sample"></a>

Después de configurar el espacio de trabajo y agregar el SDK de DAX como dependencia, copie [TryDax.java](DAX.client.TryDax.java.md) en el proyecto.

Ejecute el código utilizando este comando.

```
java -cp classpath TryDax
```

Debería ver un resultado similar a este.

```
Creating a DynamoDB client

Attempting to create table; please wait...
Successfully created table.  Table status: ACTIVE
Writing data to the table...
Writing 10 items for partition key: 1
Writing 10 items for partition key: 2
Writing 10 items for partition key: 3
...

Running GetItem and Query tests...
First iteration of each test will result in cache misses
Next iterations are cache hits

GetItem test - partition key 1-100 and sort keys 1-10
  Total time: 4390.240 ms - Avg time: 4.390 ms
  Total time: 3097.089 ms - Avg time: 3.097 ms
  Total time: 3273.463 ms - Avg time: 3.273 ms
  Total time: 3353.739 ms - Avg time: 3.354 ms
  Total time: 3533.314 ms - Avg time: 3.533 ms
Query test - partition key 1-100 and sort keys between 2 and 9
  Total time: 475.868 ms - Avg time: 4.759 ms
  Total time: 423.333 ms - Avg time: 4.233 ms
  Total time: 460.271 ms - Avg time: 4.603 ms
  Total time: 397.859 ms - Avg time: 3.979 ms
  Total time: 466.644 ms - Avg time: 4.666 ms

Attempting to delete table; please wait...
Successfully deleted table.
```

Tome nota de la información de tiempo; es decir, del número de milisegundos necesarios para realizar las pruebas de `GetItem` y `Query`. En este caso, ha ejecutado el programa en el punto de enlace de DynamoDB. Ahora volverá a ejecutar el programa, esta vez en el clúster de DAX.

Para determinar el punto de enlace del clúster de DAX, elija una de las siguientes opciones:
+ En la consola de DynamoDB seleccione su clúster de DAX. El punto de enlace del clúster se muestra dentro de la consola, como en el siguiente ejemplo.

  ```
  dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
  ```
+ Utilizando la AWS CLI, ingrese el siguiente comando.

  ```
  aws dax describe-clusters --query "Clusters[*].ClusterDiscoveryEndpoint"
  ```

  El puerto, la dirección y la URL del punto de enlace del clúster se muestran en el resultado, como en el siguiente ejemplo.

  ```
  {
      "Address": "my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com",
      "Port": 8111,
      "URL": "dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com"
  }
  ```

Ahora, vuelva a ejecutar el programa, pero, esta vez, especifique el la URL del punto de enlace del clúster como parámetro en la línea de comandos.

```
java -cp classpath TryDax dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
```

Fíjese en el resultado y tome nota de la información sobre tiempos. Los tiempos transcurridos para las operaciones `GetItem` y `Query` deberían ser significativamente menores con DAX que con DynamoDB.

## Métricas de SDK
<a name="DAX.client.run-application-java.metrics"></a>

Con SDK para Java 2.x de DAX, puede recopilar métricas sobre los clientes de servicio de su aplicación y analizar los resultados en Amazon CloudWatch. Para obtener más información, consulte [Habilitar métricas de SDK](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/metrics.html).

**nota**  
El SDK para Java de DAX solo recopila las métricas `ApiCallSuccessful` y `ApiCallDuration`.

# TryDax.java
<a name="DAX.client.TryDax.java"></a>

```
import java.util.Map;

import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.BillingMode;
import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest;
import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest;
import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement;
import software.amazon.awssdk.services.dynamodb.model.KeyType;
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
import software.amazon.awssdk.services.dynamodb.model.QueryRequest;
import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;
import software.amazon.dax.ClusterDaxAsyncClient;
import software.amazon.dax.Configuration;

public class TryDax {
    public static void main(String[] args) throws Exception {
        DynamoDbAsyncClient ddbClient = DynamoDbAsyncClient.builder()
                .build();

        DynamoDbAsyncClient daxClient = null;
        if (args.length >= 1) {
            daxClient = ClusterDaxAsyncClient.builder()
                    .overrideConfiguration(Configuration.builder()
                            .url(args[0]) // e.g. dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
                            .build())
                    .build();
        }

        String tableName = "TryDaxTable";

        System.out.println("Creating table...");
        createTable(tableName, ddbClient);

        System.out.println("Populating table...");
        writeData(tableName, ddbClient, 100, 10);

        DynamoDbAsyncClient testClient = null;
        if (daxClient != null) {
            testClient = daxClient;
        } else {
            testClient = ddbClient;
        }

        System.out.println("Running GetItem and Query tests...");
        System.out.println("First iteration of each test will result in cache misses");
        System.out.println("Next iterations are cache hits\n");

        // GetItem
        getItemTest(tableName, testClient, 100, 10, 5);

        // Query
        queryTest(tableName, testClient, 100, 2, 9, 5);

        System.out.println("Deleting table...");
        deleteTable(tableName, ddbClient);
    }

    private static void createTable(String tableName, DynamoDbAsyncClient client) {
        try {
            System.out.println("Attempting to create table; please wait...");

            client.createTable(CreateTableRequest.builder()
                    .tableName(tableName)
                    .keySchema(KeySchemaElement.builder()
                            .keyType(KeyType.HASH)
                            .attributeName("pk")
                            .build(), KeySchemaElement.builder()
                            .keyType(KeyType.RANGE)
                            .attributeName("sk")
                            .build())
                    .attributeDefinitions(AttributeDefinition.builder()
                            .attributeName("pk")
                            .attributeType(ScalarAttributeType.N)
                            .build(), AttributeDefinition.builder()
                            .attributeName("sk")
                            .attributeType(ScalarAttributeType.N)
                            .build())
                    .billingMode(BillingMode.PAY_PER_REQUEST)
                    .build()).get();
            client.waiter().waitUntilTableExists(DescribeTableRequest.builder()
                    .tableName(tableName)
                    .build()).get();
            System.out.println("Successfully created table.");

        } catch (Exception e) {
            System.err.println("Unable to create table: ");
            e.printStackTrace();
        }
    }

    private static void deleteTable(String tableName, DynamoDbAsyncClient client) {
        try {
            System.out.println("\nAttempting to delete table; please wait...");
            client.deleteTable(DeleteTableRequest.builder()
                    .tableName(tableName)
                    .build()).get();
            client.waiter().waitUntilTableNotExists(DescribeTableRequest.builder()
                    .tableName(tableName)
                    .build()).get();
            System.out.println("Successfully deleted table.");

        } catch (Exception e) {
            System.err.println("Unable to delete table: ");
            e.printStackTrace();
        }
    }

    private static void writeData(String tableName, DynamoDbAsyncClient client, int pkmax, int skmax) {
        System.out.println("Writing data to the table...");

        int stringSize = 1000;
        StringBuilder sb = new StringBuilder(stringSize);
        for (int i = 0; i < stringSize; i++) {
            sb.append('X');
        }
        String someData = sb.toString();

        try {
            for (int ipk = 1; ipk <= pkmax; ipk++) {
                System.out.println(("Writing " + skmax + " items for partition key: " + ipk));
                for (int isk = 1; isk <= skmax; isk++) {
                    client.putItem(PutItemRequest.builder()
                            .tableName(tableName)
                            .item(Map.of("pk", attr(ipk), "sk", attr(isk), "someData", attr(someData)))
                            .build()).get();
                }
            }
        } catch (Exception e) {
            System.err.println("Unable to write item:");
            e.printStackTrace();
        }
    }

    private static AttributeValue attr(int n) {
        return AttributeValue.builder().n(String.valueOf(n)).build();
    }

    private static AttributeValue attr(String s) {
        return AttributeValue.builder().s(s).build();
    }

    private static void getItemTest(String tableName, DynamoDbAsyncClient client, int pk, int sk, int iterations) {
        long startTime, endTime;
        System.out.println("GetItem test - partition key 1-" + pk + " and sort keys 1-" + sk);

        for (int i = 0; i < iterations; i++) {
            startTime = System.nanoTime();
            try {
                for (int ipk = 1; ipk <= pk; ipk++) {
                    for (int isk = 1; isk <= sk; isk++) {
                        client.getItem(GetItemRequest.builder()
                                .tableName(tableName)
                                .key(Map.of("pk", attr(ipk), "sk", attr(isk)))
                                .build()).get();
                    }
                }
            } catch (Exception e) {
                System.err.println("Unable to get item:");
                e.printStackTrace();
            }
            endTime = System.nanoTime();
            printTime(startTime, endTime, pk * sk);
        }
    }

    private static void queryTest(String tableName, DynamoDbAsyncClient client, int pk, int sk1, int sk2, int iterations) {
        long startTime, endTime;
        System.out.println("Query test - partition key 1-" + pk + " and sort keys between " + sk1 + " and " + sk2);

        for (int i = 0; i < iterations; i++) {
            startTime = System.nanoTime();
            for (int ipk = 1; ipk <= pk; ipk++) {
                try {
                    // Pagination API for Query.
                    client.queryPaginator(QueryRequest.builder()
                            .tableName(tableName)
                            .keyConditionExpression("pk = :pkval and sk between :skval1 and :skval2")
                            .expressionAttributeValues(Map.of(":pkval", attr(ipk), ":skval1", attr(sk1), ":skval2", attr(sk2)))
                            .build()).items().subscribe((item) -> {
                    }).get();
                } catch (Exception e) {
                    System.err.println("Unable to query table:");
                    e.printStackTrace();
                }
            }
            endTime = System.nanoTime();
            printTime(startTime, endTime, pk);
        }
    }

    private static void printTime(long startTime, long endTime, int iterations) {
        System.out.format("\tTotal time: %.3f ms - ", (endTime - startTime) / (1000000.0));
        System.out.format("Avg time: %.3f ms\n", (endTime - startTime) / (iterations * 1000000.0));
    }
}
```

# .NET y DAX
<a name="DAX.client.run-application-dotnet"></a>

Siga estos pasos para ejecutar el ejemplo de .NET en su instancia de Amazon EC2.

**nota**  
En este tutorial se utiliza el SDK de .NET 9. Muestra cómo puede ejecutar un programa en su Amazon VPC predeterminada para acceder a su clúster de Amazon DynamoDB Accelerator (DAX). Funciona con el [AWS SDK v4 para .NET](https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/welcome.html). Para obtener detalles sobre los cambios en V4 e información sobre la migración, consulte [Migración a la versión 4 del AWS SDK para .NET](https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/net-dg-v4.html). Si lo prefiere, puede utilizar AWS Toolkit for Visual Studio para escribir una aplicación .NET e implementarla en su VPC.  
Para obtener más información, consulte [Creación y desarrollo de las aplicaciones de Elastic Beanstalk en .NET utilizando Toolkit for Visual Studio de AWS](https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_NET.html) en la *Guía para desarrolladores de AWS Elastic Beanstalk*.

**Para ejecutar el ejemplo de .NET para DAX**

1. Vaya a la [página de descargas de Microsoft](https://www.microsoft.com/net/download?initial-os=linux) y descargue el SDK de .NET 9 para Linux más reciente. El archivo descargable es `dotnet-sdk-N.N.N-linux-x64.tar.gz`.

1. Extraiga los archivos del SDK.

   ```
   mkdir dotnet
   tar zxvf dotnet-sdk-N.N.N-linux-x64.tar.gz -C dotnet
   ```

   Sustituya `N.N.N` por el número de versión real del SDK de .NET (por ejemplo: `9.0.305`).

1. Verifica la instalación.

   ```
   alias dotnet=$HOME/dotnet/dotnet
   dotnet --version
   ```

   Esto debería imprimir el número de versión del SDK de .NET.
**nota**  
En lugar del número de versión, podría recibir el error siguiente:  
error: libunwind.so.8: cannot open shared object file: No such file or directory  
Para resolver el error, instale el paquete `libunwind`.  

   ```
   sudo yum install -y libunwind
   ```
Después de esto, debería poder ejecutar el comando `dotnet --version` sin errores.

1. Creación de un nuevo proyecto de .NET.

   ```
   dotnet new console -o myApp 
   ```

   Esto requiere algunos minutos para llevar a cabo una configuración solo una vez. Cuando se complete, ejecute el proyecto de ejemplo.

   ```
   dotnet run --project myApp
   ```

   Debería recibir el siguiente mensaje: `Hello World!`

1. El archivo `myApp/myApp.csproj` contiene metadatos acerca de su proyecto. Para utilizar el cliente de DAX en su aplicación, modifique el archivo para que tenga un aspecto similar a lo siguiente.

   ```
   <Project Sdk="Microsoft.NET.Sdk">
       <PropertyGroup>
           <OutputType>Exe</OutputType>
           <TargetFramework>net9.0</TargetFramework>
       </PropertyGroup>
       <ItemGroup>
           <PackageReference Include="AWSSDK.DAX.Client" Version="*" />
       </ItemGroup>
   </Project>
   ```

1. Descargue el código fuente del programa de ejemplo (archivo `.zip`).

   ```
   wget http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/samples/TryDax.zip
   ```

   Cuando haya terminado la descarga, extraiga los archivos de código fuente.

   ```
   unzip TryDax.zip
   ```

1. Ahora ejecute los programas de ejemplo de *dotNet*, uno cada vez. Para cada programa, copie su contenido en `myApp/Program.cs` y, a continuación, ejecute el proyecto `MyApp`.

   Ejecute los siguientes programas de .NET. El primer programa crea una tabla de DynamoDB denominada `TryDaxTable`. El segundo programa escribe datos en la tabla.

   ```
   cp TryDax/dotNet/01-CreateTable.cs myApp/Program.cs
   dotnet run --project myApp
   
   cp TryDax/dotNet/02-Write-Data.cs myApp/Program.cs
   dotnet run --project myApp
   ```

1. A continuación, ejecute algunos programas para llevar a cabo operaciones `GetItem`, `Query` y `Scan` en su clúster de DAX. Para determinar el punto de enlace del clúster de DAX, elija una de las opciones siguientes:
   +  **En la consola de DynamoDB**: elija su clúster de DAX. El punto de enlace del clúster se muestra en la consola, como en el siguiente ejemplo.

     ```
     dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
     ```
   + **En la AWS CLI**: ingrese el siguiente comando.

     ```
     aws dax describe-clusters --query "Clusters[*].ClusterDiscoveryEndpoint"
     ```

     El punto de enlace del clúster se muestra en el resultado, como en el siguiente ejemplo.

     ```
     {
         "Address": "my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com",
         "Port": 8111,
         "URL": "dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com"
     }
     ```

   Ahora, ejecute los programas siguientes, especificando el punto de enlace del clúster como parámetro en la línea de comandos. (Reemplace el punto de enlace del ejemplo por el punto de enlace de clúster de DAX real).

   ```
   cp TryDax/dotNet/03-GetItem-Test.cs myApp/Program.cs
   dotnet run --project myApp dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
   
   cp TryDax/dotNet/04-Query-Test.cs myApp/Program.cs
   dotnet run --project myApp dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
                           
   cp TryDax/dotNet/05-Scan-Test.cs myApp/Program.cs
   dotnet run --project myApp dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
   ```

   Tome nota de la información de tiempo; es decir, del número de milisegundos necesarios para realizar las pruebas de `GetItem`, `Query` y `Scan`.

1. Ejecute el siguiente programa de .NET para eliminar `TryDaxTable`.

   ```
   cp TryDax/dotNet/06-DeleteTable.cs myApp/Program.cs
   dotnet run --project myApp
   ```

Para obtener más información sobre estos programas, consulte las siguientes secciones:
+ [01-CreateTable.cs](DAX.client.run-application-dotnet.01-CreateTable.md)
+ [02-Write-Data.cs](DAX.client.run-application-dotnet.02-Write-Data.md)
+ [03-GetItem-Test.cs](DAX.client.run-application-dotnet.03-GetItem-Test.md)
+ [04-Query-Test.cs](DAX.client.run-application-dotnet.04-Query-Test.md)
+ [05-Scan-Test.cs](DAX.client.run-application-dotnet.05-Scan-Test.md)
+ [06-DeleteTable.cs](DAX.client.run-application-dotnet.06-DeleteTable.md)

# 01-CreateTable.cs
<a name="DAX.client.run-application-dotnet.01-CreateTable"></a>

El programa `01-CreateTable.cs` crea una tabla (`TryDaxTable`). Los demás programas de .NET en esta sección dependerán de esta tabla.

```
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;

namespace ClientTest
{
    class Program
    {
        public static async Task Main(string[] args)
        {
            AmazonDynamoDBClient client = new AmazonDynamoDBClient();

            var tableName = "TryDaxTable";

            var request = new CreateTableRequest()
            {
                TableName = tableName,
                KeySchema = new List<KeySchemaElement>()
                {
                    new KeySchemaElement{ AttributeName = "pk",KeyType = "HASH"},
                    new KeySchemaElement{ AttributeName = "sk",KeyType = "RANGE"}
                },
                AttributeDefinitions = new List<AttributeDefinition>() {
                    new AttributeDefinition{ AttributeName = "pk",AttributeType = "N"},
                    new AttributeDefinition{ AttributeName = "sk",AttributeType  = "N"}
                },
                ProvisionedThroughput = new ProvisionedThroughput()
                {
                    ReadCapacityUnits = 10,
                    WriteCapacityUnits = 10
                }
            };

            var response = await client.CreateTableAsync(request);

            Console.WriteLine("Hit <enter> to continue...");
            Console.ReadLine();
        }
    }
}
```

# 02-Write-Data.cs
<a name="DAX.client.run-application-dotnet.02-Write-Data"></a>

El programa `02-Write-Data.cs` escribe datos de prueba en `TryDaxTable`.

```
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;

namespace ClientTest
{
    class Program
    {
        public static async Task Main(string[] args)
        {
            AmazonDynamoDBClient client = new AmazonDynamoDBClient();

            var tableName = "TryDaxTable";

            string someData = new string('X', 1000);
            var pkmax = 10;
            var skmax = 10;

            for (var ipk = 1; ipk <= pkmax; ipk++)
            {
                Console.WriteLine($"Writing {skmax} items for partition key: {ipk}");
                for (var isk = 1; isk <= skmax; isk++)
                {
                    var request = new PutItemRequest()
                    {
                        TableName = tableName,
                        Item = new Dictionary<string, AttributeValue>()
                       {
                            { "pk", new AttributeValue{N = ipk.ToString() } },
                            { "sk", new AttributeValue{N = isk.ToString() } },
                            { "someData", new AttributeValue{S = someData } }
                       }
                    };

                    var response = await client.PutItemAsync(request);
                }
            }

            Console.WriteLine("Hit <enter> to continue...");
            Console.ReadLine();
        }
    }
}
```

# 03-GetItem-Test.cs
<a name="DAX.client.run-application-dotnet.03-GetItem-Test"></a>

El programa `03-GetItem-Test.cs` escribe realiza operaciones `GetItem` en `TryDaxTable`.

```
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Amazon.DAX;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;

namespace ClientTest
{
    class Program
    {
        public static async Task Main(string[] args)
        {
            string endpointUri = args[0];
            Console.WriteLine($"Using DAX client - endpointUri={endpointUri}");

            var clientConfig = new DaxClientConfig(endpointUri)
            {
                AwsCredentials = FallbackCredentialsFactory.GetCredentials()
            };
            var client = new ClusterDaxClient(clientConfig);

            var tableName = "TryDaxTable";

            var pk = 1;
            var sk = 10;
            var iterations = 5;

            var startTime = System.DateTime.Now;

            for (var i = 0; i < iterations; i++)
            {
                for (var ipk = 1; ipk <= pk; ipk++)
                {
                    for (var isk = 1; isk <= sk; isk++)
                    {
                        var request = new GetItemRequest()
                        {
                            TableName = tableName,
                            Key = new Dictionary<string, AttributeValue>() {
                            {"pk", new AttributeValue {N = ipk.ToString()} },
                            {"sk", new AttributeValue {N = isk.ToString() } }
                        }
                        };
                        var response = await client.GetItemAsync(request);
                        Console.WriteLine($"GetItem succeeded for pk: {ipk},sk: {isk}");
                    }
                }
            }

            var endTime = DateTime.Now;
            TimeSpan timeSpan = endTime - startTime;
            Console.WriteLine($"Total time: {timeSpan.TotalMilliseconds} milliseconds");

            Console.WriteLine("Hit <enter> to continue...");
            Console.ReadLine();
        }
    }
}
```

# 04-Query-Test.cs
<a name="DAX.client.run-application-dotnet.04-Query-Test"></a>

El programa `04-Query-Test.cs` escribe realiza operaciones `Query` en `TryDaxTable`.

```
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Amazon.Runtime;
using Amazon.DAX;
using Amazon.DynamoDBv2.Model;

namespace ClientTest
{
    class Program
    {
        public static async Task Main(string[] args)
        {
            string endpointUri = args[0];
            Console.WriteLine($"Using DAX client - endpointUri={endpointUri}");


            var clientConfig = new DaxClientConfig(endpointUri)
            {
                AwsCredentials = FallbackCredentialsFactory.GetCredentials()
            };
            var client = new ClusterDaxClient(clientConfig);

            var tableName = "TryDaxTable";

            var pk = 5;
            var sk1 = 2;
            var sk2 = 9;
            var iterations = 5;

            var startTime = DateTime.Now;

            for (var i = 0; i < iterations; i++)
            {
                var request = new QueryRequest()
                {
                    TableName = tableName,
                    KeyConditionExpression = "pk = :pkval and sk between :skval1 and :skval2",
                    ExpressionAttributeValues = new Dictionary<string, AttributeValue>() {
                            {":pkval", new AttributeValue {N = pk.ToString()} },
                            {":skval1", new AttributeValue {N = sk1.ToString()} },
                            {":skval2", new AttributeValue {N = sk2.ToString()} }
                    }
                };
                var response = await client.QueryAsync(request);
                Console.WriteLine($"{i}: Query succeeded");

            }

            var endTime = DateTime.Now;
            TimeSpan timeSpan = endTime - startTime;
            Console.WriteLine($"Total time: {timeSpan.TotalMilliseconds} milliseconds");

            Console.WriteLine("Hit <enter> to continue...");
            Console.ReadLine();
        }
    }
}
```

# 05-Scan-Test.cs
<a name="DAX.client.run-application-dotnet.05-Scan-Test"></a>

El programa `05-Scan-Test.cs` escribe realiza operaciones `Scan` en `TryDaxTable`.

```
using System;
using System.Threading.Tasks;
using Amazon.Runtime;
using Amazon.DAX;
using Amazon.DynamoDBv2.Model;

namespace ClientTest
{
    class Program
    {
        public static async Task Main(string[] args)
        {
            string endpointUri = args[0];
            Console.WriteLine($"Using DAX client - endpointUri={endpointUri}");

            var clientConfig = new DaxClientConfig(endpointUri)
            {
                AwsCredentials = FallbackCredentialsFactory.GetCredentials()
            };
            var client = new ClusterDaxClient(clientConfig);

            var tableName = "TryDaxTable";

            var iterations = 5;

            var startTime = DateTime.Now;

            for (var i = 0; i < iterations; i++)
            {
                var request = new ScanRequest()
                {
                    TableName = tableName
                };
                var response = await client.ScanAsync(request);
                Console.WriteLine($"{i}: Scan succeeded");
            }

            var endTime = DateTime.Now;
            TimeSpan timeSpan = endTime - startTime;
            Console.WriteLine($"Total time: {timeSpan.TotalMilliseconds} milliseconds");

            Console.WriteLine("Hit <enter> to continue...");
            Console.ReadLine();
        }
    }
}
```

# 06-DeleteTable.cs
<a name="DAX.client.run-application-dotnet.06-DeleteTable"></a>

El programa `06-DeleteTable.cs` elimina `TryDaxTable`. Ejecute este programa después de haber terminado las pruebas.

```
using System;
using System.Threading.Tasks;
using Amazon.DynamoDBv2.Model;
using Amazon.DynamoDBv2;

namespace ClientTest
{
    class Program
    {
        public static async Task Main(string[] args)
        {
            AmazonDynamoDBClient client = new AmazonDynamoDBClient();

            var tableName = "TryDaxTable";

            var request = new DeleteTableRequest()
            {
                TableName = tableName
            };

            var response = await client.DeleteTableAsync(request);

            Console.WriteLine("Hit <enter> to continue...");
            Console.ReadLine();
        }
    }
}
```

# Python y DAX
<a name="DAX.client.run-application-python"></a>

Siga este procedimiento para ejecutar la aplicación de ejemplo de Python en su instancia de Amazon EC2.

**Para ejecutar la muestra de Python para DAX**

1. Instale el cliente Python de DAX mediante la utilidad `pip`.

   ```
   pip install amazon-dax-client
   ```

1. Descargue el código fuente del programa de ejemplo (archivo `.zip`).

   ```
   wget http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/samples/TryDax.zip
   ```

   Cuando haya terminado la descarga, extraiga los archivos de código fuente.

   ```
   unzip TryDax.zip
   ```

1. Ejecute los siguientes programas de Python. El primer programa crea una tabla de Amazon DynamoDB denominada `TryDaxTable`. El segundo programa escribe datos en la tabla.

   ```
   python 01-create-table.py
   python 02-write-data.py
   ```

1. Ejecute los siguientes programas de Python.

   ```
   python 03-getitem-test.py
   python 04-query-test.py
   python 05-scan-test.py
   ```

    Tome nota de la información de tiempo; es decir, del número de milisegundos necesarios para realizar las pruebas de `GetItem`, `Query` y `Scan`.

1. En el paso anterior, ha ejecutado los programas en el punto de enlace de DynamoDB. Ahora, ejecute los programas de nuevo, pero, esta vez, las operaciones `GetItem`, `Query` y `Scan` se procesan en el clúster de DAX.

   Para determinar el punto de enlace del clúster de DAX, elija una de las opciones siguientes:
   + **En la consola de DynamoDB**: elija su clúster de DAX. El punto de enlace del clúster se muestra en la consola, como en el siguiente ejemplo.

     ```
     dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
     ```
   + **En la AWS CLI**: ingrese el siguiente comando.

     ```
     aws dax describe-clusters --query "Clusters[*].ClusterDiscoveryEndpoint"
     ```

     El punto de enlace del clúster se muestra en el resultado, como en este ejemplo.

     ```
     {
         "Address": "my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com",
         "Port": 8111,
         "URL": "dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com"
     }
     ```

   Vuelva a ejecutar los programas, pero, esta vez, especifique el punto de enlace del clúster como parámetro en la línea de comandos.

   ```
   python 03-getitem-test.py dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
   python 04-query-test.py dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
   python 05-scan-test.py dax://my-cluster.l6fzcv.dax-clusters.us-east-1.amazonaws.com
   ```

   Fíjese en el resto del resultado y tome nota de la información sobre tiempos. Los tiempos transcurridos para las operaciones `GetItem`, `Query` y `Scan` deberían ser significativamente menores con DAX que con DynamoDB.

1. Ejecute el siguiente programa de Python para eliminar `TryDaxTable`.

   ```
   python 06-delete-table.py
   ```

Para obtener más información sobre estos programas, consulte las siguientes secciones:
+ [01-create-table.py](DAX.client.run-application-python.01-create-table.md)
+ [02-write-data.py](DAX.client.run-application-python.02-write-data.md)
+ [03-getitem-test.py](DAX.client.run-application-python.03-getitem-test.md)
+ [04-query-test.py](DAX.client.run-application-python.04-query-test.md)
+ [05-scan-test.py](DAX.client.run-application-python.05-scan-test.md)
+ [06-delete-table.py](DAX.client.run-application-python.06-delete-table.md)

# 01-create-table.py
<a name="DAX.client.run-application-python.01-create-table"></a>

El programa `01-create-table.py` crea una tabla (`TryDaxTable`). Los demás programas de Python en esta sección dependerán de esta tabla.

```
import boto3


def create_dax_table(dyn_resource=None):
    """
    Creates a DynamoDB table.

    :param dyn_resource: Either a Boto3 or DAX resource.
    :return: The newly created table.
    """
    if dyn_resource is None:
        dyn_resource = boto3.resource("dynamodb")

    table_name = "TryDaxTable"
    params = {
        "TableName": table_name,
        "KeySchema": [
            {"AttributeName": "partition_key", "KeyType": "HASH"},
            {"AttributeName": "sort_key", "KeyType": "RANGE"},
        ],
        "AttributeDefinitions": [
            {"AttributeName": "partition_key", "AttributeType": "N"},
            {"AttributeName": "sort_key", "AttributeType": "N"},
        ],
        "BillingMode": "PAY_PER_REQUEST",
    }
    table = dyn_resource.create_table(**params)
    print(f"Creating {table_name}...")
    table.wait_until_exists()
    return table


if __name__ == "__main__":
    dax_table = create_dax_table()
    print(f"Created table.")
```

# 02-write-data.py
<a name="DAX.client.run-application-python.02-write-data"></a>

El programa `02-write-data.py` escribe datos de prueba en `TryDaxTable`.

```
import boto3


def write_data_to_dax_table(key_count, item_size, dyn_resource=None):
    """
    Writes test data to the demonstration table.

    :param key_count: The number of partition and sort keys to use to populate the
                      table. The total number of items is key_count * key_count.
    :param item_size: The size of non-key data for each test item.
    :param dyn_resource: Either a Boto3 or DAX resource.
    """
    if dyn_resource is None:
        dyn_resource = boto3.resource("dynamodb")

    table = dyn_resource.Table("TryDaxTable")
    some_data = "X" * item_size

    for partition_key in range(1, key_count + 1):
        for sort_key in range(1, key_count + 1):
            table.put_item(
                Item={
                    "partition_key": partition_key,
                    "sort_key": sort_key,
                    "some_data": some_data,
                }
            )
            print(f"Put item ({partition_key}, {sort_key}) succeeded.")


if __name__ == "__main__":
    write_key_count = 10
    write_item_size = 1000
    print(
        f"Writing {write_key_count*write_key_count} items to the table. "
        f"Each item is {write_item_size} characters."
    )
    write_data_to_dax_table(write_key_count, write_item_size)
```

# 03-getitem-test.py
<a name="DAX.client.run-application-python.03-getitem-test"></a>

El programa `03-getitem-test.py` escribe realiza operaciones `GetItem` en `TryDaxTable`. Este ejemplo se da para la región eu-west-1. 

```
import argparse
import sys
import time
import amazondax
import boto3


def get_item_test(key_count, iterations, dyn_resource=None):
    """
    Gets items from the table a specified number of times. The time before the
    first iteration and the time after the last iteration are both captured
    and reported.

    :param key_count: The number of items to get from the table in each iteration.
    :param iterations: The number of iterations to run.
    :param dyn_resource: Either a Boto3 or DAX resource.
    :return: The start and end times of the test.
    """
    if dyn_resource is None:
        dyn_resource = boto3.resource('dynamodb')

    table = dyn_resource.Table('TryDaxTable')
    start = time.perf_counter()
    for _ in range(iterations):
        for partition_key in range(1, key_count + 1):
            for sort_key in range(1, key_count + 1):
                table.get_item(Key={
                    'partition_key': partition_key,
                    'sort_key': sort_key
                })
                print('.', end='')
                sys.stdout.flush()
    print()
    end = time.perf_counter()
    return start, end


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument(
        'endpoint_url', nargs='?',
        help="When specified, the DAX cluster endpoint. Otherwise, DAX is not used.")
    args = parser.parse_args()

    test_key_count = 10
    test_iterations = 50
    if args.endpoint_url:
        print(f"Getting each item from the table {test_iterations} times, "
              f"using the DAX client.")
        # Use a with statement so the DAX client closes the cluster after completion.
        with amazondax.AmazonDaxClient.resource(endpoint_url=args.endpoint_url, region_name='eu-west-1') as dax:
            test_start, test_end = get_item_test(
                test_key_count, test_iterations, dyn_resource=dax)
    else:
        print(f"Getting each item from the table {test_iterations} times, "
              f"using the Boto3 client.")
        test_start, test_end = get_item_test(
            test_key_count, test_iterations)
    print(f"Total time: {test_end - test_start:.4f} sec. Average time: "
          f"{(test_end - test_start)/ test_iterations}.")
```

# 04-query-test.py
<a name="DAX.client.run-application-python.04-query-test"></a>

El programa `04-query-test.py` escribe realiza operaciones `Query` en `TryDaxTable`.

```
import argparse
import time
import sys
import amazondax
import boto3
from boto3.dynamodb.conditions import Key


def query_test(partition_key, sort_keys, iterations, dyn_resource=None):
    """
    Queries the table a specified number of times. The time before the
    first iteration and the time after the last iteration are both captured
    and reported.

    :param partition_key: The partition key value to use in the query. The query
                          returns items that have partition keys equal to this value.
    :param sort_keys: The range of sort key values for the query. The query returns
                      items that have sort key values between these two values.
    :param iterations: The number of iterations to run.
    :param dyn_resource: Either a Boto3 or DAX resource.
    :return: The start and end times of the test.
    """
    if dyn_resource is None:
        dyn_resource = boto3.resource("dynamodb")

    table = dyn_resource.Table("TryDaxTable")
    key_condition_expression = Key("partition_key").eq(partition_key) & Key(
        "sort_key"
    ).between(*sort_keys)

    start = time.perf_counter()
    for _ in range(iterations):
        table.query(KeyConditionExpression=key_condition_expression)
        print(".", end="")
        sys.stdout.flush()
    print()
    end = time.perf_counter()
    return start, end


if __name__ == "__main__":
    # pylint: disable=not-context-manager
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "endpoint_url",
        nargs="?",
        help="When specified, the DAX cluster endpoint. Otherwise, DAX is not used.",
    )
    args = parser.parse_args()

    test_partition_key = 5
    test_sort_keys = (2, 9)
    test_iterations = 100
    if args.endpoint_url:
        print(f"Querying the table {test_iterations} times, using the DAX client.")
        # Use a with statement so the DAX client closes the cluster after completion.
        with amazondax.AmazonDaxClient.resource(endpoint_url=args.endpoint_url) as dax:
            test_start, test_end = query_test(
                test_partition_key, test_sort_keys, test_iterations, dyn_resource=dax
            )
    else:
        print(f"Querying the table {test_iterations} times, using the Boto3 client.")
        test_start, test_end = query_test(
            test_partition_key, test_sort_keys, test_iterations
        )

    print(
        f"Total time: {test_end - test_start:.4f} sec. Average time: "
        f"{(test_end - test_start)/test_iterations}."
    )
```

# 05-scan-test.py
<a name="DAX.client.run-application-python.05-scan-test"></a>

El programa `05-scan-test.py` escribe realiza operaciones `Scan` en `TryDaxTable`.

```
import argparse
import time
import sys
import amazondax
import boto3


def scan_test(iterations, dyn_resource=None):
    """
    Scans the table a specified number of times. The time before the
    first iteration and the time after the last iteration are both captured
    and reported.

    :param iterations: The number of iterations to run.
    :param dyn_resource: Either a Boto3 or DAX resource.
    :return: The start and end times of the test.
    """
    if dyn_resource is None:
        dyn_resource = boto3.resource("dynamodb")

    table = dyn_resource.Table("TryDaxTable")
    start = time.perf_counter()
    for _ in range(iterations):
        table.scan()
        print(".", end="")
        sys.stdout.flush()
    print()
    end = time.perf_counter()
    return start, end


if __name__ == "__main__":
    # pylint: disable=not-context-manager
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "endpoint_url",
        nargs="?",
        help="When specified, the DAX cluster endpoint. Otherwise, DAX is not used.",
    )
    args = parser.parse_args()

    test_iterations = 100
    if args.endpoint_url:
        print(f"Scanning the table {test_iterations} times, using the DAX client.")
        # Use a with statement so the DAX client closes the cluster after completion.
        with amazondax.AmazonDaxClient.resource(endpoint_url=args.endpoint_url) as dax:
            test_start, test_end = scan_test(test_iterations, dyn_resource=dax)
    else:
        print(f"Scanning the table {test_iterations} times, using the Boto3 client.")
        test_start, test_end = scan_test(test_iterations)
    print(
        f"Total time: {test_end - test_start:.4f} sec. Average time: "
        f"{(test_end - test_start)/test_iterations}."
    )
```

# 06-delete-table.py
<a name="DAX.client.run-application-python.06-delete-table"></a>

El programa `06-delete-table.py` elimina `TryDaxTable`. Ejecute este programa después de haber terminado las pruebas de la funcionalidad de Amazon DynamoDB Accelerator (DAX).

```
import boto3


def delete_dax_table(dyn_resource=None):
    """
    Deletes the demonstration table.

    :param dyn_resource: Either a Boto3 or DAX resource.
    """
    if dyn_resource is None:
        dyn_resource = boto3.resource("dynamodb")

    table = dyn_resource.Table("TryDaxTable")
    table.delete()

    print(f"Deleting {table.name}...")
    table.wait_until_not_exists()


if __name__ == "__main__":
    delete_dax_table()
    print("Table deleted!")
```