

# Uso de proyección de particiones con Amazon Athena
<a name="partition-projection"></a>

Puede utilizar la proyección de particiones en Athena para acelerar el procesamiento de consultas de tablas altamente particionadas y automatizar la administración de particiones.

En la proyección de particiones, Athena calcula los valores de partición y las ubicaciones utilizando las propiedades de tabla que configure directamente en la tabla de AWS Glue. Las propiedades de la tabla permiten a Athena “proyectar” o determinar la información de partición necesaria en lugar de tener que realizar una búsqueda de metadatos en el AWS Glue Data Catalog que consume más tiempo. Dado que las operaciones en memoria suelen ser más rápidas que las operaciones remotas, la proyección de particiones puede reducir el tiempo de ejecución de las consultas en tablas altamente particionadas. Dependiendo de las características específicas de la consulta y los datos subyacentes, la proyección de particiones puede reducir significativamente el tiempo de ejecución de la consulta para las consultas que están restringidas en la recuperación de metadatos de partición.

## Información de la eliminación de particiones frente a la proyección de particiones
<a name="partition-projection-pruning-vs-projection"></a>

La poda de partición recopila metadatos y los “poda” solo en las particiones que se aplican a su consulta. Por lo general, esto acelera las consultas. Athena utiliza la poda de particiones para todas las tablas con columnas de partición, incluidas las tablas configuradas para la proyección de particiones.

Normalmente, al procesar consultas, Athena realiza una llamada `GetPartitions` al AWS Glue Data Catalog antes de realizar la poda de partición. Si una tabla tiene un gran número de particiones, el uso de `GetPartitions` puede afectar negativamente el rendimiento. Para evitar esto, puede usar la proyección de particiones. La proyección de particiones permite a Athena evitar llamadas a `GetPartitions` porque la configuración de proyección de particiones proporciona a Athena toda la información necesaria para construir las particiones en sí.

## Procedimientos para usar la proyección de particiones
<a name="partition-projection-using"></a>

Para utilizar la proyección de particiones, especifique los intervalos de valores de partición y tipos de proyección para cada columna de partición en las propiedades de tabla en el AWS Glue Data Catalog o en el [metaalmacén externo de Hive](connect-to-data-source-hive.md). Estas propiedades personalizadas en la tabla le permiten a Athena saber qué patrones de partición esperar cuando ejecuta una consulta en la tabla. Durante la ejecución de la consulta, Athena utiliza esta información para proyectar los valores de partición en lugar de recuperarlos desde el metaalmacén externo de Hive o AWS Glue Data Catalog. Esto no solo reduce el tiempo de ejecución de la consulta, sino que también automatiza la administración de particiones, ya que elimina la necesidad de crear manualmente particiones en Athena, el metaalmacén externo de Hive o AWS Glue.

**importante**  
Habilitar la proyección de particiones en una tabla hace que Athena ignore los metadatos de partición registrados en la tabla en el metaalmacén externo de Hive o AWS Glue Data Catalog.

## Algunos casos de uso
<a name="partition-projection-use-cases"></a>

Entre los escenarios en los que la proyección de particiones es útil se incluyen los siguientes:
+ Las consultas contra una tabla altamente particionada no se completan tan rápido como le gustaría.
+ Las particiones se agregan regularmente a las tablas a medida que se crean nuevas particiones de fecha u hora en los datos. Con la proyección de particiones, puede configurar intervalos de fechas relativos que se pueden utilizar a medida que llegan nuevos datos. 
+ Tiene datos altamente particionados en Amazon S3. Los datos no son prácticos para modelar en su metaalmacén AWS Glue Data Catalog o Hive, y sus consultas solo leen pequeñas partes de ellos.

### Estructuras de partición proyectables
<a name="partition-projection-known-data-structures"></a>

La proyección de particiones se configura más fácilmente cuando las particiones siguen un patrón predecible como, entre otros, los siguientes:
+ **Enteros**: cualquier secuencia continua de enteros como `[1, 2, 3, 4, ..., 1000]` o `[0500, 0550, 0600, ..., 2500]`.
+ **Fechas**: cualquier secuencia continua de fechas o fechas y horas como `[20200101, 20200102, ..., 20201231]` o `[1-1-2020 00:00:00, 1-1-2020 01:00:00, ..., 12-31-2020 23:00:00]`.
+ **Valores enumerados**: un conjunto finito de valores enumerados como códigos de aeropuertos o Regiones de AWS.
+ **Registros de Servicio de AWS**: normalmente, los registros de Servicio de AWS tienen una estructura conocida cuyo esquema de particiones puede especificar en AWS Glue y que, por lo tanto, Athena puede utilizar para la proyección de particiones.

### Procedimientos para personalizar la plantilla de ruta de partición
<a name="partition-projection-custom-s3-storage-locations"></a>

De forma predeterminada, Athena crea ubicaciones de partición utilizando el formulario `s3://amzn-s3-demo-bucket/<table-root>/partition-col-1=<partition-col-1-val>/partition-col-2=<partition-col-2-val>/`, pero si sus datos están organizados de manera diferente, Athena ofrece un mecanismo para personalizar esta plantilla de ruta. Para ver los pasos, consulte [Procedimientos para especificar ubicaciones de almacenamiento de S3 personalizadas](partition-projection-setting-up.md#partition-projection-specifying-custom-s3-storage-locations).

## Consideraciones y limitaciones
<a name="partition-projection-considerations-and-limitations"></a>

Tenga en cuenta las siguientes consideraciones:
+ La proyección de particiones elimina la necesidad de especificar particiones manualmente en AWS Glue o en un metaalmacén externo de Hive.
+ Cuando habilita la proyección de particiones en una tabla, Athena ignora los metadatos de partición en AWS Glue Data Catalog o el metaalmacén externo de Hive de esa tabla.
+ Si una partición proyectada no existe en Amazon S3, Athena seguirá proyectando la partición. Athena no arroja un error, pero no se devuelve ningún dato. Sin embargo, si hay demasiadas particiones vacías, el rendimiento puede ser más lento en comparación con las particiones de AWS Glue tradicionales. Si más de la mitad de las particiones proyectadas están vacías, se recomienda utilizar particiones tradicionales.
+ Las consultas de valores que están más allá de los límites de intervalos definidos para la proyección de particiones no devuelven ningún error. En su lugar, la consulta se ejecuta, pero devuelve cero filas. Por ejemplo, si tiene datos relacionados con el tiempo que comienzan en 2020 y se definen como `'projection.timestamp.range'='2020/01/01,NOW'`, una consulta como `SELECT * FROM table-name WHERE timestamp = '2019/02/02'` se completará correctamente, pero devolverá cero filas.
+ La proyección de particiones solo se puede utilizar cuando se consulta la tabla a través de Athena. Si se lee la misma tabla a través de otro servicio, como Amazon Redshift Spectrum, Athena para Spark o Amazon EMR, se utilizan los metadatos de partición estándar.
+ Dado que la proyección de particiones es una característica de solo DML, `SHOW PARTITIONS` no enumera las particiones proyectadas por Athena pero no registradas en el catálogo de AWS Glue o en el metaalmacén externo de Hive. 
+ Athena no utiliza las propiedades de tabla de vistas como configuración para la proyección de particiones. Para evitar esta limitación, configure y habilite la proyección de particiones en las propiedades de tabla para las tablas a las que hacen referencia las vistas.

## Video
<a name="partition-projection-video"></a>

En el siguiente video se muestra cómo utilizar la proyección de particiones para mejorar el rendimiento de las consultas en Athena.

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/iUD5pPpcyZk/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/iUD5pPpcyZk)


**Topics**
+ [Información de la eliminación de particiones frente a la proyección de particiones](#partition-projection-pruning-vs-projection)
+ [Procedimientos para usar la proyección de particiones](#partition-projection-using)
+ [Algunos casos de uso](#partition-projection-use-cases)
+ [Consideraciones y limitaciones](#partition-projection-considerations-and-limitations)
+ [Video](#partition-projection-video)
+ [Configuración de la proyección de particiones](partition-projection-setting-up.md)
+ [Tipos admitidos para la proyección de particiones](partition-projection-supported-types.md)
+ [Uso de partición de ID dinámica](partition-projection-dynamic-id-partitioning.md)
+ [Ejemplo de Amazon Data Firehose](partition-projection-kinesis-firehose-example.md)

# Configuración de la proyección de particiones
<a name="partition-projection-setting-up"></a>

Configurar la proyección de particiones en las propiedades de una tabla es un proceso de dos pasos:

1. Especifique los intervalos de datos y los patrones relevantes para cada columna de partición, o utilice una plantilla personalizada.

1. Habilite la proyección de particiones para la tabla.

**nota**  
Antes de agregar propiedades de proyección de particiones a una tabla existente, la columna de partición para la que va a configurar las propiedades de proyección de particiones ya debe existir en el esquema de la tabla. Si la columna de partición aún no existe, debe agregar una columna de partición a la tabla existente manualmente. AWS Glue no realiza este paso automáticamente. 

En esta sección se muestra cómo establecer estas propiedades de tabla para AWS Glue. Para configurarlas, puede utilizar la consola de AWS Glue, las consultas [CREATE TABLE](create-table.md) de Athena o las operaciones de [AWS Glue API](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api.html). El siguiente procedimiento muestra cómo establecer las propiedades en la consola de AWS Glue.

**: cómo configurar y habilitar la proyección de particiones mediante la consola de AWS Glue**

1. Inicie sesión en la Consola de administración de AWS y abra la consola de AWS Glue en [https://console.aws.amazon.com/glue/](https://console.aws.amazon.com/glue/).

1. Seleccione la pestaña **Tablas**.

   En la pestaña **Tablas** puede editar tablas existentes o elegir **Agregar tablas** para crear otras nuevas. Para obtener información sobre cómo agregar tablas manualmente o con un rastreador, consulte [Trabajo con tablas en la consola de AWS Glue](https://docs.aws.amazon.com/glue/latest/dg/console-tables.html) en la *Guía para desarrolladores de AWS Glue*.

1. En la lista de tablas, elija el vínculo de la tabla que desea editar.  
![\[En la consola de AWS Glue, elija una tabla para editar.\]](http://docs.aws.amazon.com/es_es/athena/latest/ug/images/partition-projection-1.png)

1. Seleccione **Acciones**, **Editar la tabla**.

1. En la página **Editar la tabla**, en la sección **Propiedades de la tabla**, agregue el siguiente par de clave-valor en cada columna particionada:

   1. En **Clave**, añada `projection.columnName.type`.

   1. En **Valor**, añada uno de los tipos admitidos: `enum`, `integer`, `date`, o `injected`. Para obtener más información, consulte [Tipos admitidos para la proyección de particiones](partition-projection-supported-types.md).

1. Siguiendo las instrucciones de [Tipos admitidos para la proyección de particiones](partition-projection-supported-types.md), añada pares clave-valor adicionales de acuerdo con sus requisitos de configuración.

   La siguiente configuración de tabla de ejemplo configura la columna `year` para la proyección de particiones, lo que restringe los valores que se pueden devolver a un intervalo comprendido entre 2010 y 2016.  
![\[Configuración de la proyección de particiones para una columna de partición en las propiedades de la tabla de la consola de AWS Glue.\]](http://docs.aws.amazon.com/es_es/athena/latest/ug/images/partition-projection-3.png)

1. Añada un par clave-valor para habilitar la proyección de particiones. En **Clave**, escriba `projection.enabled`, y en su **Valor**, escriba `true`.
**nota**  
Puede deshabilitar la proyección de particiones en esta tabla en cualquier momento estableciendo `projection.enabled` como `false`.

1. Cuando termine de actualizar las etiquetas, elija **Guardar**.

1. En el Editor de consultas de Athena, pruebe la consulta de las columnas que configuró para la tabla.

   La siguiente consulta de ejemplo utiliza `SELECT DISTINCT` para devolver los valores únicos de la columna `year`. La base de datos contiene datos de 1987 a 2016, pero la propiedad `projection.year.range` restringe los valores devueltos a los años 2010 a 2016.  
![\[Consultar una columna que utiliza la proyección de particiones.\]](http://docs.aws.amazon.com/es_es/athena/latest/ug/images/partition-projection-5.png)
**nota**  
Si establece `projection.enabled` como `true` pero no puede configurar una o más columnas de partición, recibirá un mensaje de error como el siguiente:  
`HIVE_METASTORE_ERROR: Table database_name.table_name is configured for partition projection, but the following partition columns are missing projection configuration: [column_name] (table database_name.table_name)`.

## Procedimientos para especificar ubicaciones de almacenamiento de S3 personalizadas
<a name="partition-projection-specifying-custom-s3-storage-locations"></a>

Al editar propiedades de tabla en AWS Glue, también puede especificar una plantilla de ruta de Amazon S3 personalizada para las particiones proyectadas. Una plantilla personalizada permite a Athena asignar correctamente valores de partición a ubicaciones de archivos de Amazon S3 personalizadas que no siguen un patrón `.../column=value/...` típico. 

El uso de una plantilla personalizada es opcional. Sin embargo, si utiliza una plantilla personalizada, la plantilla debe contener un marcador de posición para cada columna de partición. Las ubicaciones con plantilla deben terminar con una barra diagonal para que los archivos de datos particionados se alojen en una “carpeta” por partición.

**Para especificar una plantilla de ubicación de partición personalizada**

1. Siguiendo los pasos para [configurar y habilitar la proyección de particiones mediante la consola de AWS Glue](#partition-projection-setting-up-procedure), agregue un par clave-valor adicional que especifique una plantilla personalizada de la siguiente manera:

   1. En **Clave**, escriba `storage.location.template`.

   1. En **Valor**, especifique una ubicación que incluya un marcador de posición para cada columna de partición. Asegúrese de que cada marcador de posición (y la ruta de S3 en sí) termine con una sola barra diagonal.

      En los siguientes valores de plantilla de ejemplo se asume una tabla con columnas de partición `a`, `b` y `c`.

      ```
      s3://amzn-s3-demo-bucket/table_root/a=${a}/${b}/some_static_subdirectory/${c}/      
      ```

      ```
      s3://amzn-s3-demo-bucket/table_root/c=${c}/${b}/some_static_subdirectory/${a}/${b}/${c}/${c}/      
      ```

      En la misma tabla, el siguiente valor de plantilla de ejemplo no es válido porque no contiene marcador de posición para la columna `c`.

      ```
      s3://amzn-s3-demo-bucket/table_root/a=${a}/${b}/some_static_subdirectory/         
      ```

1. Seleccione **Aplicar**.

# Tipos admitidos para la proyección de particiones
<a name="partition-projection-supported-types"></a>

Una tabla puede tener cualquier combinación de tipos de columna de partición `enum`, `integer`, `date,` o `injected`.

## Tipo enum
<a name="partition-projection-enum-type"></a>

Utilice el tipo `enum` para las columnas de partición cuyos valores sean miembros de un conjunto enumerado (por ejemplo, códigos de aeropuerto o Regiones de AWS).

Defina las propiedades de partición en la tabla de la siguiente manera:


****  

| Nombre de la propiedad | Valores de ejemplo | Descripción | 
| --- | --- | --- | 
| projection.columnName.type |  `enum`  | Obligatorio. El tipo de proyección que se va a utilizar en la columna columnName. El valor debe ser enum (sin distinción mayúsculas y minúsculas) para indicar el uso del tipo enum. Se permite un espacio en blanco inicial y final. | 
| projection.columnName.values |  `A,B,C,D,E,F,G,Unknown`  | Obligatorio. Lista separada por comas de los valores de partición enumerados para la columna columnName. Cualquier espacio en blanco se considera parte de un valor enum. | 

**nota**  
Como práctica recomendada, sugerimos limitar el uso de proyecciones de partición basadas en `enum` a unas pocas docenas o menos. Si bien no hay un límite específico para las proyecciones `enum`, el tamaño total de los metadatos de la tabla no puede superar el límite de AWS Glue de aproximadamente 1 MB cuando se comprime a gzip. Tenga en cuenta que este límite se comparte entre partes clave de la tabla, como nombres de columna, ubicación, formato de almacenamiento y otros. Si utiliza más de unas cuantas docenas de identificadores únicos en la proyección `enum`, considere un enfoque alternativo, como la asignación de buckets en un número menor de valores únicos en un campo sustituto. Al intercambiar cardinalidad, puede controlar el número de valores únicos en `enum`. 

## Tipo entero
<a name="partition-projection-integer-type"></a>

Utilice el tipo entero para las columnas de partición cuyos valores posibles sean interpretables como enteros dentro de un intervalo definido. Las columnas enteras proyectadas se limitan actualmente al intervalo de un Java con signo largo (-263 a 263-1 inclusive).


****  

| Nombre de la propiedad | Valores de ejemplo | Descripción | 
| --- | --- | --- | 
| projection.columnName.type |  `integer`  | Obligatorio. El tipo de proyección que se va a utilizar en la columna columnName. El valor debe ser integer (sin distinción entre mayúsculas y minúsculas) para indicar el uso del tipo entero. Se permite un espacio en blanco inicial y final. | 
| projection.columnName.range |  `0,10` `-1,8675309` `0001,9999`  | Obligatorio. Lista separada por comas de dos elementos que proporciona los valores de intervalo mínimo y máximo que deben devolver las consultas de la columna columnName. Tenga en cuenta que los valores deben estar separados por una coma, no por un guion. Estos valores son inclusivos, pueden ser negativos y pueden tener ceros a la izquierda. Se permite un espacio en blanco inicial y final. | 
| projection.columnName.interval |  `1` `5`  | Opcional. Un entero positivo que especifica el intervalo entre los valores de partición sucesivos en la columna columnName. Por ejemplo, un valor range de “1,3” con un valor interval de “1” produce los valores 1, 2 y 3. El mismo valor range con un valor interval de “2” produce los valores 1 y 3, omitiendo 2. Se permite un espacio en blanco inicial y final. El valor predeterminado es 1. | 
| projection.columnName.digits |  `1` `5`  | Opcional. Un entero positivo que especifica el número de dígitos que se incluirán en la representación final del valor de partición de la columna columnName. Por ejemplo, un valor de range de “1,3” que tiene un valor de digits de “1” produce los valores 1, 2 y 3. El mismo valor de range con un valor de digits de “2” produce los valores 01, 02 y 03. Se permite un espacio en blanco inicial y final. Por defecto, no hay número estático de dígitos ni ceros a la izquierda. | 

## Tipo de fecha
<a name="partition-projection-date-type"></a>

Utilice el tipo de fecha para las columnas de partición cuyos valores se pueden interpretar como fechas (con horas opcionales) dentro de un rango definido.

**importante**  
Las columnas de fecha proyectada se generan en hora universal coordinada (UTC) en el momento de ejecución de la consulta.


****  

| Nombre de la propiedad | Valores de ejemplo | Descripción | 
| --- | --- | --- | 
| projection.columnName.type |  `date`  | Obligatorio. El tipo de proyección que se va a utilizar en la columna columnName. El valor debe ser date (sin distinción entre mayúsculas y minúsculas) para indicar el uso del tipo de fecha. Se permite un espacio en blanco inicial y final. | 
| projection.columnName.range |  `201701,201812` `01-01-2010,12-31-2018` `NOW-3YEARS,NOW` `201801,NOW+1MONTH`  |  Obligatorio. Lista separada por comas de dos elementos que proporciona los valores `range` mínimo y máximo de la columna *columnName*. Estos valores son inclusivos y pueden utilizar cualquier formato compatible con los tipos de fechas `java.time.*` de Java. Tanto los valores mínimo como máximo deben utilizar el mismo formato. El formato especificado en la propiedad `.format` debe ser el formato utilizado para estos valores. Esta columna también puede contener cadenas de fecha relativas, con el formato de este patrón de expresión regular: `\s*NOW\s*(([\+\-])\s*([0-9]+)\s*(YEARS?\|MONTHS?\|WEEKS?\|DAYS?\|HOURS?\|MINUTES?\|SECONDS?)\s*)?` Se permiten espacios en blanco, pero los literales de fecha se consideran parte de las cadenas de fecha.  | 
| projection.columnName.format |  `yyyyMM` `dd-MM-yyyy` `dd-MM-yyyy-HH-mm-ss`  | Obligatorio. Una cadena de formato de fecha basada en el formato de fecha Java [DateTimeFormatter](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html). Puede ser cualquier tipo de Java.time.\$1 compatible. | 
| projection.columnName.interval |  `1` `5`  |  Un entero positivo que especifica el intervalo entre los valores de partición sucesivos de la columna *columnName*. Por ejemplo, un valor de `range` de `2017-01,2018-12` con un valor de `interval` de `1` y un valor de `interval.unit` de `MONTHS` produce los valores 2017-01, 2017-02, 2017-03, etc. El mismo valor de `range` con un valor de `interval` de `2` y un valor de `interval.unit` de `MONTHS` produce los valores 2017-01, 2017-03, 2017-05, etc. Se permite un espacio en blanco inicial y final. Cuando las fechas proporcionadas tienen una precisión de un solo día o de un mes, la `interval` es opcional y el valor predeterminado es 1 día o 1 mes, respectivamente. De lo contrario, se requiere el `interval`.  | 
| projection.columnName.interval.unit |  `YEARS` `MONTHS` `WEEKS` `DAYS` `HOURS` `MINUTES` `SECONDS` `MILLIS`  |  Palabra de unidad de tiempo que representa la forma serializada de una [ChronoUnit](https://docs.oracle.com/javase/8/docs/api/java/time/temporal/ChronoUnit.html). Los valores posibles son `YEARS`, `MONTHS`, `WEEKS`, `DAYS`, `HOURS`, `MINUTES`, `SECONDS` o `MILLIS`. Los valores no distinguen entre mayúsculas y minúsculas. Cuando las fechas proporcionadas tienen una precisión de un solo día o de un mes, la `interval.unit` es opcional y el valor predeterminado es 1 día o 1 mes, respectivamente. De lo contrario, se requiere la `interval.unit`.  | 

**Example – Partición por mes**  
La siguiente tabla de configuración de ejemplo divide los datos por mes desde 2015 hasta la actualidad.  

```
'projection.month.type'='date', 
'projection.month.format'='yyyy-MM', 
'projection.month.interval'='1', 
'projection.month.interval.unit'='MONTHS', 
'projection.month.range'='2015-01,NOW', 
...
```

## Tipo inyectado
<a name="partition-projection-injected-type"></a>

Utilice el tipo inyectado para columnas de partición con valores posibles que no se pueden generar procesalmente dentro de algún intervalo lógico pero que se proporcionan en una cláusula `WHERE` de la consulta como un solo valor.

Es importante tener en cuenta los siguientes puntos:
+ Las consultas sobre columnas inyectadas fallan si no se proporciona una expresión de filtro para cada columna inyectada.
+ Las consultas con múltiples valores para una expresión de filtro en una columna inyectada solo funcionan si los valores están separados.
+ Solo se admiten las columnas de tipo `string`.
+ Cuando utiliza la cláusula `WHERE IN` con una columna de partición inyectada, hay un límite de 1000 valores que se pueden especificar en la lista `IN`. Para consultar un conjunto de datos con más de 1000 particiones para una columna inyectada, divida la consulta en múltiples consultas más pequeñas, cada una con hasta 1000 valores en la cláusula `WHERE IN`, y luego agregue los resultados.


****  

| Nombre de la propiedad | Valor | Descripción | 
| --- | --- | --- | 
| projection.columnName.type |  `injected`  | Obligatorio. El tipo de proyección que se va a utilizar en la columna columnName. Solo se admite el tipo string. El valor especificado debe ser injected (sin distinción entre mayúsculas y minúsculas). Se permite un espacio en blanco inicial y final. | 

Para obtener más información, consulte [Cuándo usar el tipo de proyección de `injected`](partition-projection-dynamic-id-partitioning.md#partition-projection-injection).

# Uso de partición de ID dinámica
<a name="partition-projection-dynamic-id-partitioning"></a>

Si los datos están divididos por una propiedad con cardinalidad alta o cuando los valores no se pueden conocer de antemano, puede utilizar el tipo de proyección `injected`. Algunos ejemplos de estas propiedades son los nombres de usuario y los ID de dispositivos o productos. Cuando se utiliza el tipo de proyección `injected` para configurar una clave de partición, Athena utiliza los valores de la propia consulta para calcular el conjunto de particiones que se leerán.

Para que Athena pueda ejecutar una consulta en una tabla que tenga una clave de partición configurada con el tipo de proyección `injected`, debe cumplirse lo siguiente:
+ La consulta debe incluir al menos un valor para la clave de partición.
+ Los valores deben ser literales o expresiones que se puedan evaluar sin leer ningún dato.

Si no se cumple alguno de estos criterios, la consulta fallará y mostrará el siguiente error:

CONSTRAINT\$1VIOLATION: En el caso de la columna de partición proyectada inyectada *column\$1name*, la cláusula WHERE debe contener únicamente condiciones de igualdad estáticas, y al menos una de estas condiciones debe estar presente.

## Cuándo usar el tipo de proyección de `injected`
<a name="partition-projection-injection"></a>

Imagine que tiene un conjunto de datos que consta de eventos de dispositivos de IoT, particionados en los ID de los dispositivos. Este conjunto de datos incluye las siguientes características:
+ Los ID de los dispositivos se generan de forma aleatoria.
+ Los dispositivos nuevos se aprovisionan con frecuencia.
+ Actualmente, hay cientos de miles de dispositivos y en el futuro habrá millones.

Este conjunto de datos es difícil de administrar con los metaalmacenes tradicionales. Es difícil mantener las particiones sincronizadas entre el almacenamiento de datos y el metaalmacén, y el filtrado de las particiones puede resultar ser lento durante la planificación de las consultas. Sin embargo, si configura una tabla para usar la proyección de particiones y usa el tipo de proyección `injected`, tiene dos ventajas: no tiene que administrar las particiones en el metaalmacén y sus consultas no tienen que buscar los metadatos de las particiones.

En el siguiente ejemplo de `CREATE TABLE`, se crea una tabla para el conjunto de datos de eventos del dispositivo que se acaba de describir. La tabla utiliza el tipo de proyección inyectada.

```
CREATE EXTERNAL TABLE device_events (
  event_time TIMESTAMP,
  data STRING,
  battery_level INT
)
PARTITIONED BY (
  device_id STRING
)
LOCATION "s3://amzn-s3-demo-bucket/prefix/"
TBLPROPERTIES (
  "projection.enabled" = "true",
  "projection.device_id.type" = "injected",
  "storage.location.template" = "s3://amzn-s3-demo-bucket/prefix/${device_id}"
)
```

La siguiente consulta de ejemplo busca el número de eventos recibidos de tres dispositivos específicos en el transcurso de 12 horas.

```
SELECT device_id, COUNT(*) AS events
FROM device_events
WHERE device_id IN (
  '4a770164-0392-4a41-8565-40ed8cec737e',
  'f71d12cf-f01f-4877-875d-128c23cbde17',
  '763421d8-b005-47c3-ba32-cc747ab32f9a'
)
AND event_time BETWEEN TIMESTAMP '2023-11-01 20:00' AND TIMESTAMP '2023-11-02 08:00'
GROUP BY device_id
```

Al ejecutar esta consulta, Athena ve los tres valores de la clave de partición `device_id` y los usa para calcular las ubicaciones de las particiones. Athena utiliza el valor de la propiedad `storage.location.template` para generar las siguientes ubicaciones:
+ `s3://amzn-s3-demo-bucket/prefix/4a770164-0392-4a41-8565-40ed8cec737e`
+ `s3://amzn-s3-demo-bucket/prefix/f71d12cf-f01f-4877-875d-128c23cbde17`
+ `s3://amzn-s3-demo-bucket/prefix/763421d8-b005-47c3-ba32-cc747ab32f9a`

Si omite la propiedad `storage.location.template` en la configuración de proyección de la partición, Athena utiliza la partición tipo Hive para proyectar las ubicaciones de las particiones en función del valor de `LOCATION` (por ejemplo, `s3://amzn-s3-demo-bucket/prefix/device_id=4a770164-0392-4a41-8565-40ed8cec737e`).

# Ejemplo de Amazon Data Firehose
<a name="partition-projection-kinesis-firehose-example"></a>

Cuando se usa Firehose para entregar datos a Amazon S3, la configuración predeterminada escribe objetos con claves que se parecen al siguiente ejemplo:

```
s3://amzn-s3-demo-bucket/prefix/yyyy/MM/dd/HH/file.extension
```

Para crear una tabla de Athena que encuentre las particiones de forma automática en el momento de la consulta, en lugar de tener que agregarlas al catálogo de datos de AWS Glue Data Catalog a medida que llegan nuevos datos, puede usar la proyección de particiones.

En el siguiente ejemplo de `CREATE TABLE` se usa la configuración predeterminada de Firehose.

```
CREATE EXTERNAL TABLE my_ingested_data (
 ...
)
...
PARTITIONED BY (
 datehour STRING
)
LOCATION "s3://amzn-s3-demo-bucket/prefix/"
TBLPROPERTIES (
 "projection.enabled" = "true",
 "projection.datehour.type" = "date",
 "projection.datehour.format" = "yyyy/MM/dd/HH",
 "projection.datehour.range" = "2021/01/01/00,NOW",
 "projection.datehour.interval" = "1",
 "projection.datehour.interval.unit" = "HOURS",
 "storage.location.template" = "s3://amzn-s3-demo-bucket/prefix/${datehour}/"
)
```

La cláusula `TBLPROPERTIES` de la instrucción `CREATE TABLE` indica a Athena lo siguiente:
+ Usar la proyección de la partición al consultar la tabla
+ La clave de partición `datehour` es de tipo `date` (que incluye una hora opcional)
+ Cómo se formatean las fechas
+ El rango de fechas y horas. Tenga en cuenta que los valores deben estar separados por una coma, no por un guion.
+ Dónde encontrar los datos en Amazon S3.

Al consultar la tabla, Athena calcula los valores de `datehour` y usa la plantilla de ubicación de almacenamiento para generar una lista de ubicaciones de partición.

**Topics**
+ [Cómo usar el tipo `date`](partition-projection-kinesis-firehose-example-using-the-date-type.md)
+ [Cómo elegir las claves de partición](partition-projection-kinesis-firehose-example-choosing-partition-keys.md)
+ [Cómo utilizar los prefijos personalizados y las particiones dinámicas](partition-projection-kinesis-firehose-example-using-custom-prefixes-and-dynamic-partitioning.md)

# Cómo usar el tipo `date`
<a name="partition-projection-kinesis-firehose-example-using-the-date-type"></a>

Cuando se usa el tipo `date` para una clave de partición proyectada, se debe especificar un rango. Como no tiene datos para fechas anteriores a la creación del flujo de entrega de Firehose, puede usar la fecha de creación como inicio. Y como no tiene datos para fechas en el futuro, puede usar el token especial `NOW` como fin.

En el ejemplo de `CREATE TABLE`, la fecha de inicio se especifica como 1 de enero de 2021 a medianoche UTC.

**nota**  
Configure un rango que se ajuste lo más posible a sus datos para que Athena busque solo las particiones existentes.

Cuando se ejecuta una consulta en la tabla de ejemplo, Athena usa las condiciones de la clave de partición `datehour` en combinación con el rango para generar valores. Analice la siguiente consulta:

```
SELECT *
FROM my_ingested_data
WHERE datehour >= '2020/12/15/00'
AND datehour < '2021/02/03/15'
```

La primera condición de la consulta `SELECT` usa una fecha que es anterior al inicio del rango de fechas especificado por la instrucción `CREATE TABLE`. Como la configuración de la proyección de la partición especifica que no hay particiones para las fechas anteriores al 1 de enero de 2021, Athena busca datos solo en las siguientes ubicaciones, e ignora las fechas anteriores a la consulta.

```
s3://amzn-s3-demo-bucket/prefix/2021/01/01/00/
s3://amzn-s3-demo-bucket/prefix/2021/01/01/01/
s3://amzn-s3-demo-bucket/prefix/2021/01/01/02/
...
s3://amzn-s3-demo-bucket/prefix/2021/02/03/12/
s3://amzn-s3-demo-bucket/prefix/2021/02/03/13/
s3://amzn-s3-demo-bucket/prefix/2021/02/03/14/
```

Del mismo modo, si la consulta se ejecuta en una fecha y hora anteriores al 3 de febrero de 2021 a las 15:00 h, la última partición reflejaría la fecha y hora actuales, no la fecha y hora de la condición de consulta.

Si quiere consultar los datos más recientes, puede aprovechar el hecho de que Athena no genera fechas futuras y especificar solo una `datehour` de inicio, como en el siguiente ejemplo.

```
SELECT *
FROM my_ingested_data
WHERE datehour >= '2021/11/09/00'
```

# Cómo elegir las claves de partición
<a name="partition-projection-kinesis-firehose-example-choosing-partition-keys"></a>

Puede especificar cómo la proyección de particiones asigna las ubicaciones de las particiones a las claves de partición. En el ejemplo de `CREATE TABLE` de la sección anterior, la fecha y la hora se han combinado en una clave de partición denominada datehour, pero se pueden usar otros esquemas. Por ejemplo, también podría configurar una tabla con claves de partición separadas para el año, el mes, el día y la hora. 

No obstante, si se dividen las fechas en año, mes y día no se puede utilizar el tipo de proyección de particiones `date`. Una alternativa es separar la fecha de la hora para seguir aprovechando el tipo de proyección de particiones `date`, pero realizar consultas que especifiquen intervalos de horas más fáciles de leer.

Con esto en mente, el siguiente ejemplo `CREATE TABLE` separa la fecha de la hora. Debido a que `date` es una palabra reservada en SQL, en el ejemplo se utiliza `day` como nombre para la clave de partición que representa la fecha.

```
CREATE EXTERNAL TABLE my_ingested_data2 (
 ...
)
...
PARTITIONED BY (
 day STRING,
 hour INT
)
LOCATION "s3://amzn-s3-demo-bucket/prefix/"
TBLPROPERTIES (
 "projection.enabled" = "true",
 "projection.day.type" = "date",
 "projection.day.format" = "yyyy/MM/dd",
 "projection.day.range" = "2021/01/01,NOW",
 "projection.day.interval" = "1",
 "projection.day.interval.unit" = "DAYS",
 "projection.hour.type" = "integer",
 "projection.hour.range" = "0,23",
 "projection.hour.digits" = "2",
 "storage.location.template" = "s3://amzn-s3-demo-bucket/prefix/${day}/${hour}/"
)
```

En la instrucción `CREATE TABLE` del ejemplo, la hora es una clave de partición independiente, configurada como un número entero. La configuración de la clave de partición de la hora especifica el rango de 0 a 23, y que la hora debe formatearse con dos dígitos cuando Athena genera las ubicaciones de la partición.

Una consulta para la tabla `my_ingested_data2` podría verse así:

```
SELECT *
FROM my_ingested_data2
WHERE day = '2021/11/09'
AND hour > 3
```

## Descripción de los tipos de datos de claves de particiones y proyección de particiones
<a name="partition-projection-kinesis-firehose-example-partition-key-types-and-partition-projection-types"></a>

Tenga en cuenta que la clave `datehour` en el primer ejemplo `CREATE TABLE` está configurada como `date` en la configuración de la proyección de particiones, pero el tipo de la clave de partición es `string`. Lo mismo ocurre con `day` en el segundo ejemplo. Los tipos de configuración de proyección de particiones solo le dicen a Athena cómo formatear los valores cuando genera las ubicaciones de las particiones. Los tipos que se especifican no cambian el tipo de la clave de partición: en las consultas, `datehour` y `day` son de tipo `string`.

Cuando una consulta incluye una condición como `day = '2021/11/09'`, Athena analiza la cadena a la derecha de la expresión con el formato de fecha especificado en la configuración de la proyección de particiones. Después de que Athena verifique que la fecha está dentro del rango configurado, usa de nuevo el formato de fecha para insertar la fecha como una cadena en la plantilla del almacén.

De forma similar, para una condición de consulta como `day > '2021/11/09'`, Athena analiza el lado derecho y genera una lista de todas las fechas coincidentes dentro del rango configurado. A continuación, usa el formato de fecha para insertar cada fecha en la plantilla de ubicación de almacenamiento para crear la lista de ubicaciones de partición.

Escribir la misma condición como día `day > '2021-11-09'` o día `day > DATE '2021-11-09'` no funciona. En el primer caso, el formato de la fecha no coincide (observe los guiones en lugar de las barras inclinadas), y en el segundo caso, los tipos de datos no coinciden.

# Cómo utilizar los prefijos personalizados y las particiones dinámicas
<a name="partition-projection-kinesis-firehose-example-using-custom-prefixes-and-dynamic-partitioning"></a>

Firehose puede configurarse con [prefijos personalizados](https://docs.aws.amazon.com/firehose/latest/dev/s3-prefixes.html) y [partición dinámica](https://docs.aws.amazon.com/firehose/latest/dev/dynamic-partitioning.html). Mediante estas características, puede configurar las claves de Amazon S3 y establecer esquemas de partición más compatibles con su caso de uso. También puede usar la proyección de particiones con estos esquemas de partición y configurarlos en consecuencia.

Por ejemplo, puede usar la característica de prefijo personalizado para obtener claves de Amazon S3 que tengan fechas con formato ISO en lugar del esquema predeterminado `yyyy/MM/dd/HH`.

También puede combinar los prefijos personalizados con el particionamiento dinámico para extraer una propiedad como `customer_id` de los mensajes de Firehose, como en el siguiente ejemplo.

```
prefix/!{timestamp:yyyy}-!{timestamp:MM}-!{timestamp:dd}/!{partitionKeyFromQuery:customer_id}/
```

Con ese prefijo de Amazon S3, el flujo de entrega de Firehose escribiría objetos en claves como `s3://amzn-s3-demo-bucket/prefix/2021-11-01/customer-1234/file.extension`. Para una propiedad como `customer_id`, cuyos valores pueden no conocerse de antemano, se puede usar el tipo de proyección de particiones `injected` y usar una instrucción `CREATE TABLE` como la siguiente:

```
CREATE EXTERNAL TABLE my_ingested_data3 (
 ...
)
...
PARTITIONED BY (
 day STRING,
 customer_id STRING
)
LOCATION "s3://amzn-s3-demo-bucket/prefix/"
TBLPROPERTIES (
 "projection.enabled" = "true",
 "projection.day.type" = "date",
 "projection.day.format" = "yyyy-MM-dd",
 "projection.day.range" = "2021-01-01,NOW",
 "projection.day.interval" = "1",
 "projection.day.interval.unit" = "DAYS",
 "projection.customer_id.type" = "injected",
 "storage.location.template" = "s3://amzn-s3-demo-bucket/prefix/${day}/${customer_id}/"
)
```

Cuando se consulta una tabla que tiene una clave de partición de tipo `injected`, la consulta debe incluir un valor para esa clave de partición. Una consulta para la tabla `my_ingested_data3` podría verse así:

```
SELECT *
FROM my_ingested_data3
WHERE day BETWEEN '2021-11-01' AND '2021-11-30'
AND customer_id = 'customer-1234'
```

## Uso del tipo DATE para la clave de partición diaria
<a name="partition-projection-kinesis-firehose-example-iso-formatted-dates"></a>

Ya que los valores de la clave de partición `day` tienen formato ISO, también puede usar el tipo `DATE` para la clave de partición del día en lugar de `STRING`, como en el siguiente ejemplo:

```
PARTITIONED BY (day DATE, customer_id STRING)
```

Cuando se consulta, esta estrategia permite usar las funciones de fecha en la clave de partición sin analizar ni iniciar, como en el siguiente ejemplo:

```
SELECT *
FROM my_ingested_data3
WHERE day > CURRENT_DATE - INTERVAL '7' DAY
AND customer_id = 'customer-1234'
```

**nota**  
Al especificar una clave de partición del tipo `DATE`, se supone que ha utilizado la característica de [prefijo personalizado](https://docs.aws.amazon.com/firehose/latest/dev/s3-prefixes.html) para crear claves de Amazon S3 con fechas con formato ISO. Si utiliza el formato predeterminado de Firehose de `yyyy/MM/dd/HH`, debe especificar la clave de partición como tipo `string` aunque la propiedad de la tabla correspondiente sea de tipo `date`, como en el siguiente ejemplo:  

```
PARTITIONED BY ( 
  `mydate` string)
TBLPROPERTIES (
  'projection.enabled'='true', 
   ...
  'projection.mydate.type'='date',
  'storage.location.template'='s3://amzn-s3-demo-bucket/prefix/${mydate}')
```