

For similar capabilities to Amazon Timestream for LiveAnalytics, consider Amazon Timestream for InfluxDB. It offers simplified data ingestion and single-digit millisecond query response times for real-time analytics. Learn more [here](https://docs.aws.amazon.com//timestream/latest/developerguide/timestream-for-influxdb.html).

# What is Amazon Timestream for LiveAnalytics?
<a name="what-is-timestream"></a>

 Amazon Timestream for LiveAnalytics is a fast, scalable, fully managed, purpose-built time series database that makes it easy to store and analyze trillions of time series data points per day. Timestream for LiveAnalytics saves you time and cost in managing the lifecycle of time series data by keeping recent data in memory and moving historical data to a cost optimized storage tier based upon user defined policies. Timestream for LiveAnalytics's purpose-built query engine lets you access and analyze recent and historical data together, without having to specify its location. Amazon Timestream for LiveAnalytics has built-in time series analytics functions, helping you identify trends and patterns in your data in near real-time. Timestream for LiveAnalytics is serverless and automatically scales up or down to adjust capacity and performance. Because you don't need to manage the underlying infrastructure, you can focus on optimizing and building your applications.

 Timestream for LiveAnalytics also integrates with commonly used services for data collection, visualization, and machine learning. You can send data to Amazon Timestream for LiveAnalytics using AWS IoT Core, Amazon Kinesis, Amazon MSK, and open source Telegraf. You can visualize data using Quick, Grafana, and business intelligence tools through JDBC. You can also use Amazon SageMaker AI with Timestream for LiveAnalytics for machine learning. 

## Timestream for LiveAnalytics key benefits
<a name="what-is.features"></a>

 The key benefits of Amazon Timestream for LiveAnalytics are: 
+  *Serverless with auto-scaling -* With Amazon Timestream for LiveAnalytics, there are no servers to manage and no capacity to provision. As the needs of your application change, Timestream for LiveAnalytics automatically scales to adjust capacity. 
+  *Data lifecycle management -* Amazon Timestream for LiveAnalytics simplifies the complex process of data lifecycle management. It offers storage tiering, with a memory store for recent data and a magnetic store for historical data. Amazon Timestream automates the transfer of data from the memory store to the magnetic store based upon user configurable policies. 
+  *Simplified data access -* With Amazon Timestream for LiveAnalytics, you no longer need to use disparate tools to access recent and historical data. Amazon Timestream for LiveAnalytics's purpose-built query engine transparently accesses and combines data across storage tiers without you having to specify the data location. 
+  *Purpose-built for time series -* You can quickly analyze time series data using SQL, with built-in time series functions for smoothing, approximation, and interpolation. Timestream for LiveAnalytics also supports advanced aggregates, window functions, and complex data types such as arrays and rows. 
+  *Always encrypted -* Amazon Timestream for LiveAnalytics ensures that your time series data is always encrypted, whether at rest or in transit. Amazon Timestream for LiveAnalytics also enables you to specify an AWS KMS customer managed key (CMK) for encrypting data in the magnetic store. 
+  *High availability -* Amazon Timestream ensures high availability of your write and read requests by automatically replicating data and allocating resources across at least 3 different Availability Zones within a single AWS Region. For more information, see the [Timestream Service Level Agreement](https://aws.amazon.com/timestream/sla/). 
+  *Durability -* Amazon Timestream ensures durability of your data by automatically replicating your memory and magnetic store data across different Availability Zones within a single AWS Region. All of your data is written to disk before acknowledging your write request as complete. 

## Timestream for LiveAnalytics use cases
<a name="what-is.use-cases"></a>

 Examples of a growing list of use cases for Timestream for LiveAnalytics include: 
+ Monitoring metrics to improve the performance and availability of your applications.
+ Storage and analysis of industrial telemetry to streamline equipment management and maintenance.
+ Tracking user interaction with an application over time.
+ Storage and analysis of IoT sensor data.

## Getting started with Timestream for LiveAnalytics
<a name="what-is.getting-started"></a>

We recommend that you begin by reading the following sections:
+ **[Tutorial](getting-started.db-w-sample-data.md) -** To create a database populated with sample data sets and run sample queries.
+ **[Amazon Timestream for LiveAnalytics concepts](concepts.md) -** To learn essential Timestream for LiveAnalytics concepts.
+ **[Accessing Timestream for LiveAnalytics](accessing.md) -** To learn how to access Timestream for LiveAnalytics using the console, AWS CLI, or API.
+ **[QuotasDefault quotas](ts-limits.md) -** To learn about quotas on the number of Timestream for LiveAnalytics components that you can provision.

To learn how to quickly begin developing applications for Timestream for LiveAnalytics, see the following:
+ [Using the AWS SDKs](getting-started-sdks.md)
+ [Query language reference](reference.md)

# Amazon Timestream for LiveAnalytics availability change
<a name="AmazonTimestreamForLiveAnalytics-availability-change"></a>

After careful consideration, we have made the decision to close new customer access to Amazon Timestream for LiveAnalytics, effective 6/20/25. This change will not impact customer workloads running with Amazon Timestream for LiveAnalytics. Existing customers with an active payer account currently using the service may continue to add new users and linked accounts under that payer account. AWS continues to invest in security, availability, and performance improvements for Amazon Timestream for LiveAnalytics. We recommend that new customers evaluate [Amazon Timestream for InfluxDB](https://docs.aws.amazon.com//timestream/latest/developerguide/timestream-for-influxdb.html) as an alternative due to its similar functionality.

**Topics**
+ [Amazon Timestream for LiveAnalytics availability change](timestream-availability-update.md)
+ [Migration Guide](migration-guide.md)

# Amazon Timestream for LiveAnalytics availability change
<a name="timestream-availability-update"></a>

Since time-series applications have unique requirements and characteristics, we offer a broad framework to help you evaluate various alternatives before diving into specific implementation details. This high-level guidance serves as a foundation for your decision-making process, with more detailed steps and practical implementations to be covered in subsequent sections.

## Alternative services evaluation
<a name="alternative-services"></a>

**Use-case fits into Amazon Timestream for InfluxDB**  
We recommend [Timestream for InfluxDB](https://docs.aws.amazon.com//timestream/latest/developerguide/timestream-for-influxdb.html), if your Timestream for LiveAnalytics table has less than 10 million cardinality ([series keys](https://docs.influxdata.com/influxdb/v2/reference/key-concepts/data-elements/#series)), meaning the unique combinations of [Amazon Timestream for LiveAnalytics concepts](concepts.md) or if you can reduce your table's cardinality under 10 million. Timestream for InfluxDB gives you access to the capabilities of the open source version of InfluxDB. Choosing this path provides existing time-series functionality such as time-series analytics functions provided by [Flux](https://docs.influxdata.com/influxdb/v2/query-data/flux/), tasks (equivalent to [Scheduled queries](scheduled-query.md)) and other similar functions offered by Timestream for LiveAnalytics. Timestream for InfluxDB also provides [InfluxQL](https://docs.influxdata.com/influxdb/v2/query-data/influxql/) (an SQL-like query language) to interact with InfluxDB for querying and analyzing your time-series data.

**Prefer using SQL instead of InfluxQL**  
We recommend implementing Amazon Aurora or RDS PostgreSQL. These databases offer full SQL functionality while providing effective [time-series data management](https://docs.aws.amazon.com//AmazonRDS/latest/UserGuide/PostgreSQL_Partitions.html) capabilities. Time-series analytics can either be implemented using the built-in database functions where available, or managed at the application layer.

**Require high-scale data ingestion (exceeding 1 million records per second)**  
We recommend using Amazon DynamoDB or other AWS [NoSQL](https://aws.amazon.com/nosql/) databases. These databases can be selected based on your specific application needs. Time-series analytics can either be implemented using the built-in database functions where available, or managed at the application layer.

Before beginning your data migration to the chosen alternate AWS service, it is crucial to assess several key factors that will significantly influence your migration strategy and its ultimate success. These evaluations will help shape your approach, identify potential challenges, and ensure a smoother transition during the migration process.

**Data selection and retention considerations**

Assess your data migration scope by defining exact retention requirements. Consider whether you need to migrate the complete historical dataset, recent data only (such as the last 30, 60, or 90 days), or specific time-series data segments. This decision should be guided by three key factors: regulatory compliance requirements, analytical needs of your business, and practical considerations around migration complexity and costs.

**Query pattern compatibility analysis**

Query compatibility between your source (Timestream for LiveAnalytics) and target service requires thorough evaluation, as time-series databases handle query languages and features differently. Conduct comprehensive testing to identify syntax differences, functional gaps, and performance variations between systems. Test all business-critical queries or if possible all queries that your applications rely on to ensure they will function correctly after migration and are performant.

**Data transformation planning**

Before migrating, pay close attention to schema mapping to ensure proper data alignment and structural consistency between source and target systems, and accurate data type conversions specifically tailored for time-series data. These components work together to ensure data quality, optimize performance, and maintain functionality across different system architectures. In addition, consider any specialized indexing patterns and system-specific optimizations to guarantee efficient data access and retrieval.

**Continuity and downtime management**

Since data migration inherently causes operational disruption, developing a comprehensive switchover strategy is crucial for success. Few best practices to consider in the migration plan to minimize downtime are:
+ Implement temporary parallel processing systems where possible to maintain business continuity.
+ Schedule migrations during low-traffic periods such as weekends or overnight hours.
+ Establish well-tested rollback procedures for quick recovery in case of unexpected issues.

# Migration Guide
<a name="migration-guide"></a>

This guide presents two approaches for migrating time-series data from Amazon Timestream for LiveAnalytics to Timestream for InfluxDB, and to [Aurora](https://docs.aws.amazon.com//AmazonRDS/latest/AuroraUserGuide/Aurora.AuroraPostgreSQL.html) or [RDS PostgreSQL](https://docs.aws.amazon.com//AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html) with a intermediate layer for [Amazon S3](https://aws.amazon.com/s3/). For migrations to other database services, we recommend consulting the specific documentation for importing data from S3 into your chosen service.

In this guide, we walk through following steps:

1. Export your data from Timestream for LiveAnalytics to Amazon S3.

1. Ingesting data to Timestream for InfluxDB.

1. Ingestion data to PostgreSQL.

**Topics**
+ [Exporting Timestream data to Amazon S3](export-timestream-data.md)
+ [Timestream for InfluxDB as a Target](timestream-influxdb-target.md)
+ [Aurora/RDS Postgres as a target](aurora-postgres-target.md)

# Exporting Timestream data to Amazon S3
<a name="export-timestream-data"></a>

Irrespective of the target service for migration, we recommend following the below best practices for exporting your Timestream for LiveAnalytics data to Amazon S3, creating a durable intermediate storage layer that serves as the foundation for subsequent database-specific ingestion.

To reliably export data from Timestream for LiveAnalytics tables to Amazon S3, we recommend using [Timestream for LiveAnalytics export tool](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/liveanalytics_migration_scripts/unload/README.md), which uses the Timestream [UNLOAD](https://docs.aws.amazon.com//timestream/latest/developerguide/supported-sql-constructs.UNLOAD.html) feature — designed for large-scale data exports.

**Timestream for LiveAnalytics export tool**

*Time-based chunking strategy*

Time-based chunking is essential when migrating large volumes of time-series data. This approach breaks down the export process into manageable units that can be independently processed and re-tried on failures, significantly reducing migration risks. It creates checkpoints for easier progress tracking and adds the ability to resume after interruptions. For organizations with continuous data ingestion, this allows newer data to be exported in separate time chunks, enabling better coordination between ongoing operations and migration. The tool uses day-based chunking, storing each day's data with S3 bucket prefix for efficient management. Additionally, chunking can be based on hour, day, month, or year.

*Monitoring migration*

The tool provides an option to capture the migration statistics in a DynamoDB table, tracking metrics such as configurations used, records exported, and other data points for validating the completeness of your migration. We recommend monitoring these metrics closely during your migration and validation. You can also use the logging provided within your orchestration script, capturing execution timestamps, chunk boundaries, and any error conditions encountered. The tool also provides SNS notification if you want to integrate your downstream system to take action on failures.

## Recommendations and best practices
<a name="recommendations-best-practices"></a>

The Timestream for LiveAnalytics export tool provides a flexible and robust solution for exporting data to S3 with various configuration options tailored to your target system requirements. If your target is Timestream for InfluxDB, use [Parquet](https://parquet.apache.org/docs/overview/) format without compression to ensure compatibility with ingestion scripts. For optimal tracking and monitoring, enable DynamoDB logging and configure SNS notifications to receive alerts about export failures or completions.

The tool leverages the Timestream for LiveAnalytics [UNLOAD](https://docs.aws.amazon.com//timestream/latest/developerguide/supported-sql-constructs.UNLOAD.html) feature while overcoming its [partition for query limitations](https://docs.aws.amazon.com//timestream/latest/developerguide/export-unload-limits.html) by automatically exporting data in batches based on your specified time range. You can customize data partitioning by hour, day, month, or year, day being the default. Each partition must remain under approximately 350 GB to avoid memory-related errors, such as query computation exceeding maximum available memory. For example, if your yearly data exceeds 350 GB, consider using monthly partitions or even more granular options like daily or hourly partitioning. If you choose hourly and still get a "The query computation exceeds maximum available memory" error, you can reduce the [number of partitions](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/liveanalytics_migration_scripts/unload/README.md#optional-parameters), making sure your exports are successful.

The tool offers flexibility in the scope of export, allowing you to export a single table, an entire database, or all databases in your account. For more specialized requirements, such as exporting multiple specific databases, you can build a custom wrapper around this automation. Additionally, you can choose to export the most recent data first by enabling the reverse chronological order option. When restarting after failures, you can either continue with the same migration tag to keep all files under the same S3 prefix or omit the tag to create files under a new prefix. As the tool exports the data in batches, if you encounter failures we recommend starting from the failed batch rather than restarting from the original start time. If you don't specify an end timestamp, the tool automatically uses the current timestamp (UTC) to ensure consistent exports and validation.

## Basic commands
<a name="basic-commands"></a>

**Example : Export a table with DynamoDB logging enabled**  

```
python3.9 unload.py \
    --export-table \
    --database Demo \
    --table Demo \
    --start-time '2020-03-26 17:24:38' \
    --enable-dynamodb_logger true
```

**Example : Export entire database**  

```
python3.9 unload.py \
    --export-database \
    --database Demo \
    --start-time '2020-03-26 17:24:38'
```

**Example : Export all databases**  

```
python3.9 unload.py \
    --export-all_databases \
    --start-time '2020-03-26 17:24:38'
```

**Example : Advanced export with more options**  

```
python unload.py \
    --export-table \
    --database MyDB \
    --table MyTable \
    --start-time '2024-05-14 00:00:00' \
    --end-time '2025-05-14 00:00:00' \
    --partition month \
    --export-format PARQUET \
    --compression GZIP \
    --region us-east-1 \
    --s3-uri s3://my-bucket \
    --enable-dynamodb_logger \
    --sns-topic_arn arn:aws:sns:region:account-id:topic-name
```

For more information, see the unload script's [README.](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/liveanalytics_migration_scripts/unload/README.md)

# Timestream for InfluxDB as a Target
<a name="timestream-influxdb-target"></a>

Amazon Timestream for InfluxDB is a managed time-series database service on AWS that uses open-source InfluxDB APIs for real-time applications. It offers easy setup, operation, and scaling, delivering queries with single-digit millisecond response times.

The first step for determining whether Timestream for InfluxDB is an appropriate migration target for your use-case is determining the cardinality of your Timestream for LiveAnalytics table. We have developed a [script](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/liveanalytics_migration_scripts/cardinality/README.md) that calculates table cardinality in Timestream for LiveAnalytics. This calculation serves two purposes:

1. Checks if the cardinality is under 10 million, which will help determine whether Timestream for InfluxDB can handle your use-case.

1. Helps you decide which [Timestream for InfluxDB Instance type](timestream-for-influxdb.md#timestream-for-influx-dbi-classtypes) to use.

[Cardinality](https://docs.influxdata.com/influxdb/v2/reference/glossary/#series-cardinality) in InfluxDB is the number of unique [measurements](https://docs.influxdata.com/influxdb/v2/reference/syntax/line-protocol/#measurement), [tags](https://docs.influxdata.com/influxdb/v2/reference/syntax/line-protocol/#tag-set), and [field key](https://docs.influxdata.com/influxdb/v2/reference/syntax/line-protocol/#field-set) combinations in an InfluxDB [bucket](https://docs.influxdata.com/influxdb/v2/admin/buckets/). Refer to [Timestream for InfluxDB's documentation on cardinality management](timestream-for-influxdb.md#timestream-for-influx-getting-started-security-best-practices) to understand how exceeding recommended limits can degrade query performance and increase memory consumption. Benchmark your anticipated query patterns against representative data samples before finalizing your instance selection to ensure your queries remain performant post-migration. Pay attention to memory-intensive aggregation queries that might behave differently than in Timestream for LiveAnalytics. When migrating from Timestream for LiveAnalytics, carefully select your InfluxDB instance specifications based on your dataset's cardinality as this directly impacts performance and resource requirement. We recommend considering other destinations if your data cardinality is more than 10 million.

**Cardinality calculation script overview**

The cardinality calculation script calculates the cardinality of a Timestream for LiveAnalytics table. If the cardinality is under 10 million, the script recommends a Timestream for InfluxDB instance type. Using the default schema mapping, cardinality is calculated by computing the total unique combinations of dimensions and measure name. Choosing the right [line protocol tags](https://docs.influxdata.com/influxdb/v2/reference/syntax/line-protocol/#elements-of-line-protocol) (equivalent to dimensions in Timestream for LiveAnalytics) helps you automatically [index](https://docs.influxdata.com/influxdb/v2/reference/key-concepts/data-elements/#tag-value) your data and filter your data efficiently using tags. The script also provides the option to exclude specific dimensions when calculating cardinality. If applicable to your case that is, if you are not using certain dimensions for filtering data in SQL queries (specifically not using them as predicates) then you can exclude these dimensions from the cardinality calculation. Later, you can ingest them as fields (equivalent to measures in Timestream for LiveAnalytics) in the next steps of migration.

*Prerequisites and installation*

See the Prerequisites section and installation in the [cardinality script's README](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/liveanalytics_migration_scripts/cardinality/README.md).

**Basic usage**

To determine the cardinality of a table, example\$1table, in the database example\$1database the script can be used in the following way:

**Example**  

```
python3 cardinality.py \
    --table-name example_table \
    --database-name example_database
```

This produces the following output:

```
Cardinality of "example_database"."example_table": 160
Your recommended Timestream for InfluxDB type is: db.influx.medium
```

**Recommendations**

The script automatically scans the entire table to calculate cardinality while offering time filter options for optimal query execution. We suggest implementing time filters when your data involves consistent dimensions and when analyzing distinct dimension variations across the entire table yields similar results to analyzing specific time ranges. This approach ensures efficient and performant query execution.

For more information, see the [cardinality script's README](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/liveanalytics_migration_scripts/cardinality/README.md).

# Ingesting data from Amazon S3 to Timestream for InfluxDB automation
<a name="data-ingestion-from-s3"></a>

After the Timestream for LiveAnalytics export tool completes the unload process, the next step in the automation process begins. This automation uses [InfluxDB's import tools](https://docs.influxdata.com/influxdb/v2/write-data/) to transfer the data into its specialized time-series structure. The process transforms Timestream's data model to match InfluxDB' s concepts of measurements, tags, and fields. Finally, it loads the data efficiently using [InfluxDB's line protocol](https://docs.influxdata.com/influxdb/v2/reference/syntax/line-protocol/).

The workflow for completing a migration is separated into four stages:

1. Unload data using Timestream for LiveAnalytics export tool.

1. [Data transformation](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/liveanalytics_migration_scripts/targets/timestream_for_influxdb/transform/README.md): Converting Timestream for LiveAnalytics data into InfluxDB line protocol format (Based on the schema defined after the cardinality assessment) using [Amazon Athena](https://docs.aws.amazon.com//athena/latest/ug/when-should-i-use-ate.html).

1. [Data ingestion](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/liveanalytics_migration_scripts/targets/timestream_for_influxdb/ingestion/README.md): Ingest the line protocol dataset to your Timestream for InfluxDB instance.

1. [Validation](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/liveanalytics_migration_scripts/targets/timestream_for_influxdb/validation/README.md): Optionally, you can validate that every line protocol point has been ingested (Requires `--add-validation-field true` during data transformation step).

**Data Transformation **

For data transformation, we developed a script to convert Timestream for LiveAnalytics exported data parquet format into InfluxDB's Line Protocol format using Amazon Athena. Amazon Athena provides a serverless query service and a cost-effective way to transform large volumes of time-series data without requiring dedicated compute resources.

The script does the following:
+ Loads exported Timestream for LiveAnalytics data from an Amazon S3 bucket into an Amazon Athena table.
+ Performs data mapping and transformation from the data stored in the Athena table into line protocol and stores it in the S3 bucket.

**Data Mapping**

The following table shows how Timestream for LiveAnalytics data is mapped to line protocol data.


| Timestream for LiveAnalytics Concept | Line Protocol Concept | 
| --- | --- | 
|  [Table Name](https://docs.aws.amazon.com//timestream/latest/developerguide/API_Table.html)  |  [Measurement](https://docs.influxdata.com/influxdb/v2/reference/syntax/line-protocol/#measurement)  | 
|  [Dimensions](https://docs.aws.amazon.com//timestream/latest/developerguide/API_Dimension.html)  |  [Tags](https://docs.influxdata.com/influxdb/v2/reference/syntax/line-protocol/#tag-set)  | 
|  [Measure name](https://docs.aws.amazon.com//timestream/latest/developerguide/data-modeling.html#data-modeling-measurenamemulti)  |  Tag (Optional)  | 
|  [Measures](https://docs.aws.amazon.com//timestream/latest/developerguide/API_MeasureValue.html)  |  [Fields](https://docs.influxdata.com/influxdb/v2/reference/syntax/line-protocol/#field-set)  | 
|  [Time](https://docs.aws.amazon.com///timestream/latest/developerguide/writes.html#writes.data-types)  |  [Timestamp](https://docs.influxdata.com/influxdb/v2/reference/syntax/line-protocol/#timestamp)  | 

**Prerequisites and Installation**

See the Prerequisites and Installation sections in the [transformation script’s README](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/liveanalytics_migration_scripts/targets/timestream_for_influxdb/transform/README.md#prerequisites).

**Usage**

To transform data stored in the bucket example\$1s3\$1bucket from the Timestream for LiveAnalytics table example\$1table in example\$1database, run the following command:

```
python3 transform.py \
        --database-name example_database \
        --tables example_table \
        --s3-bucket-path example_s3_bucket \
        --add-validation-field false
```

After the script is completed, 
+ In Athena, the table example\$1database\$1example\$1table will be created, containing Timestream for LiveAnalytics data.
+ In Athena, the table lp\$1example\$1database\$1example\$1table will be created, containing Timestream for LiveAnalytics data transformed to line protocol points.
+ In the S3 bucket example\$1s3\$1bucket, within the path ` example_database/example_table/unload-<%Y-%m-%d-%H:%M:%S>/line-protocol-output`, line protocol data will be stored.

**Recommendations**

Refer to the [transformation script’s README](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/liveanalytics_migration_scripts/targets/timestream_for_influxdb/transform/README.md#prerequisites) for more details on the latest usage of the script and outputs are required for later steps of the migration, such as validation. If you excluded dimensions in order to improve cardinality, adjust the schema to reduce cardinality by using the `--dimensions-to-fields` argument to change particular dimensions to fields. 

*Adding a Field for Validation*

For information on how to add a field for validation, see the [Adding a Field for Validation](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/liveanalytics_migration_scripts/targets/timestream_for_influxdb/transform/README.md#adding-a-field-for-validation) section in the transformation script’s README. 

## Data ingestion into Timestream for InfluxDB
<a name="data-ingestion-influxdb"></a>

The InfluxDB ingestion script ingests compressed line protocol datasets to Timestream for InfluxDB. A directory containing gzip compressed line protocol files is passed in as a command line argument along with the ingestion destination InfluxDB bucket. This script was designed to ingest multiple files at a time using multi-processing to utilize the resources with InfluxDB and the machine executing the script.

The script does following:
+ Extracts zipped files and ingests them into InfluxDB.
+ Implements retry mechanisms and error handling.
+ Tracks successful and failed ingestions for resuming.
+ Optimizes I/O operations when reading from line protocol dataset.

**Prerequisites and installation**

See the Prerequisites and Installation section in the ingestion script's [README](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/liveanalytics_migration_scripts/README.md#installation) in GitHub.

**Data preparation**

The zipped line protocol files required for ingestion are generated by the data transform scripts. Follow these steps to prepare your data:

1. Set up an EC2 instance with sufficient storage to hold the transformed dataset.

1. Sync the transformed data from the S3 bucket to your local directory:

   ```
   aws s3 sync \
       s3://your-bucket-name/path/to/transformed/data \
       ./data_directory
   ```

1. Make sure you have read access to all files in the data directory.

1. Run the following ingestion script to ingest data into Timestream for InfluxDB.

**Usage**

```
python influxdb_ingestion.py <bucket_name> <data_directory> [options]
```

**Basic usage**

```
python influxdb_ingestion.py my_bucket ./data_files
```

**Ingestion rates**

We have run some tests for Ingestion rates. Ingestion tests using a C5N.9XL EC2 instance executing the ingestion script with 10 Workers, and ingesting \$1500 GB line protocol to 8XL Timestream for InfluxDB instances:
+ 3K IOPS 15.86 GB/hour.
+ 12K IOPS 70.34 GB/hour.
+ 16K IOPS 71.28 GB/hour.

**Recommendations**
+ Use an EC2 instance with sufficient CPU cores to handle parallel processing.
+ Ensure the instance has enough storage to hold the entire transformed dataset with additional room for extraction.
  + The number of files extracted at one time is equal to the number of workers configured during script execution.
+ Position the EC2 instance in the same region and AZ (if possible) as your InfluxDB instance to minimize latency.
+ Consider using instance types optimized for network operations, for example C5N.
+ If high ingestion rates are required, at least 12K IOPS is recommended for the Timestream for InfluxDB instance. Additional optimizations can be gained by increasing the worker count for the script dependent on Timestream for InfluxDB instance size.

For more information, see the ingestion script's [README](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/liveanalytics_migration_scripts/README.md#installation).

# Migration validation script
<a name="migration-validation"></a>

The validation script compares logical row/point counts between a source table (Amazon Timestream or Amazon Athena) and an InfluxDB bucket measurement, with optional time-range specifications. This tool helps ensure data integrity during migration processes by running parallel queries against both systems and comparing the results.

The validation script supports queries against either the exported dataset in Athena or the original Timestream database/table. Be aware that querying Timestream directly may lead to inaccurate comparisons if data has been written since the export. The validation script can be run anytime after ingestion has begun. It first polls InfluxDB's metrics endpoint to wait for the [WAL (Write-Ahead Log)](https://docs.influxdata.com/influxdb/v2/reference/internals/storage-engine/#write-ahead-log-wal) to flush completely, ensuring all data processing, including post-ingestion file merging and de-duplication, is finished. The script then executes count-only queries over identical time windows, comparing results to highlight matches or mismatches. It supports optional schema/tag filtering for transformed schemas where dimensions are used as fields, and produces human-readable timing and result summaries to facilitate validation of the migration process.

*Prerequisites and installation*

See the prerequisites and installation section in the [Migration Validation Script README](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/liveanalytics_migration_scripts/README.md#installation).

*Usage*

```
python validator.py [options]
```

All settings can be supplied as CLI flags or environment variables. See the example.env file within the repository.

For troubleshooting and recommendations see the [Migration Validation Script README](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/liveanalytics_migration_scripts/README.md#installation).

*Cleanup*

After finishing a migration, following resources/artifacts will be created:
+ An Athena table, containing Timestream for LiveAnalytics data. By default, this is <Timestream database name>\$1<Timestream table name> in the default Athena database.
+ An Athena table, containing transformed line protocol data. By default, this is lp\$1<Athena table name> in the default Athena database.
+ Line protocol data within your S3 bucket, with the path <Timestream database name>/<Timestream table name>/unload-<%Y-%m-%d-%H:%M:%S>/line-protocol-output.
+ Unloaded data that was created as part of Timestream for LiveAnalytics export tool.
+ Downloaded data and logs on your EC2 instance.
+ DynamoDB table if used for logging as part of Timestream for LiveAnalytics export tool.

*Cleaning up Athena resources*

To delete any Athena table, run the following [AWS CLI ](https://aws.amazon.com/cli/)command, replacing <Athena table name> with the name of the table that you want to delete and <Athena database name> with the name of the Athena database that the table resides in:

```
aws glue delete-table \
    --database-name <Athena database name> \
    --name <Athena table name>
```

*Cleaning up S3 resources*

To delete line protocol data within your S3 bucket, run the following AWS CLI command, replacing <S3 bucket name> with the name of your S3 bucket, <Timestream database name> with the name of your Timestream for LiveAnalytics database, <Timestream table name> with the name of your Timestream for LiveAnalytics table, and <timestamp> with the timestamp that forms the unload-<%Y-%m-%d-%H:%M:%S> path in your S3 bucket:

```
aws s3 rm \
    s3://<S3 bucket name>/<Timestream database name>/<Timestream table name>/unload-<timestamp>/line-protocol-output \
    --recursive
```

To delete an S3 bucket, run the following command, replacing <S3 bucket name> with the name of your S3 bucket:

```
aws s3 delete-bucket --bucket <S3 bucket name>
```

*Cleaning up DynamoDB resources*

To delete a DynamoDB table, run the following command, replacing <table name> with the name of the DynamoDB table that you want to delete:

```
aws dynamodb delete-table --table-name <table name>
```

# Aurora/RDS Postgres as a target
<a name="aurora-postgres-target"></a>

This section explains ingesting the S3 staged time-series data into Amazon RDS/Aurora PostgreSQL. The ingestion process will primarily focus on the CSV files generated from Timestream's export tool to ingest into Postgres. We recommend designing the PostgreSQL schema and table with proper indexing strategies for time-based queries. Use any ETL processes to transform Timestream's specialized structures into relational tables optimized for your specific requirements. When migrating Timestream data to a relational database, structure your schema with a timestamp column as the primary time index, measurement identifier columns derived from Timestream's measure\$1name, and dimension columns from Timestream's dimensions and your actual measures. Create strategic indexes on time ranges and frequently queried dimension combinations to optimize performance during data transformation and loading process. When migrating time-series data to PostgreSQL, proper instance sizing is critical for maintaining query performance at scale. Consider your expected data volume, query complexity, and concurrency requirements when selecting an instance class, with particular attention to memory allocation for time-series aggregation workloads. For datasets exceeding tens of millions of rows, leverage [PostgreSQL's native partitioning capabilities](https://docs.aws.amazon.com//AmazonRDS/latest/UserGuide/PostgreSQL_Partitions.html) and advanced indexing strategies to optimize for time-series access patterns.

We recommend performing functional and performance testing to choose the right instance and [tuning your PostgreSQL database](https://docs.aws.amazon.com//AmazonRDS/latest/UserGuide/PostgreSQL.Tuning_proactive_insights.html) to address any performance bottlenecks. Performing rigorous data integrity checks through sample query comparisons between your source Timestream database and target system is critical to ensure migration success and maintain query correctness. By executing identical queries against both systems and comparing results — including record counts, aggregations, and outlier values — you can identify any discrepancies that might indicate transformation errors, data loss, or semantic differences in query interpretation. This verification process validates that your data maintains its analytical value post-migration, builds confidence in the new system among stakeholders who rely on these insights, helps identify any necessary query adjustments to accommodate syntax or functional differences between platforms, and establishes a quantifiable baseline for determining when the migration can be considered complete and successful. Without these systematic checks, subtle data inconsistencies might remain undetected, potentially leading to incorrect business decisions or undermining confidence in the entire migration project.

## Ingestion
<a name="postgres-ingestion"></a>

We recommend using [AWSDatabase Migration Service (DMS)](https://docs.aws.amazon.com//dms/latest/userguide/Welcome.html) with [source as S3](https://docs.aws.amazon.com//dms/latest/userguide/CHAP_Source.S3.html) (both CSV and Parquet are supported) with [PostgreSQL](https://docs.aws.amazon.com//dms/latest/userguide/CHAP_Target.PostgreSQL.html) as the target. For scenarios where AWS DMS may not be suitable for your specific requirements, we provide a supplementary Python-based utility ([PostgreSQL CSV Ingestion Tool](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/liveanalytics_migration_scripts/targets/rds_for_postgresql/README.md)) for migrating CSV data from S3 to PostgreSQL.

### Overview of PostgreSQL CSV ingestion tool
<a name="postgres-tool-overview"></a>

The PostgreSQL CSV Ingestion Tool, is a high-performance utility designed to efficiently load CSV files into PostgreSQL databases. It leverages multi-threading and connection pooling to process multiple files in parallel, significantly reducing data loading time. We recommend to running this script using an EC2 instance. Consider using instance types optimized for network operations, such as C5N.

#### Key features
<a name="key-features"></a>
+ Multi-threaded Processing: Loads multiple CSV files simultaneously.
+ Connection Pooling: Efficiently manages database connections.
+ Automatic Column Detection: Dynamically extracts column names from CSV headers.
+ Retry Logic: Handles transient errors with exponential backoff.
+ File Management; Moves processed files to a designated directory so retrying is resuming but not restarting.
+ Comprehensive Logging: Detailed logs for monitoring and troubleshooting.
+ Error Notifications: Optional SNS notifications for failures.
+ Secure Credentials: Retrieves database passwords from AWS Secrets Manager.

*Prerequisites and installation*

See prerequisites and installation in the [PostgreSQL CSV Ingestion Tool Readme](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/liveanalytics_migration_scripts/targets/rds_for_postgresql/README.md) in GitHub.

*Usage*

```
python copy_postgres.py \
    --database 'postgres_testing' \
    --table 'demolarge_restored' \
    --csv-files-dir '/data/csv_files/*partition*/*.csv' \
    --host database-1.cluster-xxxxxxxx.us-east-1.rds.amazonaws.com \
    --secret-arn 'arn:aws:secretsmanager:<region>:<account_id>:secret:rds!cluster-xxxxx-xx-xx-xx-xxxxxxxx-xxxxx' \
    --sns-topic-arn 'arn:aws:sns:<region>:<account_id>:<topic_name>'
```

*Validation*

You can use DynamoDB for exported rows or logs generated by Timestream's export tool and compare against rows ingested from PostgreSQL Ingestion automation logs. You can do select counts against the source and target tables with the consistent export and import time, if the data is being continuously ingested during the migration process the counts will vary so the recommendation is to compare rows exported and rows important from logging.

*Cleanup*
+ Cleanup unloaded data that was created as part of Timestream for LiveAnalytics export tool.
+ Delete downloaded data and logs on EC2 to reclaim the space.
+ Delete DynamoDB table if used for logging as part of Timestream for LiveAnalytics export tool.

# How it works
<a name="how-it-works"></a>

The following sections provide an overview of Amazon Timestream for Live Analytics service components and how they interact.

After you read this introduction, see the [Accessing Timestream for LiveAnalytics](accessing.md) sections to learn how to access Timestream for Live Analytics using the console, AWS CLI, or SDKs.

**Topics**
+ [Amazon Timestream for LiveAnalytics concepts](concepts.md)
+ [Architecture](architecture.md)
+ [Writes](writes.md)
+ [Storage](storage.md)
+ [Queries](queries.md)
+ [Scheduled queries](scheduled-query.md)
+ [Timestream Compute Unit (TCU)](tcu.md)

# Amazon Timestream for LiveAnalytics concepts
<a name="concepts"></a>

 Time series data is a sequence of data points recorded over a time interval. This type of data is used for measuring events that change over time. Examples include the following.
+ Stock prices over time
+ Temperature measurements over time
+ CPU utilization of an EC2 instance over time

 With time series data, each data point consists of a timestamp, one or more attributes, and the event that changes over time. This data can be used to derive insights into the performance and health of an application, detect anomalies, and identify optimization opportunities. For example, DevOps engineers might want to view data that measures changes in infrastructure performance metrics. Manufacturers might want to track IoT sensor data that measures changes in equipment across a facility. Online marketers might want to analyze clickstream data that captures how a user navigates a website over time. Because time series data is generated from multiple sources in extremely high volumes, it needs to be cost-effectively collected in near real time, and therefore requires efficient storage that helps organize and analyze the data. 

 Following are the key concepts of Timestream for LiveAnalytics. 
+ **Time series** - *A sequence of one or more data points (or records) recorded over a time interval. * Examples are the price of a stock over time, the CPU or memory utilization of an EC2 instance over time, and the temperature/pressure reading of an IoT sensor over time.
+ **Record** - *A single data point in a time series.*
+ **Dimension** - *An attribute that describes the meta-data of a time series.* A dimension consists of a dimension name and a dimension value. Consider the following examples: 
  + When considering a stock exchange as a dimension, the dimension name is "stock exchange" and the dimension value is "NYSE"
  + When considering an AWS Region as a dimension, the dimension name is "region" and the dimension value is "us-east-1"
  + For an IoT sensor, the dimension name is "device ID" and the dimension value is "12345"
+ **Measure** - *The actual value being measured by the record. * Examples are the stock price, the CPU or memory utilization, and the temperature or humidity reading. Measures consist of measure names and measure values. Consider the following examples: 
  + For a stock price, the measure name is "stock price" and the measure value is the actual stock price at a point in time. 
  + For CPU utilization, the measure name is "CPU utilization" and the measure value is the actual CPU utilization.

  Measures can be modeled in Timestream for LiveAnalytics as multi-measure or single-measure records. For more information, see [Multi-measure records vs. single-measure records](data-modeling.md#data-modeling-multiVsinglerecords).
+ **Timestamp** - *Indicates when a measure was collected for a given record.* Timestream for LiveAnalytics supports timestamps with nanosecond granularity. 
+ **Table** - *A container for a set of related time series.* 
+ **Database** - *A top level container for tables.* 

## A summary of Timestream for LiveAnalytics concepts
<a name="w2aab7c17c12c13"></a>

 A **database** contains 0 or more **tables**. Each **table** contains 0 or more **time series**. Each **time series** consists of a sequence of **records** over a given time interval at a specified **granularity**. Each **time series** can be described using its meta-data or **dimensions**, its data or **measures**, and its **timestamps**. 

![\[Database structure showing tables, time series, and records with sample CPU measure values.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/concepts_simple.png)


# Architecture
<a name="architecture"></a>

Amazon Timestream for Live Analytics has been designed from the ground up to collect, store, and process time series data at scale. Its serverless architecture supports fully decoupled data ingestion, storage, and query processing systems that can scale independently. This design simplifies each subsystem, making it easier to achieve unwavering reliability, eliminate scaling bottlenecks, and reduce the chances of correlated system failures. Each of these factors becomes more important as the system scales. 

**Topics**
+ [Write architecture](#architecture.writes)
+ [Storage architecture](#architecture.storage)
+ [Query architecture](#architecture.queries)
+ [Cellular architecture](#cells)

![\[Timestream architecture diagram showing ingestion, storage, and query layers with AWS SDK interactions.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/ts-architecture.png)


## Write architecture
<a name="architecture.writes"></a>

When writing time-series data, Amazon Timestream for Live Analytics routes writes for a table, partition, to a fault-tolerant memory store instance that processes high throughput data writes. The memory store in turn achieves durability in a separate storage system that replicates the data across three Availability Zones (AZs). Replication is quorum based such that the loss of nodes, or an entire AZ, will not disrupt write availability. In near real-time, other in-memory storage nodes sync to the data in order to serve queries. The reader replica nodes span AZs as well, to ensure high read availability.

Timestream for Live Analytics supports writing data directly into the magnetic store, for applications generating lower throughput late-arriving data. Late-arriving data is data with a timestamp earlier than the current time. Similar to the high throughput writes in the memory store, the data written into the magnetic store is replicated across three AZs and the replication is quorum based.

Whether data is written to the memory or magnetic store, Timestream for Live Analytics automatically indexes and partitions data before writing it to storage. A single Timestream for Live Analytics table may have hundreds, thousands, or even millions of partitions. Individual partitions do not, directly, communicate with each other and do not share any data (shared-nothing architecture). Instead, the partitioning of a table is tracked through a highly available partition tracking and indexing service. This provides another separation of concerns designed specifically to minimize the effect of failures in the system and make correlated failures much less likely.

## Storage architecture
<a name="architecture.storage"></a>

 When data is stored in Timestream for Live Analytics, data is organized in time order as well as across time based on context attributes written with the data. Having a partitioning scheme that divides "space" in addition to time is important for massively scaling a time series system. This is because most time series data is written at or around the current time. As a result, partitioning by time alone does not do a good job of distributing write traffic or allowing for effective pruning of data at query time. This is important for extreme scale time series processing, and it has allowed Timestream for Live Analytics to scale orders of magnitude higher than the other leading systems out there today in serverless fashion. The resulting partitions are referred to as "tiles" because they represent divisions of a two-dimensional space (which are designed to be of a similar size). Timestream for Live Analytics tables start out as a single partition (tile), and then split in the spatial dimension as throughput requires. When tiles reach a certain size, they then split in the time dimension in order to achieve better read parallelism as the data size grows. 

 Timestream for Live Analytics is designed to automatically manage the lifecycle of time series data. Timestream for Live Analytics offers two data stores—an in-memory store and a cost-effective magnetic store. It also supports configuring table-level policies to automatically transfer data across stores. Incoming high throughput data writes land in the memory store where data is optimized for writes, as well as reads performed around current time for powering dashboard and alerting type queries. When the main time frame for writes, alerting, and dashboarding needs has passed, allowing the data to automatically flow from the memory store to the magnetic store to optimize cost. Timestream for Live Analytics allows setting a data retention policy on the memory store for this purpose. Data writes for late-arriving data are directly written into the magnetic store. 

 Once the data is available in the magnetic store (because of expiration of the memory store retention period or because of direct writes into the magnetic store), it is reorganized into a format that is highly optimized for large volume data reads. The magnetic store also has a data retention policy that may be configured if there is a time threshold where the data outlives its usefulness. When the data exceeds the time range defined for the magnetic store retention policy, it is automatically removed. Therefore, with Timestream for Live Analytics, other than some configuration, the data lifecycle management occurs seamlessly behind the scenes. 

## Query architecture
<a name="architecture.queries"></a>

Timestream for Live Analytics queries are expressed in a SQL grammar that has extensions for time series-specific support (time series-specific data types and functions), so the learning curve is easy for developers already familiar with SQL. Queries are then processed by an adaptive, distributed query engine that uses metadata from the tile tracking and indexing service to seamlessly access and combine data across data stores at the time the query is issued. This makes for an experience that resonates well with customers as it collapses many of the Rube Goldberg complexities into a simple and familiar database abstraction. 

 Queries are run by a dedicated fleet of workers where the number of workers enlisted to run a given query is determined by query complexity and data size. Performance for complex queries over large datasets is achieved through massive parallelism, both on the query runtime fleet and the storage fleets of the system. The ability to analyze massive amounts of data quickly and efficiently is one of the greatest strengths of Timestream for Live Analytics. A single query that runs over terabytes or even petabytes of data might have thousands of machines working on it all at the same time. 

## Cellular architecture
<a name="cells"></a>

 To ensure that Timestream for Live Analytics can offer virtually infinite scale for your applications, while simultaneously ensuring 99.99% availability, the system is also designed using a cellular architecture. Rather than scaling the system as a whole, Timestream for Live Analytics segments into multiple smaller copies of itself, referred to as *cells*. This allows cells to be tested at full scale, and prevents a system problem in one cell from affecting activity in any other cells in a given region. While Timestream for Live Analytics is designed to support multiple cells per region, consider the following fictitious scenario, in which there are 2 cells in a region.

![\[Timestream architecture diagram showing ingestion, storage, and query layers for two cellular endpoints.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/ts-cellular-architecture.png)


 In the scenario depicted above, the data ingestion and query requests are first processed by the discovery endpoint for data ingestion and query, respectively. Then, the discovery endpoint identifies the cell containing the customer data, and directs the request to the appropriate ingestion or query endpoint for that cell. When using the SDKs, these endpoint management tasks are transparently handled for you. 

**Note**  
*When using VPC endpoints with Timestream for Live Analytics or directly accessing REST API operations for Timestream for Live Analytics, you will need to interact directly with the cellular endpoints.* For guidance on how to do so, see [VPC Endpoints](VPCEndpoints.md) for instructions on how to set up VPC endpoints, and [Endpoint Discovery Pattern](Using.API.md) for instructions on direct invocation of the REST API operations.

# Writes
<a name="writes"></a>

 You can collect time series data from connected devices, IT systems, and industrial equipment, and write it into Timestream for Live Analytics. Timestream for Live Analytics enables you to write data points from a single time series and/or data points from many series in a single write request when the time series belong to the same table. For your convenience, Timestream for Live Analytics offers you with a flexible schema that auto detects the column names and data types for your Timestream for Live Analytics tables based on the dimension names and the data types of the measure values you specify when invoking writes into the database. You can also write batches of data into Timestream for Live Analytics.

**Note**  
 Timestream for Live Analytics supports eventual consistency semantics for reads. This means that when you query data immediately after writing a batch of data into Timestream for Live Analytics, the query results might not reflect the results of a recently completed write operation. The results may also include some stale data. Similarly, while writing time series data with one or more new dimensions, a query can return a partial subset of columns for a short period of time. If you repeat these query requests after a short time, the results should return the latest data. 

 You can write data using the [AWS SDKs](getting-started-sdks.md), [AWS CLI](Tools.CLI.md), or through [AWS Lambda](Lambda.md), [AWS IoT Core](IOT-Core.md), [Amazon Managed Service for Apache Flink](ApacheFlink.md), [Amazon Kinesis](Kinesis.md), [Amazon MSK](MSK.md), and [Open source Telegraf](Telegraf.md). 

**Topics**
+ [Data types](#writes.data-types)
+ [No upfront schema definition](#writes.no-upfront-schema)
+ [Writing data (inserts and upserts)](#writes.writing-data-inserts-upserts)
+ [Eventual consistency for reads](#writes.eventual-consistency)
+ [Batching writes with WriteRecords API](writes.batching-writes.md)
+ [Batch load](batch-load-how.md)
+ [Choosing between the WriteRecords API operation and batch load](writes.writes-or-batch-load.md)

## Data types
<a name="writes.data-types"></a>

 Timestream for Live Analytics supports the following data types for writes.


| Data type | Description | 
| --- | --- | 
|  BIGINT  |   Represents a 64-bit signed integer.   | 
|  BOOLEAN  |   Represents the two truth values of logic, namely, true, and false.   | 
|  DOUBLE  |   64-bit variable-precision implementing the IEEE Standard 754 for Binary Floating-Point Arithmetic.   There are query language functions for `Infinity` and `NaN` double values which can be used in queries. But you cannot write those values to Timestream.   | 
|  VARCHAR  |   Variable length character data with an optional maximum length. The maximum limit is 2 KB.   | 
|  MULTI  |   Data type for multi-measure records. This data type includes one or more measures of type `BIGINT`, `BOOLEAN`, `DOUBLE`, `VARCHAR`, and `TIMESTAMP`.   | 
|  TIMESTAMP  |   Represents an instance in time using nanosecond precision time in UTC, tracking the time since Unix time. This data type is currently supported only for multi-measure records (i.e. within measure values of type `MULTI`).  `YYYY-MM-DD hh:mm:ss.sssssssss` Writes support timestamps in the range `1970-01-01 00:00:00.000000000` to `2262-04-11 23:47:16.854775807`.  | 

## No upfront schema definition
<a name="writes.no-upfront-schema"></a>

 Before sending data into Amazon Timestream for Live Analytics, you must create a database and a table using the AWS Management Console, Timestream for Live Analytics SDKs, or the Timestream for Live Analytics API operations. For more information, see [Create a database](console_timestream.md#console_timestream.db.using-console) and [Create a table](console_timestream.md#console_timestream.table.using-console). While creating the table, you do not need to define the schema up front. Amazon Timestream for Live Analytics automatically detects the schema based on the measures and dimensions of the data points being sent, so you no longer need to alter your schema offline to adapt it to your rapidly changing time series data. 

## Writing data (inserts and upserts)
<a name="writes.writing-data-inserts-upserts"></a>

 The write operation in Amazon Timestream for Live Analytics enables you to insert and *upsert* data. By default, writes in Amazon Timestream for Live Analytics follow the *first writer wins* semantics, where data is stored as append only and duplicate records are rejected. While the first writer wins semantics satisfies the requirements of many time series applications, there are scenarios where applications need to update existing records in an idempotent manner and/or write data with the last writer wins semantics, where the record with the highest version is stored in the service. To address these scenarios, Amazon Timestream for Live Analytics provides the ability to upsert data. Upsert is an operation that inserts a record into the system when the record does not exist, or updates the record when one exists. When the record is updated, it is updated in an idempotent manner. 

There isn't a record level operation for deletion. But tables and databases can be deleted.

**Writing data into the memory store and the magnetic store**

Amazon Timestream for Live Analytics offers the ability to directly write data into the memory store and the magnetic store. The memory store is optimized for high throughput data writes and the magnetic store is optimized for lower throughput writes of late arrival data.

Late-arriving data is data with a timestamp earlier than the current time and outside the memory store retention period. You must explicitly enable the ability to write late-arriving data into the magnetic store by enabling magnetic store writes for the table. Also, `MagneticStoreRejectedDataLocation` is defined when a table is created. To write to the magnetic store, callers of `WriteRecords` must have `S3:PutObject` permissions to the S3 bucket specified in `MagneticStoreRejectedDataLocation`during table creation. For more information, see [CreateTable](https://docs.aws.amazon.com/timestream/latest/developerguide/API_CreateTable.html), [WriteRecords](https://docs.aws.amazon.com/timestream/latest/developerguide/API_WriteRecords.html), and [PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html).

**Writing data with single-measure records and multi-measure records**

Amazon Timestream for Live Analytics offers the ability to write data using two types of records, namely, single-measure records and multi-measure records.

**Single-measure records**

Single-measure records enable you to send a single measure per record. When data is sent to Timestream for Live Analytics using this format, Timestream for Live Analytics creates one table row per record. This means that if a device emits 4 metrics and each metric is sent as a single-measure record, Timestream for Live Analytics will create 4 rows in the table to store this data, and the device attributes will be repeated for each row. This format is recommended in cases when you want to monitor a single metric from an application or when your application does not emit multiple metrics at the same time.

**Multi-measure records**

With multi-measure records, you can store multiple measures in a single table row, instead of storing one measure per table row. Multi-measure records therefore enable you to migrate your existing data from relational databases to Amazon Timestream for Live Analytics with minimal changes. 

You can also batch more data in a single write request than single-measure records. This increases data write throughput and performance, and also reduces the cost of data writes. This is because batching more data in a write request enables Amazon Timestream for Live Analytics to identify more repeatable data in a single write request (where applicable), and charge only once for repeated data.

**Topics**
+ [Multi-measure records](#writes.writing-data-multi-measure)
+ [Writing data with a timestamp that exists in the past or in the future](#writes.timestamp-past-future)

### Multi-measure records
<a name="writes.writing-data-multi-measure"></a>

With multi-measure records, you can store your time-series data in a more compact format in the memory and magnetic store, which helps lower data storage costs. Also, the compact data storage lends itself to writing simpler queries for data retrieval, improves query performance, and lowers the cost of queries.

Furthermore, multi-measure records also support the TIMESTAMP data type for storing more than one timestamp in a time-series record. TIMESTAMP attributes in a multi-measure record support timestamps in future or past. Multi-measure records therefore help improve performance, cost, and query simplicity—and offer more flexibility for storing different types of correlated measures.

**Benefits**

The following are the benefits of using multi-measure records.
+ **Performance and cost** – Multi-measure records enable you to write multiple time-series measures in a single write request. This increases the write throughput and also reduces the cost of writes. With multi-measure records, you can store data in a more compact manner, which helps lower the data storage costs. The compact data storage of multi-measure records results in less data being processed by queries. This is designed to improve the overall query performance and help lower the query cost.
+ **Query simplicity** – With multi-measure records, you do not need to write complex common table expressions (CTEs) in a query to read multiple measures with the same timestamp. This is because the measures are stored as columns in a single table row. Multi-measure records therefore enable writing simpler queries.
+ **Data modeling flexibility** – You can write future timestamps into Timestream for Live Analytics by using the TIMESTAMP data type and multi-measure records. A multi-measure record can have multiple attributes of TIMESTAMP data type, in addition to the time field in a record. TIMESTAMP attributes, in a multi-measure record, can have timestamps in the future or the past and behave like the time field except that Timestream for Live Analytics does not index on the values of type TIMESTAMP in a multi-measure record.

**Use cases**

You can use multi-measure records for any time-series application that generates more than one measurement from the same device at any given time. The following are some example applications.
+ A video streaming platform that generates hundreds of metrics at a given time.
+ Medical devices that generate measurements such as blood oxygen levels, heart rate, and pulse.
+ Industrial equipment such as oil rigs that generate metrics, temperature, and weather sensors.
+ Other applications that are architected with one or more microservices.

#### Example: Monitoring the performance and health of a video streaming application
<a name="writes.writing-data-multi-measure-example1"></a>

Consider a video streaming application that is running on 200 EC2 instances. You want to use Amazon Timestream for Live Analytics to store and analyze the metrics being emitted from the application, so you can understand the performance and health of your application, quickly identify anomalies, resolve issues, and discover optimization opportunities. 

We will model this scenario with single-measure records and multi-measure records, and then compare/contrast both approaches. For each approach, we make the following assumptions.
+ Each EC2 instance emits four measures (video\$1startup\$1time, rebuffering\$1ratio, video\$1playback\$1failures, and average\$1frame\$1rate) and four dimensions (device\$1id, device\$1type, os\$1version, and region) per second. 
+ You want to store 6 hours of data in the memory store and 6 months of data in the magnetic store.
+ To identify anomalies, you've set up 10 queries that run every minute to identify any unusual activity over the past few minutes. You've also built a dashboard with eight widgets that display the last 6 hours of data, so that you can effectively monitor your application. This dashboard is accessed by five users at any given time and is auto-refreshed every hour.

##### Using single measure records
<a name="writes.writing-data-multi-measure-example1-sm"></a>

**Data modeling**: With single measure records, we will create one record for each of the four measures (video startup time, rebuffering ratio, video playback failures, and average frame rate). Each record will have the four dimensions (device\$1id, device\$1type, os\$1version, and region) and a timestamp. 

**Writes**: When you write data into Amazon Timestream for Live Analytics, the records are constructed as follows.

```
public void writeRecords() {
    System.out.println("Writing records");
    // Specify repeated values for all records
    List<Record> records = new ArrayList<>();
    final long time = System.currentTimeMillis();
 
    List<Dimension> dimensions = new ArrayList<>();
    
    final Dimension device_id = new Dimension().withName("device_id").withValue("12345678");
    final Dimension device_type = new Dimension().withName("device_type").withValue("iPhone 11");
    final Dimension os_version = new Dimension().withName("os_version").withValue("14.8");
    final Dimension region = new Dimension().withName("region").withValue("us-east-1");
 
    dimensions.add(device_id);
    dimensions.add(device_type);
    dimensions.add(os_version);
    dimensions.add(region);
 
    Record videoStartupTime = new Record()
        .withDimensions(dimensions)
        .withMeasureName("video_startup_time")
        .withMeasureValue("200")
        .withMeasureValueType(MeasureValueType.BIGINT)
        .withTime(String.valueOf(time));
    Record rebufferingRatio = new Record()
        .withDimensions(dimensions)
        .withMeasureName("rebuffering_ratio")
        .withMeasureValue("0.5")
        .withMeasureValueType(MeasureValueType.DOUBLE)
        .withTime(String.valueOf(time));
    Record videoPlaybackFailures = new Record()
        .withDimensions(dimensions)
        .withMeasureName("video_playback_failures")
        .withMeasureValue("0")
        .withMeasureValueType(MeasureValueType.BIGINT)
        .withTime(String.valueOf(time));
    Record averageFrameRate = new Record()
        .withDimensions(dimensions)
        .withMeasureName("average_frame_rate")
        .withMeasureValue("0.5")
        .withMeasureValueType(MeasureValueType.DOUBLE)
        .withTime(String.valueOf(time));

    records.add(videoStartupTime);
    records.add(rebufferingRatio); 
    records.add(videoPlaybackFailures);
    records.add(averageFrameRate);
 
    WriteRecordsRequest writeRecordsRequest = new WriteRecordsRequest()
        .withDatabaseName(DATABASE_NAME)
        .withTableName(TABLE_NAME)
        .withRecords(records);
 
    try {
      WriteRecordsResult writeRecordsResult = amazonTimestreamWrite.writeRecords(writeRecordsRequest);
      System.out.println("WriteRecords Status: " + writeRecordsResult.getSdkHttpMetadata().getHttpStatusCode());
    } catch (RejectedRecordsException e) {
      System.out.println("RejectedRecords: " + e);
      for (RejectedRecord rejectedRecord : e.getRejectedRecords()) {
        System.out.println("Rejected Index " + rejectedRecord.getRecordIndex() + ": "
            + rejectedRecord.getReason());
      }
      System.out.println("Other records were written successfully. ");
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }
  }
```

When you store single-measure records, the data is logically represented as follows.


| Time | device\$1id | device\$1type | os\$1version | region | measure\$1name | measure\$1value::bigint | measure\$1value::double | 
| --- | --- | --- | --- | --- | --- | --- | --- | 
|  2021-09-07 21:48:44 .000000000  |  12345678  |  iPhone 11  |  14.8  |  us-east-1  |  video\$1startup\$1time  |  200  |    | 
|  2021-09-07 21:48:44 .000000000  |  12345678  |  iPhone 11  |  14.8  |  us-east-1  |  rebuffering\$1ratio  |    |  0.5  | 
|  2021-09-07 21:48:44 .000000000  |  12345678  |  iPhone 11  |  14.8  |  us-east-1  |  video\$1playback\$1failures  |  0  |    | 
|  2021-09-07 21:48:44 .000000000  |  12345678  |  iPhone 11  |  14.8  |  us-east-1  |  average\$1frame\$1rate  |    |  0.85  | 
|  2021-09-07 21:53:44 .000000000  |  12345678  |  iPhone 11  |  14.8  |  us-east-1  |  video\$1startup\$1time  |  500  |    | 
|  2021-09-07 21:53:44 .000000000  |  12345678  |  iPhone 11  |  14.8  |  us-east-1  |  rebuffering\$1ratio  |    |  1.5  | 
|  2021-09-07 21:53:44 .000000000  |  12345678  |  iPhone 11  |  14.8  |  us-east-1  |  video\$1playback\$1failures  |  10  |    | 
|  2021-09-07 21:53:44 .000000000  |  12345678  |  iPhone 11  |  14.8  |  us-east-1  |  average\$1frame\$1rate  |    |  0.2  | 

**Queries**: You can write a query that retrieves all of the data points with the same timestamp received over the past 15 minutes as follows.

```
with cte_video_startup_time as ( SELECT time, device_id, device_type, os_version, region, measure_value::bigint as video_startup_time FROM table where time >= ago(15m) and measure_name=”video_startup_time”),
cte_rebuffering_ratio as ( SELECT time, device_id, device_type, os_version, region, measure_value::double as rebuffering_ratio FROM table where time >= ago(15m) and measure_name=”rebuffering_ratio”),
cte_video_playback_failures as ( SELECT time, device_id, device_type, os_version, region, measure_value::bigint as video_playback_failures FROM table where time >= ago(15m) and measure_name=”video_playback_failures”),
cte_average_frame_rate as ( SELECT time, device_id, device_type, os_version, region, measure_value::double as average_frame_rate FROM table where time >= ago(15m) and measure_name=”average_frame_rate”)
SELECT a.time, a.device_id, a.os_version, a.region, a.video_startup_time, b.rebuffering_ratio, c.video_playback_failures, d.average_frame_rate FROM cte_video_startup_time a, cte_buffering_ratio b, cte_video_playback_failures c, cte_average_frame_rate d WHERE
a.time = b.time AND a.device_id = b.device_id AND a.os_version = b.os_version AND a.region=b.region AND
a.time = c.time AND a.device_id = c.device_id AND a.os_version = c.os_version AND a.region=c.region AND
a.time = d.time AND a.device_id = d.device_id AND a.os_version = d.os_version AND a.region=d.region
```

**Workload cost**: The cost of this workload is estimated to be \$1373.23 per month with single-measure records

##### Using multi-measure records
<a name="writes.writing-data-multi-measure-example1-mm"></a>

**Data modeling**: With multi-measure records, we will create one record that contains all four measures (video startup time, rebuffering ratio, video playback failures, and average frame rate), all four dimensions (device\$1id, device\$1type, os\$1version, and region), and a timestamp. 

**Writes**: When you write data into Amazon Timestream for Live Analytics, the records are constructed as follows.

```
public void writeRecords() {
    System.out.println("Writing records");
    // Specify repeated values for all records
    List<Record> records = new ArrayList<>();
    final long time = System.currentTimeMillis();
 
    List<Dimension> dimensions = new ArrayList<>();
    
    final Dimension device_id = new Dimension().withName("device_id").withValue("12345678");
    final Dimension device_type = new Dimension().withName("device_type").withValue("iPhone 11");
    final Dimension os_version = new Dimension().withName("os_version").withValue("14.8");
    final Dimension region = new Dimension().withName("region").withValue("us-east-1");
 
    dimensions.add(device_id);
    dimensions.add(device_type);
    dimensions.add(os_version);
    dimensions.add(region);
 
    Record videoMetrics = new Record()
        .withDimensions(dimensions)
        .withMeasureName("video_metrics")
        .withTime(String.valueOf(time));
        .withMeasureValueType(MeasureValueType.MULTI)
        .withMeasureValues(
          new MeasureValue()
        	.withName("video_startup_time")
        	.withValue("0")
        	.withValueType(MeasureValueType.BIGINT),
        	new MeasureValue()
		.withName("rebuffering_ratio")
        	.withValue("0.5")
        	.withType(MeasureValueType.DOUBLE),
          new MeasureValue()
        	.withName("video_playback_failures")
        	.withValue("0")
        	.withValueType(MeasureValueType.BIGINT),
		 new MeasureValue()
         	.withName("average_frame_rate")
        	.withValue("0.5")
        	.withValueType(MeasureValueType.DOUBLE))
 
    records.add(videoMetrics);
 
    WriteRecordsRequest writeRecordsRequest = new WriteRecordsRequest()
        .withDatabaseName(DATABASE_NAME)
        .withTableName(TABLE_NAME)
        .withRecords(records);
 
    try {
      WriteRecordsResult writeRecordsResult = amazonTimestreamWrite.writeRecords(writeRecordsRequest);
      System.out.println("WriteRecords Status: " + writeRecordsResult.getSdkHttpMetadata().getHttpStatusCode());
    } catch (RejectedRecordsException e) {
      System.out.println("RejectedRecords: " + e);
      for (RejectedRecord rejectedRecord : e.getRejectedRecords()) {
        System.out.println("Rejected Index " + rejectedRecord.getRecordIndex() + ": "
            + rejectedRecord.getReason());
      }
      System.out.println("Other records were written successfully. ");
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }
  }
```

When you store multi-measure records, the data is logically represented as follows.


| Time | device\$1id | device\$1type | os\$1version | region | measure\$1name | video\$1startup\$1time | rebuffering\$1ratio | video\$1 playback\$1failures | average\$1frame\$1rate | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 
|  2021-09-07 21:48:44 .000000000  |  12345678  |  iPhone 11  |  14.8  |  us-east-1  |  video\$1metrics  |  200  |  0.5  |  0  |  0.85  | 
|  2021-09-07 21:53:44 .000000000  |  12345678  |  iPhone 11  |  14.8  |  us-east-1  |  video\$1metrics  |  500  |  1.5  |  10  |  0.2  | 

**Queries**: You can write a query that retrieves all of the data points with the same timestamp received over the past 15 minutes as follows.

```
SELECT time, device_id, device_type, os_version, region, video_startup_time, rebuffering_ratio, video_playback_failures, average_frame_rate FROM table where time >= ago(15m)
```

**Workload cost**: The cost of workload is estimated to be \$1127.43 with multi-measure records.

**Note**  
In this case, using multi-measure records reduces the overall estimated monthly spend by 2.5x, with the data writes cost reduced by 3.3x, the storage cost reduced by 3.3x, and the query cost reduced by 1.2x.

### Writing data with a timestamp that exists in the past or in the future
<a name="writes.timestamp-past-future"></a>

Timestream for Live Analytics offers the ability to write data with a timestamp that lies outside of the memory store retention window through a couple different mechanisms.
+ **Magnetic store writes** – You can write late-arriving data directly into the magnetic store through magnetic store writes. To use magnetic store writes, you must first enable magnetic store writes for a table. You can then ingest data into the table using the same mechanism used for writing data into the memory store. Amazon Timestream for Live Analytics will automatically write the data into the magnetic store based on its timestamp.
**Note**  
The write-to-read latency for the magnetic store can be up to 6 hours, unlike writing data into the memory store, where the write-to-read latency is in the sub-second range.
+ **TIMESTAMP data type for measures** – You can use the TIMESTAMP data type to store data from the past, present, or future. A multi-measure record can have multiple attributes of TIMESTAMP data type, in addition to the time field in a record. TIMESTAMP attributes, in a multi-measure record, can have timestamps in the future or the past and behave like the time field except that Timestream for Live Analytics does not index on the values of type TIMESTAMP in a multi-measure record.
**Note**  
The TIMESTAMP data type is supported only for multi-measure records.

## Eventual consistency for reads
<a name="writes.eventual-consistency"></a>

Timestream for Live Analytics supports eventual consistency semantics for reads. This means that when you query data immediately after writing a batch of data into Timestream for Live Analytics, the query results might not reflect the results of a recently completed write operation. If you repeat these query requests after a short time, the results should return the latest data. 

# Batching writes with WriteRecords API
<a name="writes.batching-writes"></a>

Amazon Timestream for Live Analytics enables you to write data points from a single time series and/or data points from many series in a single write request. Batching multiple data points in a single write operation is beneficial from a performance and cost perspective. See [Writes](metering-and-pricing.writes.md) in the Metering and Pricing section for more details.

**Note**  
Your write requests to Timestream for Live Analytics may be throttled as Timestream for Live Analytics scales to adapt to the data ingestion needs of your application. If your applications encounter throttling exceptions, you must continue to send data at the same (or higher) throughput to allow Timestream for Live Analytics to automatically scale to your application's needs. 

# Batch load
<a name="batch-load-how"></a>

With *batch load* for Amazon Timestream for LiveAnalytics, you can ingest CSV files stored in Amazon S3 into Timestream in batches. With this new functionality, you can have your data in Timestream for LiveAnalytics without having to rely on other tools or write custom code. You can use batch load for backfilling data with flexible wait times, such as data that isn't immediately required for querying or analysis.

You can create batch load tasks by using the AWS Management Console, the AWS CLI, and the AWS SDKs. For more information, see [Using batch load with the console](batch-load-using-console.md), [Using batch load with the AWS CLI](batch-load-using-cli.md), and [Using batch load with the AWS SDKs](batch-load-using-sdk.md).

For more information about batch load, see [Using batch load in Timestream for LiveAnalytics](batch-load.md).

# Choosing between the WriteRecords API operation and batch load
<a name="writes.writes-or-batch-load"></a>

With the WriteRecords API operation, you can write your streaming time series data into Timestream for LiveAnalytics as it's generated by your system. By using WriteRecords, you can continuously ingest a single data point or smaller batches of data in real time. Timestream for LiveAnalytics offers you a flexible schema that auto detects the column names and data types for your Timestream for LiveAnalytics tables, based on the dimension names and data types of the data points you specify when invoking writes into the database. 

In contrast, *batch load* enables the robust ingestion of batched time-series data from source files (CSV files) into Timestream for LiveAnalytics, using a data model that you define. A few examples for when to use batch load with a source file are importing time series data in bulk for the evaluation of Timestream for LiveAnalytics through a proof of concept, importing time series data in bulk from an IoT device that was offline for some time, and migrating historical time series data from Amazon S3 to Timestream for LiveAnalytics. For information about batch load, see [Using batch load in Timestream for LiveAnalytics](batch-load.md).

Both solutions are secure, reliable, and performant.

**Use WriteRecords when:**
+ Streaming smaller amounts (less than 10 MB) of data per request.
+ Populating existing tables.
+ Ingesting data from a log stream.
+ Performing real-time analytics.
+ Requiring lower latency.

**Use batch load when:**
+ Ingesting larger loads of data that originate in Amazon S3 in CSV files. For more information about limits, see [QuotasDefault quotas](ts-limits.md).
+ Populating new tables, such as in the case of a data migration.
+ Enriching databases with historical data (ingestion into new tables).
+ You have source data that changes slowly or not at all.
+ You have flexible wait times because a batch load task might be in a pending state until resources are available, especially if you load a very large amount of data. Batch load is suitable for data that doesn't need to be readily available for querying or analysis to add more clarity.

# Storage
<a name="storage"></a>

Timestream for Live Analytics stores and organizes your time series data to optimize query processing time and to reduce storage costs. It offers data storage tiering and supports two storage tiers: a memory store and a magnetic store. The memory store is optimized for high throughput data writes and fast point-in-time queries. The magnetic store is optimized for lower throughput late-arriving data writes, long term data storage, and fast analytical queries. 

Timestream for Live Analytics ensures durability of your data by automatically replicating your memory and magnetic store data across different Availability Zones within a single AWS Region. All of your data is written to disk before acknowledging your write request as complete. 

Timestream for Live Analytics enables you to configure retention policies to move data from the memory store to the magnetic store. When the data reaches the configured value, Timestream for Live Analytics automatically moves the data to the magnetic store. You can also set a retention value on the magnetic store. When data expires out of the magnetic store, it is permanently deleted. 

For example, consider a scenario where you configure the memory store to hold a week's-worth of data and the magnetic store to hold 1 year's-worth of data. The age of the data is computed using the timestamp associated with the data point. When the data in the memory store becomes a week old it is automatically moved to the magnetic store. It is then retained in the magnetic store for a year. When the data becomes a year old, it is deleted from Timestream for Live Analytics. The retention values of the memory store and the magnetic store cumulatively define the amount of time that your data will be stored in Timestream for Live Analytics. This means that for the above scenario, from the time of data arrival, the data is stored in Timestream for Live Analytics for a total period of 1 year and 1 week. 

**Note**  
When you upgrade the retention period of the memory or magnetic store, the retention change takes effect from that point onwards. For example, if the retention period of the memory store was set to 2 hours and then changed to 24 hours by updating the table retention policies, the memory store will be capable of holding 24 hours of data, but will be populated with 24 hours of data 22 hours after this change was made. Timestream for Live Analytics does not retrieve data from the magnetic store to populate the memory store. 

To ensure the security of your time series data, your data in Timestream for Live Analytics is always encrypted by default. This applies to data in transit and at rest. Furthermore, Timestream for Live Analytics enables you to use customer managed keys to secure your data in the magnetic store. For more information on customer managed keys, see [AWS KMS keys](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#kms_keys). 

# Queries
<a name="queries"></a>

With Timestream for Live Analytics, you can easily store and analyze metrics for DevOps, sensor data for IoT applications, and industrial telemetry data for equipment maintenance, as well as many other use cases. The purpose-built, adaptive query engine in Timestream for Live Analytics allows you to access data across storage tiers using a single SQL statement. It transparently accesses and combines data across storage tiers without requiring you to specify the data location. You can use SQL to query data in Timestream for Live Analytics to retrieve time series data from one or more tables. You can access the metadata information for databases and tables. Timestream for Live Analytics SQL also supports built-in functions for time series analytics. You can refer to the [Query language reference](reference.md) reference for additional details. 

Timestream for Live Analytics is designed to have a fully decoupled data ingestion, storage, and query architecture where each component can scale independently of other components (allowing it to offer virtually infinite scale for an application's needs). This means that Timestream for Live Analytics does not "tip over" when your applications send hundreds of terabytes of data per day or run millions of queries processing small or large amounts of data. As your data grows over time, the query latency in Timestream for Live Analytics remains mostly unchanged. This is because the Timestream for Live Analytics query architecture can leverage massive amounts of parallelism to process larger data volumes and automatically scale to match query throughput needs of an application. 

## Data model
<a name="datamodel"></a>

 Timestream supports two data models for queries—the flat model and the time series model. 

**Note**  
Data in Timestream is stored using the flat model and it is the default model for querying data. The time series model is a query-time concept and is used for time series analytics.
+  [Flat model](#flatmodel) 
+  [Time series model](#timeseriesmodel) 

### Flat model
<a name="flatmodel"></a>

 The flat model is Timestream's default data model for queries. It represents time series data in a tabular format. The dimension names, time, measure names and measure values appear as columns. Each row in the table is an atomic data point corresponding to a measurement at a specific time within a time series. Timestream databases, tables, and columns have some naming constraints. Those are described in [Service limits](ts-limits.md#system-limits).

 The table below shows an illustrative example for how Timestream stores data representing the CPU utilization, memory utilization, and network activity of EC2 instances, when the data is sent as a single-measure record. In this case, the dimensions are the region, availability zone, virtual private cloud, and instance IDs of the EC2 instances. The measures are the CPU utilization, memory utilization, and the incoming network data for the EC2 instances. The columns region, az, vpc, and instance\$1id contain the dimension values. The column time contains the timestamp for each record. The column measure\$1name contains the names of the measures represented by cpu-utilization, memory\$1utilization, and network\$1bytes\$1in. The columns measure\$1value::double contains measurements emitted as doubles (e.g. CPU utilization and memory utilization). The column measure\$1value::bigint contains measurements emitted as integers e.g. the incoming network data. 


| Time | region | az | vpc | instance\$1id | measure\$1name | measure\$1value::double | measure\$1value::bigint | 
| --- | --- | --- | --- | --- | --- | --- | --- | 
|  2019-12-04 19:00:00.000000000  |   us-east-1   |   us-east-1d   |   vpc-1a2b3c4d   |   i-1234567890abcdef0   |   cpu\$1utilization   |   35.0   |   null   | 
|  2019-12-04 19:00:01.000000000  |   us-east-1   |   us-east-1d   |   vpc-1a2b3c4d   |   i-1234567890abcdef0   |   cpu\$1utilization   |   38.2   |   null   | 
|  2019-12-04 19:00:02.000000000  |   us-east-1   |   us-east-1d   |   vpc-1a2b3c4d   |   i-1234567890abcdef0   |   cpu\$1utilization   |   45.3   |   null   | 
|  2019-12-04 19:00:00.000000000  |   us-east-1   |   us-east-1d   |   vpc-1a2b3c4d   |   i-1234567890abcdef0   |   memory\$1utilization   |   54.9   |   null   | 
|  2019-12-04 19:00:01.000000000  |   us-east-1   |   us-east-1d   |   vpc-1a2b3c4d   |   i-1234567890abcdef0   |   memory\$1utilization   |   42.6   |   null   | 
|  2019-12-04 19:00:02.000000000  |   us-east-1   |   us-east-1d   |   vpc-1a2b3c4d   |   i-1234567890abcdef0   |   memory\$1utilization   |   33.3   |   null   | 
|  2019-12-04 19:00:00.000000000  |   us-east-1   |   us-east-1d   |   vpc-1a2b3c4d   |   i-1234567890abcdef0   |   network\$1bytes   |   34,400   |   null   | 
|  2019-12-04 19:00:01.000000000  |   us-east-1   |   us-east-1d   |   vpc-1a2b3c4d   |   i-1234567890abcdef0   |   network\$1bytes   |   1,500   |   null   | 
|  2019-12-04 19:00:02.000000000  |   us-east-1   |   us-east-1d   |   vpc-1a2b3c4d   |   i-1234567890abcdef0   |   network\$1bytes   |   6,000   |   null   | 

The table below shows an illustrative example for how Timestream stores data representing the CPU utilization, memory utilization, and network activity of EC2 instances, when the data is sent as a multi-measure record.


| Time | region | az | vpc | instance\$1id | measure\$1name | cpu\$1utilization | memory\$1utilization | network\$1bytes | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | 
|  2019-12-04 19:00:00.000000000  |   us-east-1   |   us-east-1d   |   vpc-1a2b3c4d   |   i-1234567890abcdef0   |   metrics   |   35.0   |   54.9   |   34,400   | 
|  2019-12-04 19:00:01.000000000  |   us-east-1   |   us-east-1d   |   vpc-1a2b3c4d   |   i-1234567890abcdef0   |   metrics   |   38.2   |   42.6   |   1,500   | 
|  2019-12-04 19:00:02.000000000  |   us-east-1   |   us-east-1d   |   vpc-1a2b3c4d   |   i-1234567890abcdef0   |   metrics   |   45.3   |   33.3   |   6,600   | 

### Time series model
<a name="timeseriesmodel"></a>

 The time series model is a query time construct used for time series analytics. It represents data as an ordered sequence of (time, measure value) pairs. Timestream supports time series functions such as interpolation to enable you to fill the gaps in your data. To use these functions, you must convert your data into the time series model using functions such as create\$1time\$1series. Refer to [Query language reference](reference.md) for more details. 

 Using the earlier example of the EC2 instance, here is the CPU utilization data expressed as a timeseries. 


| region | az | vpc | instance\$1id | cpu\$1utilization | 
| --- | --- | --- | --- | --- | 
|   us-east-1   |   us-east-1d   |   vpc-1a2b3c4d   |   i-1234567890abcdef0   |   [\$1time: 2019-12-04 19:00:00.000000000, value: 35\$1, \$1time: 2019-12-04 19:00:01.000000000, value: 38.2\$1, \$1time: 2019-12-04 19:00:02.000000000, value: 45.3\$1]   | 

# Scheduled queries
<a name="scheduled-query"></a>

The scheduled query feature in Amazon Timestream for Live Analytics is a fully managed, serverless, and scalable solution for calculating and storing aggregates, rollups, and other forms of preprocessed data typically used to power operational dashboards, business reports, ad hoc analytics, and other applications. Scheduled queries make real-time analytics more performant and cost-effective, so you can derive additional insights from your data, and can continue to make better business decisions.

For more information about scheduled query, see [Using scheduled queries in Timestream for LiveAnalytics](scheduledqueries.md).

# Timestream Compute Unit (TCU)
<a name="tcu"></a>

Amazon Timestream for Live Analytics measures the compute capacity allocated to you for your query needs in Timestream compute unit (TCU). One TCU comprises of 4 vCPUs and 16 GB of memory. When you run queries in Timestream for Live Analytics, the service allocates TCUs on-demand based on the complexity of your queries and the amount of data being processed. The number of TCUs that a query consumes determines the associated cost.

**Note**  
All AWS accounts that onboard to the service after April 29, 2024 will default to using TCUs for query pricing. 

**Topics**
+ [Provisioned Timestream Compute Units](provisioned-tcu.md)
+ [MaxQuery TCU](#maxquery-tcu)
+ [Billing for TCU](#billing-tcus)
+ [Configuring TCU](#config-tcus)
+ [Estimating required compute units](#estimate-compute-units)
+ [When to increase MaxQueryTCU](#increase-maxquery-tcu)
+ [When to decrease MaxQueryTCU](#decrease-maxquery-tcu)
+ [Monitoring usage with CloudWatch metrics](#cw-metrics-monitor-usage)
+ [Understanding variations in compute units usage](#variations-compute-units-usage)

# Provisioned Timestream Compute Units
<a name="provisioned-tcu"></a>

**Note**  
Provisioned TCU is available only in the Asia Pacific (Mumbai) region.

With provisioned Timestream Compute Units (TCUs), you can allocate a fixed number of TCUs to your account, ensuring predictable performance and cost for your queries. By provisioning TCUs, you gain greater control over compute capacity, enabling you to optimize both performance and query costs based on your application's specific needs.

**Topics**
+ [Benefits of Provisioning TCU](#provisioned-tcu.benefits)
+ [How Provisioned TCU Works](#provisioned-tcu.how-provisioned-tcu-works)
+ [Monitoring Provisioned TCU usage](#provisioned-tcu.monitoring)
+ [Modifying your Provisioned TCUs](#provisioned-tcu.modifying)
+ [Pricing for Provisioned TCUs](#provisioned-tcu.pricing)

## Benefits of Provisioning TCU
<a name="provisioned-tcu.benefits"></a>

Provisioning TCU provides several benefits for customers with dedicated workloads, including:

1. **Predictable Performance:** By allocating a fixed number of TCUs, you ensure consistent performance for your queries.

1. **Cost Control:** With provisioned TCU, you can better predict and manage your costs, as you are only charged for the duration of the provisioned TCUs.

1. **Flexibility:** Provisioned TCU ensures that your workload has dedicated compute resources and you can adjust the number of provisioned TCUs to match your workload requirements, providing the required scalability as your application’s needs change. 

## How Provisioned TCU Works
<a name="provisioned-tcu.how-provisioned-tcu-works"></a>

Each Timestream Compute Unit (TCU) is comprised of 4 vCPUs and 16GB of memory. To provision TCUs, use the AWS Management Console or the UpdateAccountSettings API operation to allocate a fixed number of TCUs to your account, which are then dedicated to your workload. This ensures predictable performance and cost for your queries. The minimum number of provisioned TCUs is 4, with subsequent increments also in multiples of 4 (e.g., 4, 8, 12, 16). Once provisioned, you can run your query workloads uninterrupted. As your workload demands change, you can adjust the provisioned TCUs using the AWS Management Console or the UpdateAccountSettings API operation at any time. However, you can only decrease the number of TCUs after a minimum of 1 hour has passed since provisioning them.

For example, if you provision 8 TCUs at 10:00 AM, you will be charged for a minimum of 1 hour, until 11:00 AM. During this time, you can increment the TCUs to 12 or more, but you cannot decrement them until 11:00 AM. 

The time it takes to provision the requested Timestream Compute Units (TCUs) in your account varies depending on the number of TCUs requested. For example, provisioning 100 TCUs could take up to 30 minutes. However, you will only be charged for the resources once they are provisioned and available to serve your query workload. To ensure a smooth experience during planned increases in usage, we recommend provisioning the required resources in advance. This allows sufficient time for the resources to become available and ensures that your workload can be handled without interruption.

## Monitoring Provisioned TCU usage
<a name="provisioned-tcu.monitoring"></a>

To monitor your provisioned TCU usage, you can use the following CloudWatch metrics:
+ **Provisioned QueryTCU:** This metric specifies the number of TCUs provisioned in your account.
+ **QueryTCU:** This metric specifies the number of TCUs used by your workload.
+ **InsufficientTCUThrottles:** This metric specifies the number of queries throttled due to insufficient compute capacity.

## Modifying your Provisioned TCUs
<a name="provisioned-tcu.modifying"></a>

You can adjust the number of provisioned Timestream Compute Units (TCUs) to match your changing workload demands using the AWS Management Console, AWS Command Line Interface (CLI), or AWS SDKs. 

To view the current number of provisioned TCUs in your account, navigate to the "Admin Dashboard" section in the AWS Management Console. From there, you can easily monitor and manage your provisioned TCUs.

In the Query Compute Settings, you can verify that the compute mode is set to "Provisioned" and view the current number of provisioned Timestream Compute Units (TCUs) in your account, which is displayed as "Active Query TCU". The default value is 0. You need to provision TCUs before you run your query workload. 

To modify the query compute settings, click the "Modify" button. For instance, if you want to increase the provisioned TCUs from 32 to 64, simply enter your desired target value (64) in the "Target Query TCU" field. Additionally, you can specify an Amazon Simple Notification Service (SNS) topic to receive a notification when the provisioning process is complete.

![\[Image of console view of modifying settings for provisioned TCUs.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/modify-prov-tcu-settings.png)


After confirming your desired configuration by selecting "Save settings", you will see that the current request status is updated to "Pending". The "Target Query TCU" field will now reflect the desired number of compute units, which is 64 in this case, indicating that the provisioning process has been initiated and is awaiting completion.

![\[Image of console view of saving settings for provisioned TCUs.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/query-compute-save-settings.png)


Once provisioned, the "Active Query TCU" field will be updated to reflect the new provisioned capacity of 64 Timestream Compute Units, indicating that the provisioning process is complete and the additional resources are now available for use in your account.

![\[Image of console view of new updated settings for provisioned TCUs.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/query-compute-updated-settings.png)


To reduce the number of provisioned Timestream Compute Units (TCUs) in your account, follow the same steps as before and enter your desired target value. For example, if you want to decrease the provisioned TCUs to 16, simply set the "Target Query TCU" field to 16. Please note that you can only decrease the number of provisioned TCUs after a minimum of 1 hour has passed since the last provisioning request. This means that if you provisioned or modified your TCUs within the last hour, you will need to wait until the 1-hour window has elapsed before you can decrement the TCUs.

![\[Image of console view of reducing the number of provisioned TCUs.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/query-modify-reduce-tcu-settings.png)


After requesting a decrease in provisioned Timestream Compute Units (TCUs), the service will decrement the TCUs when it determines it is safe to do so, which may take up to a few minutes. During this time, the "Target Query TCU" field will continue to display the desired target value, in this case, 16 TCUs, indicating the pending change. Once the decrement is complete, the "Active Query TCU" field will be updated to reflect the new provisioned capacity of 16 TCUs.

![\[Image of console view of updated reduced number of provisioned TCUs.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/query-modify-updated-reduce-tcu-settings.png)


Once the request is successfully completed, the "Active Query TCU" field will be updated to reflect the new provisioned capacity of 16 Timestream Compute Units (TCUs). If you no longer anticipate any query workload, you can further decrement the provisioned TCUs to 0, effectively releasing all provisioned resources and stopping any associated charges.

## Pricing for Provisioned TCUs
<a name="provisioned-tcu.pricing"></a>

You are charged for the duration of the Timestream Compute Units (TCUs) provisioned in your account, with a minimum charge of 1 hour. After the first hour, the TCUs are metered per second. 

To calculate the total metered hours, multiply the number of provisioned TCUs by the duration of use. For example: If you provision 16 TCUs for 2 hours, the total metered hours are 16 TCU \$1 2 hours = 32 TCU-hours. If you provision 16 TCUs for 4 hours, then decrement to 8 TCUs and use them for 6 hours, the total metered hours are 16 TCU \$1 4 hours \$1 8 TCU \$1 6 hours = 112 TCU-hours. 

Your total spend will depend on the prevailing TCU-hour cost in your region. Please refer to the Amazon Timestream Pricing page for detailed information. 

**Best Practices for managing Provisioned TCU**

To get the most out of the Provisioned TCU feature, follow these best practices:
+ **Monitor your workload:** Monitor your workload's performance, [QueryTCU used](monitoring-cloudwatch.md) and view `InsufficientTCUThrottles` to understand your usage patterns and adjust your provisioned TCUs accordingly.
+ **Pro-active adjustment:** Increase or decrease provisioned TCUs based on observed trends and anticipated workload changes. Make adjustments for your peak and off-peak periods. 
+ **Maintain Headroom:** Maintain your consumed QueryTCU to within 80% - 90% of your ProvisionedQueryTCU to handle unexpected spikes. 
+ **Optimize Queries:** Leverage features such as Query Insights and follow Timestream Query best practices to optimize queries for reduced compute usage.
+ **Implement Retries:**Timestream for LiveAnalytics Query SDK supports a retry mechanism with a default of 3 retries. Adjust the value accordingly to handle occasional and unanticipated bursts.

## MaxQuery TCU
<a name="maxquery-tcu"></a>

This setting specifies the maximum number of compute units the service will use at any point in time to serve your queries. To run queries, you must set the minimum capacity to 4 TCUs. You can set the maximum number of TCUs in multiples of 4, for example, 4, 8, 16, 32, and so on. You're charged only for the compute resources you use for your workload. For example, if you set the maximum TCUs to 128, but consistently use only 8 TCUs. You'll be charged only for the duration during which you used the 8 TCUs. The default `MaxQueryTCU` in your account is set to 200. You can adjust `MaxQueryTCU` from 4 to 1000, using the AWS Management Console or [UpdateAccountSettings](https://docs.aws.amazon.com/timestream/latest/developerguide/API_query_UpdateAccountSettings.html) API operation with the AWS SDK or AWS CLI.

We recommend setting the `MaxQueryTCU` for your account. Setting a maximum TCU limit helps control costs by restricting the number of compute units the service can use for your query workload. This allows you to better predict and manage your query spending.

## Billing for TCU
<a name="billing-tcus"></a>

Each TCU is billed on an hourly basis with per-second granularity and for a minimum of 30 seconds. The usage unit of these compute units is TCU-hour.

When you run queries, you're billed for the TCUs used during the query execution time, measured in TCU-hours. For example:
+ Your workload uses 20 TCUs for 3 hours. You're billed for 60 TCU-hours (20 TCUs x 3 hours).
+ Your workload uses 10 TCUs for 30 minutes, and then 20 TCUs for the next 30 minutes. You're billed for 15 TCU-hours (10 TCUs x 0.5 hours \$1 20 TCUs x 0.5 hours).

The pricing per TCU-hour varies by AWS Region. Refer to [Amazon Timestream pricing](https://aws.amazon.com/timestream/pricing/) for additional details. As your workload grows, the service automatically scales the compute capacity up to the specified maximum TCU limit (`MaxQueryTCU`) to maintain consistent performance. The `MaxQueryTCU` setting acts as a ceiling for the compute capacity that the service can scale to. This setting helps you to control the number of compute resources and as a result their cost.

## Configuring TCU
<a name="config-tcus"></a>

When you onboard the service, each AWS account has a default `MaxQueryTCU` limit of 200. You can update this limit as required at any point in time using the AWS Management Console or [UpdateAccountSettings](https://docs.aws.amazon.com/timestream/latest/developerguide/API_query_UpdateAccountSettings.html) API operation with the AWS SDK or AWS CLI.

If you're unsure about the values to configure, monitor the `QueryTCU` metric for your account. This metric is available in the AWS Management Console and Amazon CloudWatch. This metric provides insight into the maximum number of TCUs used at a minute granularity. Based on historical data and your estimation of future growth, set the `MaxQueryTCU` to accommodate the spikes in your usage. We recommend having a headroom of at least 4-16 TCUs above your peak usage. For example, if your peak `QueryTCU` in the last 30 days was 128, we recommend setting `MaxQueryTCU` between 132 to 144.

## Estimating required compute units
<a name="estimate-compute-units"></a>

Compute units can process queries concurrently. To determine the number of compute units required, consider the general guidelines in the following table: 


| Concurrent queries | TCUs | 
| --- | --- | 
| 7 | 4 | 
| 14 | 8 | 
| 21 | 12 | 

**Note**  
These are general guidelines and the actual number of compute units required depends on several factors, such as:  
The effective concurrency of queries.
Query patterns.
The number of partitions scanned.
Other workload-specific characteristics.
This guideline pertains to queries that scan for the last few minutes to an hour of data and adhere to the [Timestream query best practices](queries-bp.md) and [Data modeling guidelines](data-modeling.md).
Monitor your application's performance and the `QueryTCU` metric to adjust the compute units, as required.

## When to increase MaxQueryTCU
<a name="increase-maxquery-tcu"></a>

You should consider increasing the `MaxQueryTCU` in the following scenarios:
+ Your peak query consumption is approaching or reaching the current configured maximum query TCU. We recommend setting the maximum query TCU at least 4-16 TCUs higher than your peak consumption.
+ Your queries are returning a 4xx error with the message MaxQueryTCU exceeded. If you anticipate a planned increase in your workload, revisit and adjust the configured maximum query TCU accordingly.

## When to decrease MaxQueryTCU
<a name="decrease-maxquery-tcu"></a>

You should consider decreasing the `MaxQueryTCU` in the following scenarios:
+ Your workload has a predictable and stable usage pattern, and you have a good understanding of your compute usage requirements. Lowering the maximum query TCU to within 4-16 TCU above your peak consumption can help prevent unintentional usage and costs. You can modify the value using the [UpdateAccountSettings](https://docs.aws.amazon.com/timestream/latest/developerguide/API_query_UpdateAccountSettings.html) API operation.
+ Your workload's peak usage has decreased over time, either due to changes in your application or user behavior patterns. Lowering the maximum TCU can help mitigate unintentional costs.

**Note**  
Depending on your current usage, reducing the maximum TCU limit change might take up to 24 hours to be effective. You're billed only for the TCUs that your queries actually consume. Having a higher maximum query TCU limit does not impact your costs unless those TCUs are used by your workload.

## Monitoring usage with CloudWatch metrics
<a name="cw-metrics-monitor-usage"></a>

To monitor your TCU usage, Timestream for Live Analytics provides the following CloudWatch metric: `QueryTCU`. This metric specifies the number of compute units used in a minute and is emitted every minute. You can choose to monitor the maximum and minimum TCUs used in a minute. You can also set alarms on this metric to track your query costs in real-time.

## Understanding variations in compute units usage
<a name="variations-compute-units-usage"></a>

The number of compute resources required for your queries can either increase or decrease based on several parameters. For example, data volume, data ingestion patterns, query latency, query shape, query efficiency, and query combinations that use real-time and analytical queries. These parameters can lead to either higher or lower TCU units required for your workload. In a steady state where these parameters don't change, you might observe that the number of compute units required for your workload decrease. Consequently, this can lower your monthly cost.

Additionally, if any of these parameters in your workload or data change, the number of compute units required might increase. When Timestream receives a query, depending upon the data partitions the query accesses, Timestream decides the number of compute resources to performantly address the query.

At periodic intervals, based on your ingest and query access patterns, Timestream optimizes the data layout. Timestream performs the optimization by clubbing less accessed partitions into a single partition or splitting a hot partition into multiple partitions for performance. Consequently, the compute capacity used by the same query might vary slightly at different points in time.

**Opting-in to use TCU pricing for your queries**  
As an existing user, you can do a one-time opt-in to use TCUs for better cost management and removal of per query minimum bytes metered. You can opt-in using the AWS Management Console or [UpdateAccountSettings](https://docs.aws.amazon.com/timestream/latest/developerguide/API_query_UpdateAccountSettings.html) API operation with the AWS SDK or AWS CLI. In the API operation, set the `QueryPricingModel` parameter to `COMPUTE_UNITS`.  
Opting into the compute-based pricing model is an irreversible change.

# Accessing Timestream for LiveAnalytics
<a name="accessing"></a>

You can access Timestream for LiveAnalytics using the console, CLI or the API. For information about accessing Timestream for LiveAnalytics, review the following:

**Topics**
+ [Sign up for an AWS account](#sign-up-for-aws)
+ [Create a user with administrative access](#create-an-admin)
+ [Provide Timestream for LiveAnalytics access](#getting-started.prereqs.iam-user)
+ [Grant programmatic access](#programmatic-access)
+ [Using the console](console_timestream.md)
+ [Accessing Amazon Timestream for LiveAnalytics using the AWS CLI](Tools.CLI.md)
+ [Using the API](Using.API.md)
+ [Using the AWS SDKs](getting-started-sdks.md)

## Sign up for an AWS account
<a name="sign-up-for-aws"></a>

If you do not have an AWS account, complete the following steps to create one.

**To sign up for an AWS account**

1. Open [https://portal.aws.amazon.com/billing/signup](https://portal.aws.amazon.com/billing/signup).

1. Follow the online instructions.

   Part of the sign-up procedure involves receiving a phone call or text message and entering a verification code on the phone keypad.

   When you sign up for an AWS account, an *AWS account root user* is created. The root user has access to all AWS services and resources in the account. As a security best practice, assign administrative access to a user, and use only the root user to perform [tasks that require root user access](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#root-user-tasks).

AWS sends you a confirmation email after the sign-up process is complete. At any time, you can view your current account activity and manage your account by going to [https://aws.amazon.com/](https://aws.amazon.com/) and choosing **My Account**.

## Create a user with administrative access
<a name="create-an-admin"></a>

After you sign up for an AWS account, secure your AWS account root user, enable AWS IAM Identity Center, and create an administrative user so that you don't use the root user for everyday tasks.

**Secure your AWS account root user**

1.  Sign in to the [AWS Management Console](https://console.aws.amazon.com/) as the account owner by choosing **Root user** and entering your AWS account email address. On the next page, enter your password.

   For help signing in by using root user, see [Signing in as the root user](https://docs.aws.amazon.com/signin/latest/userguide/console-sign-in-tutorials.html#introduction-to-root-user-sign-in-tutorial) in the *AWS Sign-In User Guide*.

1. Turn on multi-factor authentication (MFA) for your root user.

   For instructions, see [Enable a virtual MFA device for your AWS account root user (console)](https://docs.aws.amazon.com/IAM/latest/UserGuide/enable-virt-mfa-for-root.html) in the *IAM User Guide*.

**Create a user with administrative access**

1. Enable IAM Identity Center.

   For instructions, see [Enabling AWS IAM Identity Center](https://docs.aws.amazon.com//singlesignon/latest/userguide/get-set-up-for-idc.html) in the *AWS IAM Identity Center User Guide*.

1. In IAM Identity Center, grant administrative access to a user.

   For a tutorial about using the IAM Identity Center directory as your identity source, see [ Configure user access with the default IAM Identity Center directory](https://docs.aws.amazon.com//singlesignon/latest/userguide/quick-start-default-idc.html) in the *AWS IAM Identity Center User Guide*.

**Sign in as the user with administrative access**
+ To sign in with your IAM Identity Center user, use the sign-in URL that was sent to your email address when you created the IAM Identity Center user.

  For help signing in using an IAM Identity Center user, see [Signing in to the AWS access portal](https://docs.aws.amazon.com/signin/latest/userguide/iam-id-center-sign-in-tutorial.html) in the *AWS Sign-In User Guide*.

**Assign access to additional users**

1. In IAM Identity Center, create a permission set that follows the best practice of applying least-privilege permissions.

   For instructions, see [ Create a permission set](https://docs.aws.amazon.com//singlesignon/latest/userguide/get-started-create-a-permission-set.html) in the *AWS IAM Identity Center User Guide*.

1. Assign users to a group, and then assign single sign-on access to the group.

   For instructions, see [ Add groups](https://docs.aws.amazon.com//singlesignon/latest/userguide/addgroups.html) in the *AWS IAM Identity Center User Guide*.

## Provide Timestream for LiveAnalytics access
<a name="getting-started.prereqs.iam-user"></a>

 The permissions that are required to access Timestream for LiveAnalytics are already granted to the administrator. For other users, you should grant them Timestream for LiveAnalytics access using the following policy: 

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "timestream:*",
        "kms:DescribeKey",
        "kms:CreateGrant",
        "kms:Decrypt",
        "dbqms:CreateFavoriteQuery",
        "dbqms:DescribeFavoriteQueries",
        "dbqms:UpdateFavoriteQuery",
        "dbqms:DeleteFavoriteQueries",
        "dbqms:GetQueryString",
        "dbqms:CreateQueryHistory",
        "dbqms:UpdateQueryHistory",
        "dbqms:DeleteQueryHistory",
        "dbqms:DescribeQueryHistory",
        "s3:ListAllMyBuckets"
      ],
      "Resource": "*"
    }
  ]
}
```

------

**Note**  
For information about `dbqms`, see [Actions, resources, and condition keys for Database Query Metadata Service](https://docs.aws.amazon.com/service-authorization/latest/reference/list_databasequerymetadataservice.html). For information about `kms` see [Actions, resources, and condition keys for AWS Key Management Service](https://docs.aws.amazon.com/service-authorization/latest/reference/list_awskeymanagementservice.html).

## Grant programmatic access
<a name="programmatic-access"></a>

Users need programmatic access if they want to interact with AWS outside of the AWS Management Console. The way to grant programmatic access depends on the type of user that's accessing AWS.

To grant users programmatic access, choose one of the following options.


****  

| Which user needs programmatic access? | To | By | 
| --- | --- | --- | 
| IAM | (Recommended) Use console credentials as temporary credentials to sign programmatic requests to the AWS CLI, AWS SDKs, or AWS APIs. |  Following the instructions for the interface that you want to use. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/accessing.html)  | 
|  Workforce identity (Users managed in IAM Identity Center)  | Use temporary credentials to sign programmatic requests to the AWS CLI, AWS SDKs, or AWS APIs. |  Following the instructions for the interface that you want to use. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/accessing.html)  | 
| IAM | Use temporary credentials to sign programmatic requests to the AWS CLI, AWS SDKs, or AWS APIs. | Following the instructions in [Using temporary credentials with AWS resources](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html) in the IAM User Guide. | 
| IAM | (Not recommended)Use long-term credentials to sign programmatic requests to the AWS CLI, AWS SDKs, or AWS APIs. |  Following the instructions for the interface that you want to use. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/accessing.html)  | 

# Using the console
<a name="console_timestream"></a>

 You can use the AWS Management Console for Timestream Live Analytics to create, edit, delete, describe, and list databases and tables. You can also use the console to run queries.

**Topics**
+ [Tutorial](#console_timestream.db-w-sample-data)
+ [Create a database](#console_timestream.db.using-console)
+ [Create a table](#console_timestream.table.using-console)
+ [Run a query](#console_timestream.queries.using-console)
+ [Create a scheduled query](#console_timestream.scheduledquery.using-console)
+ [Delete a scheduled query](#console_timestream.scheduledquerydeletedisable.using-console)
+ [Delete a table](#console_timestream.delete-table.using-console)
+ [Delete a database](#console_timestream.delete-db.using-console)
+ [Edit a table](#console_timestream.edit-table.using-console)
+ [Edit a database](#console_timestream.edit-db.using-console)

## Tutorial
<a name="console_timestream.db-w-sample-data"></a>

 This tutorial shows you how to create a database populated with sample data sets and run sample queries. The sample datasets used in this tutorial are frequently seen in IoT and DevOps scenarios. The IoT dataset contains time series data such as the speed, location, and load of a truck, to streamline fleet management and identify optimization opportunities. The DevOps dataset contains EC2 instance metrics such as CPU, network, and memory utilization to improve application performance and availability. Here's a [video tutorial](https://www.youtube.com/watch?v=YBWCGDd4ChQ) for the instructions described in this section 

Follow these steps to create a database populated with the sample data sets and run sample queries using the AWS Console.

1. Open the [AWS Console](https://console.aws.amazon.com/timestream).

1. In the navigation pane, choose **Databases**

1. Click on **Create database**.

1. On the create database page, enter the following:
   + **Choose configuration**—Select **Sample database**.
   + **Name**—Enter a database name of your choice.
   + **Choose sample datasets**—Select **IoT** and **DevOps**.
   +  Click on **Create database** to create a database containing two tables—IoT and DevOps populated with sample data. 

1. In the navigation pane, choose **Query editor**

1. Select **Sample queries** from the top menu.

1. Click on one of the sample queries. This will take you back to the query editor with the editor populated with the sample query.

1. Click **Run** to run the query and see query results.

## Create a database
<a name="console_timestream.db.using-console"></a>

Follow these steps to create a database using the AWS Console.

1. Open the [AWS Console](https://console.aws.amazon.com/timestream).

1. In the navigation pane, choose **Databases**

1. Click on **Create database**.

1. On the create database page, enter the following.
   + **Choose configuration**—Select **Standard database**.
   + **Name**—Enter a database name of your choice.
   + **Encryption **—Choose a KMS key or use the default option, where Timestream Live Analytics will create a KMS key in your account if one does not already exist.

1.  Click on **Create database** to create a database.

## Create a table
<a name="console_timestream.table.using-console"></a>

Follow these steps to create a table using the AWS Console.

1. Open the [AWS Console](https://console.aws.amazon.com/timestream).

1. In the navigation pane, choose **Tables**

1. Click on **Create table**.

1. On the create table page, enter the following.
   + **Database name**—Select the name of the database created in [Create a database](#console_timestream.db.using-console).
   + **Table name**—Enter a table name of your choice.
   + **Memory store retention**—Specify how long you want to retain data in the memory store. The memory store processes incoming data, including late arriving data (data with a timestamp earlier than the current time) and is optimized for fast point-in-time queries.
   + **Magnetic store retention**—Specify how long you want to retain data in the magnetic store. The magnetic store is meant for long term storage and is optimized for fast analytical queries.

1.  Click on **Create table**.

## Run a query
<a name="console_timestream.queries.using-console"></a>

Follow these steps to run queries using the AWS Console.

1. Open the [AWS Console](https://console.aws.amazon.com/timestream).

1. In the navigation pane, choose **Query editor**

1. In the left pane, select the database created in [Create a database](#console_timestream.db.using-console).

1. In the left pane, select the database created in [Create a table](#console_timestream.table.using-console).

1. In the query editor, you can run a query. To see the latest 10 rows in the table, run: 

   ```
   SELECT * FROM <database_name>.<table_name> ORDER BY time DESC LIMIT 10
   ```

1. (Optional) Turn on **Enable Insights** to get insights about the efficiency of your queries. 

## Create a scheduled query
<a name="console_timestream.scheduledquery.using-console"></a>

Follow these steps to create a scheduled query using the AWS Console.

1. Open the [AWS Console](https://console.aws.amazon.com/timestream).

1. In the navigation pane, choose **Scheduled queries**.

1. Click on **Create scheduled query**.

1. In the **Query Name** and **Destination Table** sections, enter the following.
   + **Name**—Enter a query name.
   + **Database name**—Select the name of the database created in [Create a database](#console_timestream.db.using-console).
   + **Table name**—Select the name of the table created in [Create a table](#console_timestream.table.using-console).

1. In the **Query Statement** section, enter a valid query statement. Then click **Validate query**.

1. From **Destination table model**, define the model for any undefined attributes. You can use **Visual builder** or JSON.

1. In the **Run schedule** section, choose **Fixed rate** or **Chron expression**.For chron expressions, refer to [Schedule Expressions for Scheduled Queries](https://docs.aws.amazon.com/timestream/latest/developerguide/scheduledqueries-schedule.html) for more details on schedule expressions. 

1. In the **SNS topic** section, enter the SNS topic that will be used to for notification.

1. In the **Error log report** section enter the S3 location that will be used to report errors.

   Choose the **Encryption key type**.

1. In the **Security settings** section from **AWS KMS key**, choose the type of AWS KMS key.

   Enter the **IAM role** that Timestream for LiveAnalytics will use to run the scheduled query. Refer to the [IAM policy examples for scheduled queries](https://docs.aws.amazon.com/timestream/latest/developerguide/security_iam_id-based-policy-examples.html#security_iam_id-based-policy-examples-sheduledqueries) for details on the required permissions and trust relationship for the role.

1.  Click **Create scheduled query**.

## Delete a scheduled query
<a name="console_timestream.scheduledquerydeletedisable.using-console"></a>

Follow these steps to delete or disable a scheduled query using the AWS Console.

1. Open the [AWS Console](https://console.aws.amazon.com/timestream).

1. In the navigation pane, choose **Scheduled queries**

1. Select the scheduled query created in [Create a scheduled query](#console_timestream.scheduledquery.using-console).

1. Select **Actions**.

1. Choose **Disable** or **Delete**.

1. If you selected Delete, confirm the action and select **Delete**.

## Delete a table
<a name="console_timestream.delete-table.using-console"></a>

Follow these steps to delete a database using the AWS Console.

1. Open the [AWS Console](https://console.aws.amazon.com/timestream).

1. In the navigation pane, choose **Tables**

1. Select the table that you created in [Create a table](#console_timestream.table.using-console).

1. Click **Delete**.

1. Type *delete* in the confirmation box.

## Delete a database
<a name="console_timestream.delete-db.using-console"></a>

Follow these steps to delete a database using the AWS Console: 

1. Open the [AWS Console](https://console.aws.amazon.com/timestream).

1. In the navigation pane, choose **Databases**

1. Select the database that you created in **Create a database**.

1. Click **Delete**.

1. Type *delete* in the confirmation box.

## Edit a table
<a name="console_timestream.edit-table.using-console"></a>

Follow these steps to edit a table using the AWS Console.

1. Open the [AWS Console](https://console.aws.amazon.com/timestream).

1. In the navigation pane, choose **Tables**

1. Select the table that you created in [Create a table](#console_timestream.table.using-console).

1. Click **Edit**

1. Edit the table details and save.
   + **Memory store retention**—Specify how long you want to retain data in the memory store. The memory store processes incoming data, including late arriving data (data with a timestamp earlier than the current time) and is optimized for fast point-in-time queries.
   + **Magnetic store retention**—Specify how long you want to retain data in the magnetic store. The magnetic store is meant for long term storage and is optimized for fast analytical queries.

## Edit a database
<a name="console_timestream.edit-db.using-console"></a>

Follow these steps to edit a database using the AWS Console.

1. Open the [AWS Console](https://console.aws.amazon.com/timestream).

1. In the navigation pane, choose **Databases**

1. Select the database that you created in **Create a database**.

1. Click **Edit**

1. Edit the database details and save.

# Accessing Amazon Timestream for LiveAnalytics using the AWS CLI
<a name="Tools.CLI"></a>

 You can use the AWS Command Line Interface (AWS CLI) to control multiple AWS services from the command line and automate them through scripts. You can use the AWS CLI for ad hoc operations. You can also use it to embed Amazon Timestream for LiveAnalytics operations within utility scripts.

 Before you can use the AWS CLI with Timestream for LiveAnalytics, you must set up programmatic access. For more information, see [Grant programmatic access](accessing.md#programmatic-access). 

For a complete listing of all the commands available for the Timestream for LiveAnalytics Query API in the AWS CLI, see the [AWS CLI Command Reference](https://docs.aws.amazon.com/cli/latest/reference/timestream-query/index.html).

For a complete listing of all the commands available for the Timestream for LiveAnalytics Write API in the AWS CLI, see the [AWS CLI Command Reference](https://docs.aws.amazon.com/cli/latest/reference/timestream-write/index.html).

**Topics**
+ [Downloading and configuring the AWS CLI](#Tools.CLI.DownloadingAndRunning)
+ [Using the AWS CLI with Timestream for LiveAnalytics](#Tools.CLI.UsingWithQLDB)

## Downloading and configuring the AWS CLI
<a name="Tools.CLI.DownloadingAndRunning"></a>

The AWS CLI runs on Windows, macOS, or Linux. To download, install, and configure it, follow these steps:

1. Download the AWS CLI at [http://aws.amazon.com/cli](https://aws.amazon.com/cli).

1. Follow the instructions for [Installing the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/installing.html) and [Configuring the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html) in the *AWS Command Line Interface User Guide*.

## Using the AWS CLI with Timestream for LiveAnalytics
<a name="Tools.CLI.UsingWithQLDB"></a>

The command line format consists of an Amazon Timestream for LiveAnalytics operation name, followed by the parameters for that operation. The AWS CLI supports a shorthand syntax for the parameter values, in addition to JSON.

 Use `help` to list all available commands in Timestream for LiveAnalytics. For example: 

```
aws timestream-write help
```

```
aws timestream-query help
```

 You can also use `help` to describe a specific command and learn more about its usage: 

```
aws timestream-write create-database help
```

 For example, to create a database: 

```
aws timestream-write create-database --database-name myFirstDatabase
```

 To create a table with magnetic store writes enabled: 

```
aws timestream-write create-table \
--database-name metricsdb \
--table-name metrics \
--magnetic-store-write-properties "{\"EnableMagneticStoreWrites\": true}"
```

To write data using single-measure records:

```
aws timestream-write write-records \
--database-name metricsdb \
--table-name metrics \
--common-attributes "{\"Dimensions\":[{\"Name\":\"asset_id\", \"Value\":\"100\"}], \"Time\":\"1631051324000\",\"TimeUnit\":\"MILLISECONDS\"}" \
--records "[{\"MeasureName\":\"temperature\", \"MeasureValueType\":\"DOUBLE\",\"MeasureValue\":\"30\"},{\"MeasureName\":\"windspeed\", \"MeasureValueType\":\"DOUBLE\",\"MeasureValue\":\"7\"},{\"MeasureName\":\"humidity\", \"MeasureValueType\":\"DOUBLE\",\"MeasureValue\":\"15\"},{\"MeasureName\":\"brightness\", \"MeasureValueType\":\"DOUBLE\",\"MeasureValue\":\"17\"}]"
```

To write data using multi-measure records:

```
# wide model helper method to create Multi-measure records
function ingest_multi_measure_records {
  epoch=`date +%s`
  epoch+=$i

  # multi-measure records
  aws timestream-write write-records \
  --database-name $src_db_wide \
  --table-name $src_tbl_wide \
  --common-attributes "{\"Dimensions\":[{\"Name\":\"device_id\", \
              \"Value\":\"12345678\"},\
            {\"Name\":\"device_type\", \"Value\":\"iPhone\"}, \
            {\"Name\":\"os_version\", \"Value\":\"14.8\"}, \
            {\"Name\":\"region\", \"Value\":\"us-east-1\"} ], \
            \"Time\":\"$epoch\",\"TimeUnit\":\"MILLISECONDS\"}" \
--records "[{\"MeasureName\":\"video_metrics\", \"MeasureValueType\":\"MULTI\", \
  \"MeasureValues\": \
  [{\"Name\":\"video_startup_time\",\"Value\":\"0\",\"Type\":\"BIGINT\"}, \
  {\"Name\":\"rebuffering_ratio\",\"Value\":\"0.5\",\"Type\":\"DOUBLE\"}, \
  {\"Name\":\"video_playback_failures\",\"Value\":\"0\",\"Type\":\"BIGINT\"}, \
  {\"Name\":\"average_frame_rate\",\"Value\":\"0.5\",\"Type\":\"DOUBLE\"}]}]" \
--endpoint-url $ingest_endpoint \
  --region  $region
}

# create 5 records
for i in {100..105};
  do ingest_multi_measure_records $i;
done
```

To query a table: 

```
aws timestream-query query \
--query-string "SELECT time, device_id, device_type, os_version, 
region, video_startup_time, rebuffering_ratio, video_playback_failures, \
average_frame_rate \
FROM metricsdb.metrics \
where time >= ago (15m)"
```

To create a scheduled query: 

```
aws timestream-query create-scheduled-query \
  --name scheduled_query_name \
  --query-string "select bin(time, 1m) as time, \
          avg(measure_value::double) as avg_cpu, min(measure_value::double) as min_cpu, region \
          from $src_db.$src_tbl where measure_name = 'cpu' \
          and time BETWEEN @scheduled_runtime - (interval '5' minute)  AND @scheduled_runtime \
          group by region, bin(time, 1m)" \
  --schedule-configuration "{\"ScheduleExpression\":\"$cron_exp\"}" \
  --notification-configuration "{\"SnsConfiguration\":{\"TopicArn\":\"$sns_topic_arn\"}}" \
  --scheduled-query-execution-role-arn "arn:aws:iam::452360119086:role/TimestreamSQExecutionRole" \
  --target-configuration "{\"TimestreamConfiguration\":{\
          \"DatabaseName\": \"$dest_db\",\
          \"TableName\": \"$dest_tbl\",\
          \"TimeColumn\":\"time\",\
          \"DimensionMappings\":[{\
            \"Name\": \"region\", \"DimensionValueType\": \"VARCHAR\"
          }],\
          \"MultiMeasureMappings\":{\
            \"TargetMultiMeasureName\": \"mma_name\",
            \"MultiMeasureAttributeMappings\":[{\
              \"SourceColumn\": \"avg_cpu\", \"MeasureValueType\": \"DOUBLE\", \"TargetMultiMeasureAttributeName\": \"target_avg_cpu\"
            },\
            { \
              \"SourceColumn\": \"min_cpu\", \"MeasureValueType\": \"DOUBLE\", \"TargetMultiMeasureAttributeName\": \"target_min_cpu\"
            }] \
          }\
          }}" \
  --error-report-configuration "{\"S3Configuration\": {\
        \"BucketName\": \"$s3_err_bucket\",\
        \"ObjectKeyPrefix\": \"scherrors\",\
        \"EncryptionOption\": \"SSE_S3\"\
        }\
      }"
```

# Using the API
<a name="Using.API"></a>

 In addition to the [SDKs](getting-started-sdks.md), Amazon Timestream for LiveAnalytics provides direct REST API access via the *endpoint discovery pattern*. The endpoint discovery pattern is described below, along with its use cases. 

## The endpoint discovery pattern
<a name="Using-API.endpoint-discovery"></a>

Because Timestream Live Analytics's SDKs are designed to transparently work with the service's architecture, including the management and mapping of the service endpoints, it is recommended that you use the SDKs for most applications. However, there are a few instances where use of the Timestream for LiveAnalytics REST API endpoint discovery pattern is necessary: 
+ You are using [VPC endpoints (AWS PrivateLink) with Timestream for LiveAnalytics](VPCEndpoints.md)
+ Your application uses a programming language that does not yet have SDK support
+ You require better control over the client-side implementation

This section includes information on how the endpoint discovery pattern works, how to implement the endpoint discovery pattern, and usage notes. Select a topic below to learn more. 

**Topics**
+ [The endpoint discovery pattern](#Using-API.endpoint-discovery)
+ [How the endpoint discovery pattern works](Using-API.endpoint-discovery.how-it-works.md)
+ [Implementing the endpoint discovery pattern](Using-API.endpoint-discovery.describe-endpoints.implementation.md)

# How the endpoint discovery pattern works
<a name="Using-API.endpoint-discovery.how-it-works"></a>

 Timestream is built using a [cellular architecture ](architecture.md#cells) to ensure better scaling and traffic isolation properties. Because each customer account is mapped to a specific cell in a region, your application must use the correct cell-specific endpoints that your account has been mapped to. When using the SDKs, this mapping is transparently handled for you and you do not need to manage the cell-specific endpoints. However, when directly accessing the REST API, you will need to manage and map the correct endpoints yourself. This process, the *endpoint discovery pattern*, is described below: 

1.  The endpoint discovery pattern starts with a call to the `DescribeEndpoints` action (described in the [https://docs.aws.amazon.com/timestream/latest/developerguide/API_Reference.html](https://docs.aws.amazon.com/timestream/latest/developerguide/API_Reference.html) section). 

1.  The endpoint should be cached and reused for the amount of time specified by the returned time-to-live (TTL) value (the [https://docs.aws.amazon.com/timestream/latest/developerguide/API_Endpoint.html#timestream-Type-Endpoint-CachePeriodInMinutes.html](https://docs.aws.amazon.com/timestream/latest/developerguide/API_Endpoint.html#timestream-Type-Endpoint-CachePeriodInMinutes.html)). Calls to the Timestream Live Analytics API can then be made for the duration of the TTL. 

1.  After the TTL expires, a new call to DescribeEndpoints should be made to refresh the endpoint (in other words, start over at Step 1). 

**Note**  
 Syntax, parameters and other usage information for the `DescribeEndpoints` action are described in the [API Reference](https://docs.aws.amazon.com/timestream/latest/developerguide/API_DescribeEndpoints.html). Note that the `DescribeEndpoints` action is available via both SDKs, and is identical for each. 

For implementation of the endpoint discovery pattern, see [Implementing the endpoint discovery pattern](Using-API.endpoint-discovery.describe-endpoints.implementation.md).

# Implementing the endpoint discovery pattern
<a name="Using-API.endpoint-discovery.describe-endpoints.implementation"></a>

 To implement the endpoint discovery pattern, choose an API (Write or Query), create a **DescribeEndpoints** request, and use the returned endpoint(s) for the duration of the returned TTL value(s). The implementation procedure is described below. 

**Note**  
Ensure you are familiar with the [usage notes](#Using-API.endpoint-discovery.describe-endpoints.usage-notes).

## Implementation procedure
<a name="Using-API.endpoint-discovery.describe-endpoints.implementation.procedure"></a>

1.  Acquire the endpoint for the API you would like to make calls against ([Write](https://docs.aws.amazon.com/timestream/latest/developerguide/API_Operations_Amazon_Timestream_Write.html) or [Query](https://docs.aws.amazon.com/timestream/latest/developerguide/API_Operations_Amazon_Timestream_Query.html)). using the [https://docs.aws.amazon.com/timestream/latest/developerguide/API_DescribeEndpoints.html](https://docs.aws.amazon.com/timestream/latest/developerguide/API_DescribeEndpoints.html) request. 

   1.  Create a request for [https://docs.aws.amazon.com/timestream/latest/developerguide/API_DescribeEndpoints.html](https://docs.aws.amazon.com/timestream/latest/developerguide/API_DescribeEndpoints.html) that corresponds to the API of interest ([Write](https://docs.aws.amazon.com/timestream/latest/developerguide/API_Operations_Amazon_Timestream_Write.html) or [Query](https://docs.aws.amazon.com/timestream/latest/developerguide/API_Operations_Amazon_Timestream_Query.html)) using one of the two endpoints described below. There are no input parameters for the request. Ensure that you read the notes below.   
*Write SDK:*  

      ```
      ingest.timestream.<region>.amazonaws.com
      ```  
*Query SDK:*  

      ```
      query.timestream.<region>.amazonaws.com
      ```

      An example CLI call for region `us-east-1` follows.

      ```
      REGION_ENDPOINT="https://query.timestream.us-east-1.amazonaws.com"
      REGION=us-east-1
      aws timestream-write describe-endpoints \
      --endpoint-url $REGION_ENDPOINT \
      --region $REGION
      ```
**Note**  
 The HTTP "Host" header *must* also contain the API endpoint. The request will fail if the header is not populated. This is a standard requirement for all HTTP/1.1 requests. If you use an HTTP library supporting 1.1 or later, the HTTP library should automatically populate the header for you.
**Note**  
Substitute *<region>* with the region identifier for the region the request is being made in, e.g. `us-east-1`

   1. Parse the response to extract the endpoint(s), and cache TTL value(s). The response is an array of one or more [`Endpoint` objects ](https://docs.aws.amazon.com/timestream/latest/developerguide/API_Endpoint.html). Each `Endpoint` object contains an endpoint address (`Address`) and the TTL for that endpoint (`CachePeriodInMinutes`). 

1.  Cache the endpoint for up to the specified TTL. 

1.  When the TTL expires, retrieve a new endpoint by starting over at step 1 of the Implementation. 

## Usage notes for the endpoint discovery pattern
<a name="Using-API.endpoint-discovery.describe-endpoints.usage-notes"></a>
+ The **DescribeEndpoints** action is the only action that Timestream Live Analytics regional endpoints recognize. 
+ The response contains a list of endpoints to make Timestream Live Analytics API calls against. 
+  On successful response, there should be at least one endpoint in the list. If there is more than one endpoint in the list, any of them are equally usable for the API calls, and the caller may choose the endpoint to use at random. 
+ In addition to the DNS address of the endpoint, each endpoint in the list will specify a time to live (TTL) that is allowable for using the endpoint specified in minutes.
+ The endpoint should be cached and reused for the amount of time specified by the returned TTL value (in minutes). After the TTL expires a new call to **DescribeEndpoints** should be made to refresh the endpoint to use, as the endpoint will no longer work after the TTL has expired.

# Using the AWS SDKs
<a name="getting-started-sdks"></a>

 You can access Amazon Timestream using the AWS SDKs. Timestream supports two SDKs per language; namely, the Write SDK and the Query SDK. The Write SDK is used to perform CRUD operations and to insert your time series data into Timestream. The Query SDK is used to query your existing time series data stored in Timestream. 

Once you've completed the necessary prerequisites for your SDK of choice, you can get started with the [Code samples](code-samples.md).

**Topics**
+ [Java](getting-started.java.md)
+ [Java v2](getting-started.java-v2.md)
+ [Go](getting-started.go.md)
+ [Python](getting-started.python.md)
+ [Node.js](getting-started.node-js.md)
+ [.NET](getting-started.dot-net.md)

# Java
<a name="getting-started.java"></a>

To get started with the [Java 1.0 SDK](https://aws.amazon.com/sdk-for-java/) and Amazon Timestream, complete the prerequisites, described below.

Once you've completed the necessary prerequisites for the Java SDK, you can get started with the [Code samples](code-samples.md).

## Prerequisites
<a name="getting-started.java.prereqs"></a>

Before you get started with Java, you must do the following:

1. Follow the AWS setup instructions in [Accessing Timestream for LiveAnalytics](accessing.md).

1. Set up a Java development environment by downloading and installing the following:
   + Java SE Development Kit 8 (such as [Amazon Corretto 8](https://docs.aws.amazon.com/corretto/latest/corretto-8-ug/downloads-list.html)).
   + Java IDE (such as [Eclipse](http://www.eclipse.org) or [IntelliJ](https://www.jetbrains.com/idea/)).

      For more information, see [Getting Started with the AWS SDK for Java](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html) 

1. Configure your AWS credentials and Region for development:
   + Set up your AWS security credentials for use with the AWS SDK for Java.
   + Set your AWS Region to determine your default Timestream for LiveAnalytics endpoint.

## Using Apache Maven
<a name="getting-started.java.with-maven"></a>

 You can use [Apache Maven ](https://maven.apache.org/) to configure and build AWS SDK for Java projects. 

**Note**  
To use Apache Maven, ensure your Java SDK and runtime are 1.8 or higher.

You can configure the AWS SDK as a Maven dependency as described in [ Using the SDK with Apache Maven](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/setup-project-maven.html). 

You can run compile and run your source code with the following command:

```
mvn clean compile
mvn exec:java -Dexec.mainClass=<your source code Main class>
```

**Note**  
 `<your source code Main class>` is the path to your Java source code's main class. 

## Setting your AWS credentials
<a name="getting-started.java.credentials"></a>

The [AWS SDK for Java](https://aws.amazon.com/sdk-for-java) requires that you provide AWS credentials to your application at runtime. The code examples in this guide assume that you are using an AWS credentials file, as described in [Set up AWS Credentials and Region for Development](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-credentials.html) in the *AWS SDK for Java Developer Guide*.

The following is an example of an AWS credentials file named `~/.aws/credentials`, where the tilde character (`~`) represents your home directory.

```
[default] 
aws_access_key_id = AWS access key ID goes here 
aws_secret_access_key = Secret key goes here
```

# Java v2
<a name="getting-started.java-v2"></a>

To get started with the [Java 2.0 SDK](https://aws.amazon.com/sdk-for-java/) and Amazon Timestream, complete the prerequisites, described below.

Once you've completed the necessary prerequisites for the Java 2.0 SDK, you can get started with the [Code samples](code-samples.md).

## Prerequisites
<a name="getting-started.java-v2.prereqs"></a>

Before you get started with Java, you must do the following:

1. Follow the AWS setup instructions in [Accessing Timestream for LiveAnalytics](accessing.md).

1. You can configure the AWS SDK as a Maven dependency as described in [ Using the SDK with Apache Maven](https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/welcome.html). 

1. Set up a Java development environment by downloading and installing the following:
   + Java SE Development Kit 8 (such as [Amazon Corretto 8](https://docs.aws.amazon.com/corretto/latest/corretto-8-ug/downloads-list.html)).
   + Java IDE (such as [Eclipse](http://www.eclipse.org) or [IntelliJ](https://www.jetbrains.com/idea/)).

      For more information, see [Getting Started with the AWS SDK for Java](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html) 

## Using Apache Maven
<a name="getting-started.java-v2.with-maven"></a>

 You can use [Apache Maven ](https://maven.apache.org/) to configure and build AWS SDK for Java projects. 

**Note**  
To use Apache Maven, ensure your Java SDK and runtime are 1.8 or higher.

You can configure the AWS SDK as a Maven dependency as described in [ Using the SDK with Apache Maven](https://docs.aws.amazon.com/sdk-for-java/v2/developer-guide/welcome.html). The changes required to the pom.xml file are described [here](https://docs.aws.amazon.com/sdk-for-java/v2/migration-guide/whats-different.html#adding-v2). 

You can run compile and run your source code with the following command:

```
mvn clean compile
mvn exec:java -Dexec.mainClass=<your source code Main class>
```

**Note**  
 `<your source code Main class>` is the path to your Java source code's main class. 

# Go
<a name="getting-started.go"></a>

To get started with the [Go SDK](https://aws.amazon.com/sdk-for-go/) and Amazon Timestream, complete the prerequisites, described below.

Once you've completed the necessary prerequisites for the Go SDK, you can get started with the [Code samples](code-samples.md).

## Prerequisites
<a name="getting-started.prereqs.go"></a>

1.  [Download the GO SDK 1.14](https://golang.org/doc/install). 

1.  [Configure the GO SDK](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html). 

1.  [Construct your client](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html). 

# Python
<a name="getting-started.python"></a>

To get started with the [Python SDK](https://aws.amazon.com/sdk-for-python/) and Amazon Timestream, complete the prerequisites, described below.

Once you've completed the necessary prerequisites for the Python SDK, you can get started with the [Code samples](code-samples.md).

## Prerequisites
<a name="getting-started.python.prereqs"></a>

To use Python, install and configure Boto3, following the instructions [here](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html).

# Node.js
<a name="getting-started.node-js"></a>

To get started with the [Node.js SDK](https://aws.amazon.com/sdk-for-node-js/) and Amazon Timestream, complete the prerequisites, described below.

Once you've completed the necessary prerequisites for the Node.js SDK, you can get started with the [Code samples](code-samples.md).

## Prerequisites
<a name="getting-started.node-js.prereqs"></a>

Before you get started with Node.js, you must do the following:

1. [Install Node.js](https://nodejs.org/en/).

1.  [Install the AWS SDK for JavaScript](https://aws.amazon.com/sdk-for-node-js/). 

# .NET
<a name="getting-started.dot-net"></a>

To get started with the [.NET SDK](https://aws.amazon.com/sdk-for-net/) and Amazon Timestream, complete the prerequisites, described below.

Once you've completed the necessary prerequisites for the .NET SDK, you can get started with the [Code samples](code-samples.md).

## Prerequisites
<a name="getting-started.dot-net.prereqs"></a>

Before you get started with .NET, install the required NuGet packages and ensure that AWSSDK.Core version is 3.3.107 or newer by running the following commands: 

```
dotnet add package AWSSDK.Core
dotnet add package AWSSDK.TimestreamWrite
dotnet add package AWSSDK.TimestreamQuery
```

# Getting started
<a name="getting-started"></a>

This section includes a tutorial to get you started with Amazon Timestream Live Analytics, as well as instructions for setting up a fully functional sample application. You can get started with the tutorial or the sample application by selecting one of the links below.

**Topics**
+ [Tutorial](getting-started.db-w-sample-data.md)
+ [Sample application](sample-apps.md)

# Tutorial
<a name="getting-started.db-w-sample-data"></a>

 This tutorial shows you how to create a database populated with sample data sets and run sample queries. The sample data sets used in this tutorial are frequently seen in IoT and DevOps scenarios. The IoT data set contains time series data such as the speed, location, and load of a truck, to streamline fleet management and identify optimization opportunities. The DevOps data set contains EC2 instance metrics such as CPU, network, and memory utilization to improve application performance and availability. Here's a [video tutorial](https://www.youtube.com/watch?v=YBWCGDd4ChQ) for the instructions described in this section. 

Follow these steps to create a database populated with the sample data sets and run sample queries using the AWS Console: 

## Using the console
<a name="getting-started.db-w-sample-data.using-console"></a>

Follow these steps to create a database populated with the sample data sets and run sample queries using the AWS Console: 

1. Open the [AWS Console](https://console.aws.amazon.com/timestream).

1. In the navigation pane, choose **Databases**.

1. Click on **Create database**.

1. On the create database page, enter the following:
   + **Choose configuration**—Select **Sample database**.
   + **Name**—Enter a database name of your choice. 
**Note**  
After creating a database with sample data sets, to use the sample queries which are available in the console, you can adjust the database name referenced in the query to match the database name you enter here. There are sample queries for each combination of sample data set and type of time series records. 
   + **Choose sample data sets**—Select **IoT** and **DevOps**.
   + **Choose the type of time series records**—Select **Multi-measure records**.
   +  Click on **Create database** to create a database containing two tables populated with sample data. The table names for sample data sets with multi-measure records are `DevOpsMulti` and `IoTMulti`. The table names for sample datasets with single-measure records are `DevOps` and `IoT`.

1. In the navigation pane, choose **Query editor**.

1. Select **Sample queries** from the top menu.

1. Click on one of the sample queries for a data set you chose when creating the sample database. This will take you back to the query editor with the editor populated with the sample query.

1. Adjust the database name for the sample query.

1. Click **Run** to run the query and see query results.

## Using the SDKs
<a name="getting-started.db-w-sample-data.using-sdks"></a>

 Timestream Live Analytics provides a fully functional sample application that shows you how to create a database and table, populate the table with \$1126K rows of sample data, and run sample queries. The sample application is available in [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps) for Java, Python, Node.js, Go, and .NET. 

1. Clone the GitHub repository Timestream Live Analytics sample applications following the instructions from GitHub.

1. Configure the AWS SDK to connect to Amazon Timestream Live Analytics following the instructions described in [Using the AWS SDKs](getting-started-sdks.md).

1. Compile and run the sample application using the instructions below:
   + Instructions for the [ Java sample application](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps/java/README.md).
   + Instructions for the [Java v2 sample application](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps/javaV2/README.md).
   + Instructions for the [Go sample application](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/sample_apps/goV2/README.md).
   + Instructions for the [Python sample application](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps/python/README.md).
   + Instructions for the [Node.js sample application](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps/js/README.md).
   + Instructions for the [.NET sample application](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps/dotnet/README.md).

# Sample application
<a name="sample-apps"></a>

Timestream ships with a fully functional sample application that shows how to create a database and table, populate the table with \$1126K rows of sample data, and run sample queries. Follow the steps below to get started with the sample application in any of the supported languages:

------
#### [  Java  ]

1. Clone the GitHub repository [Timestream for LiveAnalytics sample applications](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps) following the instructions from [GitHub](https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/cloning-a-repository).

1. Configure the AWS SDK to connect to Timestream for LiveAnalytics following the instructions described in Getting Started with [Java](getting-started.java.md).

1. Run the [Java sample application](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps/java) following the instructions described [here](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps/java/README.md) 

------
#### [  Java v2  ]

1. Clone the GitHub repository [Timestream for LiveAnalytics sample applications](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps) following the instructions from [GitHub](https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/cloning-a-repository).

1. Configure the AWS SDK to connect to Amazon Timestream for LiveAnalytics following the instructions described in Getting Started with [Java v2](getting-started.java-v2.md).

1. Run the [Java 2.0 sample application](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps/javaV2) following the instructions described [here](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps/javaV2/README.md) 

------
#### [  Go  ]

1. Clone the GitHub repository [Timestream for LiveAnalytics sample applications](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps) following the instructions from [GitHub](https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/cloning-a-repository).

1. Configure the AWS SDK to connect to Amazon Timestream for LiveAnalytics following the instructions described in Getting Started with [Go](getting-started.go.md).

1. Run the [Go sample application](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/goV2) following the instructions described [here](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/sample_apps/goV2/README.md) 

------
#### [  Python  ]

1. Clone the GitHub repository [Timestream for LiveAnalytics sample applications](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps) following the instructions from [GitHub](https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/cloning-a-repository).

1. Configure the AWS SDK to connect to Amazon Timestream for LiveAnalytics following the instructions described in [Python](getting-started.python.md).

1. Run the [Python sample application](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps/python) following the instructions described [here](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps/python/README.md) 

------
#### [  Node.js  ]

1. Clone the GitHub repository [Timestream for LiveAnalytics sample applications](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps) following the instructions from [GitHub](https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/cloning-a-repository).

1. Configure the AWS SDK to connect to Amazon Timestream for LiveAnalytics following the instructions described in Getting Started with [Node.js](getting-started.node-js.md).

1. Run the [Node.js sample application](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps/js) following the instructions described [here](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps/js/README.md) 

------
#### [  .NET  ]

1. Clone the GitHub repository [Timestream for LiveAnalytics sample applications](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps) following the instructions from [GitHub](https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/cloning-a-repository).

1. Configure the AWS SDK to connect to Amazon Timestream for LiveAnalytics following the instructions described in Getting Started with [.NET](getting-started.dot-net.md).

1. Run the [.NET sample application](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps/dotnet) following the instructions described [here](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps/dotnet/README.md) 

------

# Code samples
<a name="code-samples"></a>

You can access Amazon Timestream using the AWS SDKs. Timestream supports two SDKs per language; namely, the Write SDK and the Query SDK. The Write SDK is used to perform CRUD operations and to insert your time series data into Timestream. The Query SDK is used to query your existing time series data stored in Timestream. Select a topic from the list below for more details, including code samples for each of the supported SDKs.

**Topics**
+ [Write SDK client](code-samples.write-client.md)
+ [Query SDK client](code-samples.query-client.md)
+ [Create database](code-samples.create-db.md)
+ [Describe database](code-samples.describe-db.md)
+ [Update database](code-samples.update-db.md)
+ [Delete database](code-samples.delete-db.md)
+ [List databases](code-samples.list-db.md)
+ [Create table](code-samples.create-table.md)
+ [Describe table](code-samples.describe-table.md)
+ [Update table](code-samples.update-table.md)
+ [Delete table](code-samples.delete-table.md)
+ [List tables](code-samples.list-table.md)
+ [Write data (inserts and upserts)](code-samples.write.md)
+ [Run query](code-samples.run-query.md)
+ [Run UNLOAD query](code-samples.run-query-unload.md)
+ [Cancel query](code-samples.cancel-query.md)
+ [Create batch load task](code-samples.create-batch-load.md)
+ [Describe batch load task](code-samples.describe-batch-load.md)
+ [List batch load tasks](code-samples.list-batch-load-tasks.md)
+ [Resume batch load task](code-samples.resume-batch-load-task.md)
+ [Create scheduled query](code-samples.create-scheduledquery.md)
+ [List scheduled query](code-samples.list-scheduledquery.md)
+ [Describe scheduled query](code-samples.describe-scheduledquery.md)
+ [Execute scheduled query](code-samples.execute-scheduledquery.md)
+ [Update scheduled query](code-samples.update-scheduledquery.md)
+ [Delete scheduled query](code-samples.delete-scheduledquery.md)

# Write SDK client
<a name="code-samples.write-client"></a>

You can use the following code snippets to create a Timestream client for the Write SDK. The Write SDK is used to perform CRUD operations and to insert your time series data into Timestream.

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
    private static AmazonTimestreamWrite buildWriteClient() {
        final ClientConfiguration clientConfiguration = new ClientConfiguration()
                .withMaxConnections(5000)
                .withRequestTimeout(20 * 1000)
                .withMaxErrorRetry(10);

        return AmazonTimestreamWriteClientBuilder
                .standard()
                .withRegion("us-east-1")
                .withClientConfiguration(clientConfiguration)
                .build();
    }
```

------
#### [  Java v2  ]

```
    private static TimestreamWriteClient buildWriteClient() {
        ApacheHttpClient.Builder httpClientBuilder =
                ApacheHttpClient.builder();
        httpClientBuilder.maxConnections(5000);

        RetryPolicy.Builder retryPolicy =
                RetryPolicy.builder();
        retryPolicy.numRetries(10);

        ClientOverrideConfiguration.Builder overrideConfig =
                ClientOverrideConfiguration.builder();
        overrideConfig.apiCallAttemptTimeout(Duration.ofSeconds(20));
        overrideConfig.retryPolicy(retryPolicy.build());

        return TimestreamWriteClient.builder()
                .httpClientBuilder(httpClientBuilder)
                .overrideConfiguration(overrideConfig.build())
                .region(Region.US_EAST_1)
                .build();
    }
```

------
#### [  Go  ]

```
tr := &http.Transport{
        ResponseHeaderTimeout: 20 * time.Second,
        // Using DefaultTransport values for other parameters: https://golang.org/pkg/net/http/#RoundTripper
        Proxy: http.ProxyFromEnvironment,
        DialContext: (&net.Dialer{
            KeepAlive: 30 * time.Second,
            DualStack: true,
            Timeout:   30 * time.Second,
        }).DialContext,
        MaxIdleConns:          100,
        IdleConnTimeout:       90 * time.Second,
        TLSHandshakeTimeout:   10 * time.Second,
        ExpectContinueTimeout: 1 * time.Second,
    }

    // So client makes HTTP/2 requests
    http2.ConfigureTransport(tr)

    sess, err := session.NewSession(&aws.Config{ Region: aws.String("us-east-1"), MaxRetries: aws.Int(10), HTTPClient: &http.Client{ Transport: tr }})
    writeSvc := timestreamwrite.New(sess)
```

------
#### [  Python  ]

```
write_client = session.client('timestream-write', config=Config(read_timeout=20, max_pool_connections = 5000, retries={'max_attempts': 10})) 
```

------
#### [  Node.js  ]

The following snippet uses AWS SDK for JavaScript v3. For more information about how to install the client and usage, see [Timestream Write Client - AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/index.html).

An additional command import is shown here. The `CreateDatabaseCommand` import is not required to create the client.

```
import { TimestreamWriteClient, CreateDatabaseCommand } from "@aws-sdk/client-timestream-write";
const writeClient = new TimestreamWriteClient({ region: "us-east-1" });
```

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
var https = require('https');
var agent = new https.Agent({
    maxSockets: 5000
});
writeClient = new AWS.TimestreamWrite({
        maxRetries: 10,
        httpOptions: {
            timeout: 20000,
            agent: agent
        }
    });
```

------
#### [  .NET  ]

```
var writeClientConfig = new AmazonTimestreamWriteConfig
{
    RegionEndpoint = RegionEndpoint.USEast1,
    Timeout = TimeSpan.FromSeconds(20),
    MaxErrorRetry = 10
};

var writeClient = new AmazonTimestreamWriteClient(writeClientConfig);
```

------

We recommend you use the following configuration.
+ Set the SDK retry count to `10`.
+ Use `SDK DEFAULT_BACKOFF_STRATEGY`.
+ Set `RequestTimeout` to `20` seconds.
+ Set the max connections to `5000` or higher.

# Query SDK client
<a name="code-samples.query-client"></a>

You can use the following code snippets to create a Timestream client for the Query SDK. The Query SDK is used to query your existing time series data stored in Timestream.

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
    private static AmazonTimestreamQuery buildQueryClient() {
        AmazonTimestreamQuery client = AmazonTimestreamQueryClient.builder().withRegion("us-east-1").build();
        return client;
    }
```

------
#### [  Java v2  ]

```
    private static TimestreamQueryClient buildQueryClient() {
        return TimestreamQueryClient.builder()
                .region(Region.US_EAST_1)
                .build();
    }
```

------
#### [  Go  ]

```
sess, err := session.NewSession(&aws.Config{Region: aws.String("us-east-1")})
```

------
#### [  Python  ]

```
query_client = session.client('timestream-query')
```

------
#### [  Node.js  ]

The following snippet uses AWS SDK for JavaScript v3. For more information about how to install the client and usage, see [Timestream Query Client - ,AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-query/index.html).

An additional command import is shown here. The `QueryCommand` import is not required to create the client.

```
import { TimestreamQueryClient, QueryCommand } from "@aws-sdk/client-timestream-query";
const queryClient = new TimestreamQueryClient({ region: "us-east-1" });
```

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
queryClient = new AWS.TimestreamQuery();
```

------
#### [  .NET  ]

```
var queryClientConfig = new AmazonTimestreamQueryConfig 
{ 
    RegionEndpoint = RegionEndpoint.USEast1 
}; 

var queryClient = new AmazonTimestreamQueryClient(queryClientConfig);
```

------

# Create database
<a name="code-samples.create-db"></a>

You can use the following code snippets to create a database.

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
   public void createDatabase() {
        System.out.println("Creating database");
        CreateDatabaseRequest request = new CreateDatabaseRequest();
        request.setDatabaseName(DATABASE_NAME);
        try {
            amazonTimestreamWrite.createDatabase(request);
            System.out.println("Database [" + DATABASE_NAME + "] created successfully");
        } catch (ConflictException e) {
            System.out.println("Database [" + DATABASE_NAME + "] exists. Skipping database creation");
        }
    }
```

------
#### [  Java v2  ]

```
    public void createDatabase() {
        System.out.println("Creating database");
        CreateDatabaseRequest request = CreateDatabaseRequest.builder().databaseName(DATABASE_NAME).build();
        try {
            timestreamWriteClient.createDatabase(request);
            System.out.println("Database [" + DATABASE_NAME + "] created successfully");
        } catch (ConflictException e) {
            System.out.println("Database [" + DATABASE_NAME + "] exists. Skipping database creation");
        }
    }
```

------
#### [  Go  ]

```
// Create database.
    createDatabaseInput := &timestreamwrite.CreateDatabaseInput{
        DatabaseName: aws.String(*databaseName),
    }

    _, err = writeSvc.CreateDatabase(createDatabaseInput)

    if err != nil {
        fmt.Println("Error:")
        fmt.Println(err)
    } else {
        fmt.Println("Database successfully created")
    }

    fmt.Println("Describing the database, hit enter to continue")
```

------
#### [  Python  ]

```
    def create_database(self):
        print("Creating Database")
        try:
            self.client.create_database(DatabaseName=Constant.DATABASE_NAME)
            print("Database [%s] created successfully." % Constant.DATABASE_NAME)
        except self.client.exceptions.ConflictException:
            print("Database [%s] exists. Skipping database creation" % Constant.DATABASE_NAME)
        except Exception as err:
            print("Create database failed:", err)
```

------
#### [  Node.js  ]

The following snippet uses AWS SDK for JavaScript v3. For more information about how to install the client and usage, see [Timestream Write Client - AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/index.html).

Also see [Class CreateDatabaseCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/classes/createdatabasecommand.html) and [CreateDatabase](https://docs.aws.amazon.com/timestream/latest/developerguide/API_CreateDatabase.html).

```
import { TimestreamWriteClient, CreateDatabaseCommand } from "@aws-sdk/client-timestream-write";
const writeClient = new TimestreamWriteClient({ region: "us-east-1" });

const params = {
    DatabaseName: "testDbFromNode"
};

const command = new CreateDatabaseCommand(params);

try {
    const data = await writeClient.send(command);
    console.log(`Database ${data.Database.DatabaseName} created successfully`);
} catch (error) {
    if (error.code === 'ConflictException') {
        console.log(`Database ${params.DatabaseName} already exists. Skipping creation.`);
    } else {
        console.log("Error creating database", error);
    }
}
```

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
async function createDatabase() {
    console.log("Creating Database");
    const params = {
        DatabaseName: constants.DATABASE_NAME
    };
 
    const promise = writeClient.createDatabase(params).promise();
 
    await promise.then(
        (data) => {
            console.log(`Database ${data.Database.DatabaseName} created successfully`);
        },
        (err) => {
            if (err.code === 'ConflictException') {
                console.log(`Database ${params.DatabaseName} already exists. Skipping creation.`);
            } else {
                console.log("Error creating database", err);
            }
        }
    );
}
```

------
#### [  .NET  ]

```
        public async Task CreateDatabase()
        {
            Console.WriteLine("Creating Database");

            try
            {
                var createDatabaseRequest = new CreateDatabaseRequest
                {
                    DatabaseName = Constants.DATABASE_NAME
                };
                CreateDatabaseResponse response = await writeClient.CreateDatabaseAsync(createDatabaseRequest);
                Console.WriteLine($"Database {Constants.DATABASE_NAME} created");
            }
            catch (ConflictException)
            {
                Console.WriteLine("Database already exists.");
            }
            catch (Exception e)
            {
                Console.WriteLine("Create database failed:" + e.ToString());
            }

        }
```

------

# Describe database
<a name="code-samples.describe-db"></a>

You can use the following code snippets to get information about the attributes of your newly created database.

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
    public void describeDatabase() {
        System.out.println("Describing database");
        final DescribeDatabaseRequest describeDatabaseRequest = new DescribeDatabaseRequest();
        describeDatabaseRequest.setDatabaseName(DATABASE_NAME);
        try {
            DescribeDatabaseResult result = amazonTimestreamWrite.describeDatabase(describeDatabaseRequest);
            final Database databaseRecord = result.getDatabase();
            final String databaseId = databaseRecord.getArn();
            System.out.println("Database " + DATABASE_NAME + " has id " + databaseId);
        } catch (final Exception e) {
            System.out.println("Database doesn't exist = " + e);
            throw e;
        }
    }
```

------
#### [  Java v2  ]

```
    public void describeDatabase() {
        System.out.println("Describing database");
        final DescribeDatabaseRequest describeDatabaseRequest = DescribeDatabaseRequest.builder()
                .databaseName(DATABASE_NAME).build();
        try {
            DescribeDatabaseResponse response = timestreamWriteClient.describeDatabase(describeDatabaseRequest);
            final Database databaseRecord = response.database();
            final String databaseId = databaseRecord.arn();
            System.out.println("Database " + DATABASE_NAME + " has id " + databaseId);
        } catch (final Exception e) {
            System.out.println("Database doesn't exist = " + e);
            throw e;
        }
    }
```

------
#### [  Go  ]

```
describeDatabaseOutput, err := writeSvc.DescribeDatabase(describeDatabaseInput)

    if err != nil {
        fmt.Println("Error:")
        fmt.Println(err)
    } else {
        fmt.Println("Describe database is successful, below is the output:")
        fmt.Println(describeDatabaseOutput)
    }
```

------
#### [  Python  ]

```
    def describe_database(self):
        print("Describing database")
        try:
            result = self.client.describe_database(DatabaseName=Constant.DATABASE_NAME)
            print("Database [%s] has id [%s]" % (Constant.DATABASE_NAME, result['Database']['Arn']))
        except self.client.exceptions.ResourceNotFoundException:
            print("Database doesn't exist")
        except Exception as err:
            print("Describe database failed:", err)
```

------
#### [  Node.js  ]

The following snippet uses AWS SDK for JavaScript v3. For more information about how to install the client and usage, see [Timestream Write Client - AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/index.html).

Also see [Class DescribeDatabaseCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/classes/describedatabasecommand.html) and [DescribeDatabase](https://docs.aws.amazon.com/timestream/latest/developerguide/API_DescribeDatabase.html).

```
import { TimestreamWriteClient, DescribeDatabaseCommand } from "@aws-sdk/client-timestream-write";
const writeClient = new TimestreamWriteClient({ region: "us-east-1" });

const params = {
    DatabaseName: "testDbFromNode"
};

const command = new DescribeDatabaseCommand(params);

try {
    const data = await writeClient.send(command);
    console.log(`Database ${data.Database.DatabaseName} has id ${data.Database.Arn}`);
} catch (error) {
    if (error.code === 'ResourceNotFoundException') {
        console.log("Database doesn't exist.");
    } else {
        console.log("Describe database failed.", error);
        throw error;
    }
}
```

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
async function describeDatabase () {
    console.log("Describing Database");
    const params = {
        DatabaseName: constants.DATABASE_NAME
    };
 
    const promise = writeClient.describeDatabase(params).promise();
 
    await promise.then(
        (data) => {
            console.log(`Database ${data.Database.DatabaseName} has id ${data.Database.Arn}`);
        },
        (err) => {
            if (err.code === 'ResourceNotFoundException') {
                console.log("Database doesn't exist.");
            } else {
                console.log("Describe database failed.", err);
                throw err;
            }
        }
    );
}
```

------
#### [  .NET  ]

```
        public async Task DescribeDatabase()
        {
            Console.WriteLine("Describing Database");

            try
            {
                var describeDatabaseRequest = new DescribeDatabaseRequest
                {
                    DatabaseName = Constants.DATABASE_NAME
                };
                DescribeDatabaseResponse response = await writeClient.DescribeDatabaseAsync(describeDatabaseRequest);
                Console.WriteLine($"Database {Constants.DATABASE_NAME} has id:{response.Database.Arn}");
            }
            catch (ResourceNotFoundException)
            {
                Console.WriteLine("Database does not exist.");
            }
            catch (Exception e)
            {
                Console.WriteLine("Describe database failed:" + e.ToString());
            }

        }
```

------

# Update database
<a name="code-samples.update-db"></a>

You can use the following code snippets to update your databases.

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
    public void updateDatabase(String kmsId) {
        System.out.println("Updating kmsId to " + kmsId);
        UpdateDatabaseRequest request = new UpdateDatabaseRequest();
        request.setDatabaseName(DATABASE_NAME);
        request.setKmsKeyId(kmsId);
        try {
            UpdateDatabaseResult result = amazonTimestreamWrite.updateDatabase(request);
            System.out.println("Update Database complete");
        } catch (final ValidationException e) {
            System.out.println("Update database failed:");
            e.printStackTrace();
        } catch (final ResourceNotFoundException e) {
            System.out.println("Database " + DATABASE_NAME + " doesn't exist = " + e);
        } catch (final Exception e) {
            System.out.println("Could not update Database " + DATABASE_NAME + " = " + e);
            throw e;
        }
    }
```

------
#### [  Java v2  ]

```
    public void updateDatabase(String kmsKeyId) {

        if (kmsKeyId == null) {
            System.out.println("Skipping UpdateDatabase because KmsKeyId was not given");
            return;
        }

        System.out.println("Updating database");

        UpdateDatabaseRequest request = UpdateDatabaseRequest.builder()
                .databaseName(DATABASE_NAME)
                .kmsKeyId(kmsKeyId)
                .build();
        try {
            timestreamWriteClient.updateDatabase(request);
            System.out.println("Database [" + DATABASE_NAME + "] updated successfully with kmsKeyId " + kmsKeyId);
        } catch (ResourceNotFoundException e) {
            System.out.println("Database [" + DATABASE_NAME + "] does not exist. Skipping UpdateDatabase");
        } catch (Exception e) {
            System.out.println("UpdateDatabase failed: " + e);
        }
    }
```

------
#### [  Go  ]

```
// Update Database.
        updateDatabaseInput := &timestreamwrite.UpdateDatabaseInput {
            DatabaseName: aws.String(*databaseName),
            KmsKeyId: aws.String(*kmsKeyId),
        }

        updateDatabaseOutput, err := writeSvc.UpdateDatabase(updateDatabaseInput)

        if err != nil {
            fmt.Println("Error:")
            fmt.Println(err)
        } else {
            fmt.Println("Update database is successful, below is the output:")
            fmt.Println(updateDatabaseOutput)
        }
```

------
#### [  Python  ]

```
    def update_database(self, kms_id):
        print("Updating database")
        try:
            result = self.client.update_database(DatabaseName=Constant.DATABASE_NAME, KmsKeyId=kms_id)
            print("Database [%s] was updated to use kms [%s] successfully" % (Constant.DATABASE_NAME,
                                                                              result['Database']['KmsKeyId']))
        except self.client.exceptions.ResourceNotFoundException:
            print("Database doesn't exist")
        except Exception as err:
            print("Update database failed:", err)
```

------
#### [  Node.js  ]

The following snippet uses AWS SDK for JavaScript v3. For more information about how to install the client and usage, see [Timestream Write Client - AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/index.html).

Also see [Class UpdateDatabaseCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/classes/updatedatabasecommand.html) and [UpdateDatabase](https://docs.aws.amazon.com/timestream/latest/developerguide/API_UpdateDatabase.html).

```
import { TimestreamWriteClient, UpdateDatabaseCommand } from "@aws-sdk/client-timestream-write";
const writeClient = new TimestreamWriteClient({ region: "us-east-1" });
let updatedKmsKeyId = "<updatedKmsKeyId>";

const params = {
    DatabaseName: "testDbFromNode",
    KmsKeyId: updatedKmsKeyId
};

const command = new UpdateDatabaseCommand(params);

try {
    const data = await writeClient.send(command);
    console.log(`Database ${data.Database.DatabaseName} updated kmsKeyId to ${updatedKmsKeyId}`);
} catch (error) {
    if (error.code === 'ResourceNotFoundException') {
        console.log("Database doesn't exist.");
    } else {
        console.log("Update database failed.", error);
    }
}
```

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
async function updateDatabase(updatedKmsKeyId) { 
 
    if (updatedKmsKeyId === undefined) { 
        console.log("Skipping UpdateDatabase; KmsKeyId was not given"); 
        return; 
    } 
    console.log("Updating Database"); 
    const params = { 
        DatabaseName: constants.DATABASE_NAME, 
        KmsKeyId: updatedKmsKeyId 
    } 
 
    const promise = writeClient.updateDatabase(params).promise(); 
 
    await promise.then( 
        (data) => { 
            console.log(`Database ${data.Database.DatabaseName} updated kmsKeyId to ${updatedKmsKeyId}`); 
        }, 
        (err) => { 
            if (err.code === 'ResourceNotFoundException') { 
                console.log("Database doesn't exist."); 
            } else { 
                console.log("Update database failed.", err); 
            } 
        } 
    ); 
}
```

------
#### [  .NET  ]

```
        public async Task UpdateDatabase(String updatedKmsKeyId)
        {
            Console.WriteLine("Updating Database");

            try
            {
                var updateDatabaseRequest = new UpdateDatabaseRequest
                {
                    DatabaseName = Constants.DATABASE_NAME,
                    KmsKeyId = updatedKmsKeyId
                };
                UpdateDatabaseResponse response = await writeClient.UpdateDatabaseAsync(updateDatabaseRequest);
                Console.WriteLine($"Database {Constants.DATABASE_NAME} updated with KmsKeyId {updatedKmsKeyId}");
            }
            catch (ResourceNotFoundException)
            {
                Console.WriteLine("Database does not exist.");
            }
            catch (Exception e)
            {
                Console.WriteLine("Update database failed: " + e.ToString());
            }

        }
                
        private void PrintDatabases(List<Database> databases)
        {
            foreach (Database database in databases)
                Console.WriteLine($"Database:{database.DatabaseName}");
        }
```

------

# Delete database
<a name="code-samples.delete-db"></a>

You can use the following code snippet to delete a database.

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
    public void deleteDatabase() {
        System.out.println("Deleting database");
        final DeleteDatabaseRequest deleteDatabaseRequest = new DeleteDatabaseRequest();
        deleteDatabaseRequest.setDatabaseName(DATABASE_NAME);
        try {
            DeleteDatabaseResult result =
                    amazonTimestreamWrite.deleteDatabase(deleteDatabaseRequest);
            System.out.println("Delete database status: " + result.getSdkHttpMetadata().getHttpStatusCode());
        } catch (final ResourceNotFoundException e) {
            System.out.println("Database " + DATABASE_NAME + " doesn't exist = " + e);
            throw e;
        } catch (final Exception e) {
            System.out.println("Could not delete Database " + DATABASE_NAME + " = " + e);
            throw e;
        }
    }
```

------
#### [  Java v2  ]

```
    public void deleteDatabase() {
        System.out.println("Deleting database");
        final DeleteDatabaseRequest deleteDatabaseRequest = new DeleteDatabaseRequest();
        deleteDatabaseRequest.setDatabaseName(DATABASE_NAME);
        try {
            DeleteDatabaseResult result =
                    amazonTimestreamWrite.deleteDatabase(deleteDatabaseRequest);
            System.out.println("Delete database status: " + result.getSdkHttpMetadata().getHttpStatusCode());
        } catch (final ResourceNotFoundException e) {
            System.out.println("Database " + DATABASE_NAME + " doesn't exist = " + e);
            throw e;
        } catch (final Exception e) {
            System.out.println("Could not delete Database " + DATABASE_NAME + " = " + e);
            throw e;
        }
    }
```

------
#### [  Go  ]

```
deleteDatabaseInput := &timestreamwrite.DeleteDatabaseInput{
        DatabaseName:   aws.String(*databaseName),
    }

    _, err = writeSvc.DeleteDatabase(deleteDatabaseInput)

    if err != nil {
        fmt.Println("Error:")
        fmt.Println(err)
    } else {
        fmt.Println("Database deleted:", *databaseName)
    }
```

------
#### [  Python  ]

```
    def delete_database(self):
        print("Deleting Database")
        try:
            result = self.client.delete_database(DatabaseName=Constant.DATABASE_NAME)
            print("Delete database status [%s]" % result['ResponseMetadata']['HTTPStatusCode'])
        except self.client.exceptions.ResourceNotFoundException:
            print("database [%s] doesn't exist" % Constant.DATABASE_NAME)
        except Exception as err:
            print("Delete database failed:", err)
```

------
#### [  Node.js  ]

The following snippet uses AWS SDK for JavaScript v3. For more information about how to install the client and usage, see [Timestream Write Client - AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/index.html).

Also see [Class DeleteDatabaseCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/classes/deletedatabasecommand.html) and [DeleteDatabase](https://docs.aws.amazon.com/timestream/latest/developerguide/API_DeleteDatabase.html).

```
import { TimestreamWriteClient, DeleteDatabaseCommand } from "@aws-sdk/client-timestream-write";
const writeClient = new TimestreamWriteClient({ region: "us-east-1" });

const params = {
    DatabaseName: "testDbFromNode"
};

const command = new DeleteDatabaseCommand(params);

try {
    const data = await writeClient.send(command);
    console.log("Deleted database"); 
} catch (error) {
    if (error.code === 'ResourceNotFoundException') { 
        console.log(`Database ${params.DatabaseName} doesn't exists.`); 
    } else { 
        console.log("Delete database failed.", error); 
        throw error; 
    } 
}
```

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
async function deleteDatabase() { 
    console.log("Deleting Database"); 
    const params = { 
        DatabaseName: constants.DATABASE_NAME 
    }; 
 
    const promise = writeClient.deleteDatabase(params).promise(); 
 
    await promise.then( 
        function (data) { 
            console.log("Deleted database"); 
         }, 
        function(err) { 
            if (err.code === 'ResourceNotFoundException') { 
                console.log(`Database ${params.DatabaseName} doesn't exists.`); 
            } else { 
                console.log("Delete database failed.", err); 
                throw err; 
            } 
        } 
    ); 
}
```

------
#### [  .NET  ]

```
        public async Task DeleteDatabase()
        {
            Console.WriteLine("Deleting database");
            try
            {
                var deleteDatabaseRequest = new DeleteDatabaseRequest
                {
                    DatabaseName = Constants.DATABASE_NAME
                };
                DeleteDatabaseResponse response = await writeClient.DeleteDatabaseAsync(deleteDatabaseRequest);
                Console.WriteLine($"Database {Constants.DATABASE_NAME} delete request status:{response.HttpStatusCode}");
            }
            catch (ResourceNotFoundException)
            {
                Console.WriteLine($"Database {Constants.DATABASE_NAME} does not exists");
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception while deleting database:" + e.ToString());
            }
        }
```

------

# List databases
<a name="code-samples.list-db"></a>

You can use the following code snippets to list your databases.

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
    public void listDatabases() {
        System.out.println("Listing databases");
        ListDatabasesRequest request = new ListDatabasesRequest();
        ListDatabasesResult result = amazonTimestreamWrite.listDatabases(request);
        final List<Database> databases = result.getDatabases();
        printDatabases(databases);

        String nextToken = result.getNextToken();
        while (nextToken != null && !nextToken.isEmpty()) {
            request.setNextToken(nextToken);
            ListDatabasesResult nextResult = amazonTimestreamWrite.listDatabases(request);
            final List<Database> nextDatabases = nextResult.getDatabases();
            printDatabases(nextDatabases);
            nextToken = nextResult.getNextToken();
        }
    }
    
    private void printDatabases(List<Database> databases) {
        for (Database db : databases) {
            System.out.println(db.getDatabaseName());
        }
    }
```

------
#### [  Java v2  ]

```
    public void listDatabases() {
        System.out.println("Listing databases");
        ListDatabasesRequest request = ListDatabasesRequest.builder().maxResults(2).build();
        ListDatabasesIterable listDatabasesIterable = timestreamWriteClient.listDatabasesPaginator(request);
        for(ListDatabasesResponse listDatabasesResponse : listDatabasesIterable) {
            final List<Database> databases = listDatabasesResponse.databases();
            databases.forEach(database -> System.out.println(database.databaseName()));
        }
    }
```

------
#### [  Go  ]

```
// List databases.
    listDatabasesMaxResult := int64(15)

    listDatabasesInput := &timestreamwrite.ListDatabasesInput{
        MaxResults: &listDatabasesMaxResult,
    }

    listDatabasesOutput, err := writeSvc.ListDatabases(listDatabasesInput)

    if err != nil {
        fmt.Println("Error:")
        fmt.Println(err)
    } else {
        fmt.Println("List databases is successful, below is the output:")
        fmt.Println(listDatabasesOutput)
    }
```

------
#### [  Python  ]

```
    def list_databases(self):
        print("Listing databases")
        try:
            result = self.client.list_databases(MaxResults=5)
            self._print_databases(result['Databases'])
            next_token = result.get('NextToken', None)
            while next_token:
                result = self.client.list_databases(NextToken=next_token, MaxResults=5)
                self._print_databases(result['Databases'])
                next_token = result.get('NextToken', None)
        except Exception as err:
            print("List databases failed:", err)
```

------
#### [  Node.js  ]

The following snippet uses AWS SDK for JavaScript v3. For more information about how to install the client and usage, see [Timestream Write Client - AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/index.html).

Also see [Class ListDatabasesCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/classes/listdatabasescommand.html) and [ListDatabases](https://docs.aws.amazon.com/timestream/latest/developerguide/API_ListDatabases.html).

```
import { TimestreamWriteClient, ListDatabasesCommand } from "@aws-sdk/client-timestream-write";
const writeClient = new TimestreamWriteClient({ region: "us-east-1" });

const params = {
    MaxResults: 15
};

const command = new ListDatabasesCommand(params);

getDatabasesList(null);

async function getDatabasesList(nextToken) {
    if (nextToken) {
        params.NextToken = nextToken;
    }

    try {
        const data = await writeClient.send(command);

        data.Databases.forEach(function (database) {
            console.log(database.DatabaseName);
        });

        if (data.NextToken) {
            return getDatabasesList(data.NextToken);
        }
    } catch (error) {
        console.log("Error while listing databases", error);
    }
}
```

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
async function listDatabases() {
    console.log("Listing databases:");
    const databases = await getDatabasesList(null);
    databases.forEach(function(database){
        console.log(database.DatabaseName);
    });
}

function getDatabasesList(nextToken, databases = []) {
    var params = {
        MaxResults: 15
    };

    if(nextToken) {
        params.NextToken = nextToken;
    }

    return writeClient.listDatabases(params).promise()
        .then(
            (data) => {
                databases.push.apply(databases, data.Databases);
                if (data.NextToken) {
                    return getDatabasesList(data.NextToken, databases);
                } else {
                    return databases;
                }
            },
            (err) => {
                console.log("Error while listing databases", err);
            });
}
```

------
#### [  .NET  ]

```
        public async Task ListDatabases()
        {
            Console.WriteLine("Listing Databases");

            try
            {
                var listDatabasesRequest = new ListDatabasesRequest
                {
                    MaxResults = 5
                };
                ListDatabasesResponse response = await writeClient.ListDatabasesAsync(listDatabasesRequest);
                PrintDatabases(response.Databases);
                var nextToken = response.NextToken;
                while (nextToken != null)
                {
                    listDatabasesRequest.NextToken = nextToken;
                    response = await writeClient.ListDatabasesAsync(listDatabasesRequest);
                    PrintDatabases(response.Databases);
                    nextToken = response.NextToken;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("List database failed:" + e.ToString());
            }

        }
```

------

# Create table
<a name="code-samples.create-table"></a>

**Topics**
+ [Memory store writes](#code-samples.create-table-memorystore)
+ [Magnetic store writes](#code-samples.create-table-magneticstore)

## Memory store writes
<a name="code-samples.create-table-memorystore"></a>

You can use the following code snippet to create a table that has magnetic store writes disabled, as a result you can only write data into your memory store retention window.

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
    public void createTable() {
        System.out.println("Creating table");
        CreateTableRequest createTableRequest = new CreateTableRequest();
        createTableRequest.setDatabaseName(DATABASE_NAME);
        createTableRequest.setTableName(TABLE_NAME);
        final RetentionProperties retentionProperties = new RetentionProperties()
                .withMemoryStoreRetentionPeriodInHours(HT_TTL_HOURS)
                .withMagneticStoreRetentionPeriodInDays(CT_TTL_DAYS);
        createTableRequest.setRetentionProperties(retentionProperties);

        try {
            amazonTimestreamWrite.createTable(createTableRequest);
            System.out.println("Table [" + TABLE_NAME + "] successfully created.");
        } catch (ConflictException e) {
            System.out.println("Table [" + TABLE_NAME + "] exists on database [" + DATABASE_NAME + "] . Skipping database creation");
        }
    }
```

------
#### [  Java v2  ]

```
    public void createTable() {
        System.out.println("Creating table");

        final RetentionProperties retentionProperties = RetentionProperties.builder()
                .memoryStoreRetentionPeriodInHours(HT_TTL_HOURS)
                .magneticStoreRetentionPeriodInDays(CT_TTL_DAYS).build();
        final CreateTableRequest createTableRequest = CreateTableRequest.builder()
                .databaseName(DATABASE_NAME).tableName(TABLE_NAME).retentionProperties(retentionProperties).build();

        try {
            timestreamWriteClient.createTable(createTableRequest);
            System.out.println("Table [" + TABLE_NAME + "] successfully created.");
        } catch (ConflictException e) {
            System.out.println("Table [" + TABLE_NAME + "] exists on database [" + DATABASE_NAME + "] . Skipping database creation");
        }
    }
```

------
#### [  Go  ]

```
// Create table.
    createTableInput := &timestreamwrite.CreateTableInput{
        DatabaseName: aws.String(*databaseName),
        TableName:    aws.String(*tableName),
    }
    _, err = writeSvc.CreateTable(createTableInput)

    if err != nil {
        fmt.Println("Error:")
        fmt.Println(err)
    } else {
        fmt.Println("Create table is successful")
    }
```

------
#### [  Python  ]

```
    def create_table(self):
        print("Creating table")
        retention_properties = {
            'MemoryStoreRetentionPeriodInHours': Constant.HT_TTL_HOURS,
            'MagneticStoreRetentionPeriodInDays': Constant.CT_TTL_DAYS
        }
        try:
            self.client.create_table(DatabaseName=Constant.DATABASE_NAME, TableName=Constant.TABLE_NAME,
                                     RetentionProperties=retention_properties)
            print("Table [%s] successfully created." % Constant.TABLE_NAME)
        except self.client.exceptions.ConflictException:
            print("Table [%s] exists on database [%s]. Skipping table creation" % (
                Constant.TABLE_NAME, Constant.DATABASE_NAME))
        except Exception as err:
            print("Create table failed:", err)
```

------
#### [  Node.js  ]

The following snippet uses AWS SDK for JavaScript v3. For more information about how to install the client and usage, see [Timestream Write Client - AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/index.html).

Also see [Class CreateTableCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/classes/createtablecommand.html) and [CreateTable](https://docs.aws.amazon.com/timestream/latest/developerguide/API_CreateTable.html).

```
import { TimestreamWriteClient, CreateTableCommand } from "@aws-sdk/client-timestream-write";
const writeClient = new TimestreamWriteClient({ region: "us-east-1" });

const params = {
    DatabaseName: "testDbFromNode",
    TableName: "testTableFromNode",
    RetentionProperties: {
        MemoryStoreRetentionPeriodInHours: 24,
        MagneticStoreRetentionPeriodInDays: 365
    }
};

const command = new CreateTableCommand(params);

try {
    const data = await writeClient.send(command);
    console.log(`Table ${data.Table.TableName} created successfully`);
} catch (error) {
    if (error.code === 'ConflictException') {
        console.log(`Table ${params.TableName} already exists on db ${params.DatabaseName}. Skipping creation.`);
    } else {
        console.log("Error creating table. ", error);
        throw error;
    }
}
```

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
async function createTable() {
    console.log("Creating Table");
    const params = {
        DatabaseName: constants.DATABASE_NAME,
        TableName: constants.TABLE_NAME,
        RetentionProperties: {
            MemoryStoreRetentionPeriodInHours: constants.HT_TTL_HOURS,
            MagneticStoreRetentionPeriodInDays: constants.CT_TTL_DAYS
        }
    };

    const promise = writeClient.createTable(params).promise();

    await promise.then(
        (data) => {
            console.log(`Table ${data.Table.TableName} created successfully`);
        },
        (err) => {
            if (err.code === 'ConflictException') {
                console.log(`Table ${params.TableName} already exists on db ${params.DatabaseName}. Skipping creation.`);
            } else {
                console.log("Error creating table. ", err);
                throw err;
            }
        }
    );
}
```

------
#### [  .NET  ]

```
        public async Task CreateTable()
        {
            Console.WriteLine("Creating Table");

            try
            {
                var createTableRequest = new CreateTableRequest
                {
                    DatabaseName = Constants.DATABASE_NAME,
                    TableName = Constants.TABLE_NAME,
                    RetentionProperties = new RetentionProperties
                    {
                        MagneticStoreRetentionPeriodInDays = Constants.CT_TTL_DAYS,
                        MemoryStoreRetentionPeriodInHours = Constants.HT_TTL_HOURS
                    }
                };
                CreateTableResponse response = await writeClient.CreateTableAsync(createTableRequest);
                Console.WriteLine($"Table {Constants.TABLE_NAME} created");
            }
            catch (ConflictException)
            {
                Console.WriteLine("Table already exists.");
            }
            catch (Exception e)
            {
                Console.WriteLine("Create table failed:" + e.ToString());
            }

        }
```

------

## Magnetic store writes
<a name="code-samples.create-table-magneticstore"></a>

You can use the following code snippet to create a table with magnetic store writes enabled. With magnetic store writes you can write data into both your memory store retention window and magnetic store retention window.

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
    public void createTable(String databaseName, String tableName) {
        System.out.println("Creating table");
        CreateTableRequest createTableRequest = new CreateTableRequest();
        createTableRequest.setDatabaseName(databaseName);
        createTableRequest.setTableName(tableName);
        final RetentionProperties retentionProperties = new RetentionProperties()
                .withMemoryStoreRetentionPeriodInHours(HT_TTL_HOURS)
                .withMagneticStoreRetentionPeriodInDays(CT_TTL_DAYS);
        createTableRequest.setRetentionProperties(retentionProperties);
        // Enable MagneticStoreWrite
        final MagneticStoreWriteProperties magneticStoreWriteProperties = new MagneticStoreWriteProperties()
                .withEnableMagneticStoreWrites(true);
        createTableRequest.setMagneticStoreWriteProperties(magneticStoreWriteProperties);
        try {
            amazonTimestreamWrite.createTable(createTableRequest);
            System.out.println("Table [" + tableName + "] successfully created.");
        } catch (ConflictException e) {
            System.out.println("Table [" + tableName + "] exists on database [" + databaseName + "] . Skipping table creation");
            //We do not throw exception here, we use the existing table instead
        }
    }
```

------
#### [  Java v2  ]

```
    public void createTable(String databaseName, String tableName) {
        System.out.println("Creating table");

        // Enable MagneticStoreWrite
        final MagneticStoreWriteProperties magneticStoreWriteProperties =
                MagneticStoreWriteProperties.builder()
                        .enableMagneticStoreWrites(true)
                        .build();

        CreateTableRequest createTableRequest =
                CreateTableRequest.builder()
                        .databaseName(databaseName)
                        .tableName(tableName)
                        .retentionProperties(RetentionProperties.builder()
                                .memoryStoreRetentionPeriodInHours(HT_TTL_HOURS)
                                .magneticStoreRetentionPeriodInDays(CT_TTL_DAYS)
                                .build())
                        .magneticStoreWriteProperties(magneticStoreWriteProperties)
                        .build();
        try {
            timestreamWriteClient.createTable(createTableRequest);
            System.out.println("Table [" + tableName + "] successfully created.");
        } catch (ConflictException e) {
            System.out.println("Table [" + tableName + "] exists in database [" + databaseName + "] . Skipping table creation");
        }
    }
```

------
#### [  Go  ]

```
// Create table.
    createTableInput := &timestreamwrite.CreateTableInput{
        DatabaseName: aws.String(*databaseName),
        TableName:    aws.String(*tableName),
    // Enable MagneticStoreWrite
        MagneticStoreWriteProperties: &timestreamwrite.MagneticStoreWriteProperties{
            EnableMagneticStoreWrites: aws.Bool(true),
             },
      }
    _, err = writeSvc.CreateTable(createTableInput)
```

------
#### [  Python  ]

```
    def create_table(self):
        print("Creating table")
        retention_properties = {
            'MemoryStoreRetentionPeriodInHours': Constant.HT_TTL_HOURS,
            'MagneticStoreRetentionPeriodInDays': Constant.CT_TTL_DAYS
        }
        magnetic_store_write_properties = {
            'EnableMagneticStoreWrites': True
        }
        try:
            self.client.create_table(DatabaseName=Constant.DATABASE_NAME, TableName=Constant.TABLE_NAME,
                                     RetentionProperties=retention_properties,
                                     MagneticStoreWriteProperties=magnetic_store_write_properties)
            print("Table [%s] successfully created." % Constant.TABLE_NAME)
        except self.client.exceptions.ConflictException:
            print("Table [%s] exists on database [%s]. Skipping table creation" % (
                Constant.TABLE_NAME, Constant.DATABASE_NAME))
        except Exception as err:
            print("Create table failed:", err)
```

------
#### [  Node.js  ]

```
async function createTable() {
    console.log("Creating Table");

    const params = {
        DatabaseName: constants.DATABASE_NAME,
        TableName: constants.TABLE_NAME,
        RetentionProperties: {
            MemoryStoreRetentionPeriodInHours: constants.HT_TTL_HOURS,
            MagneticStoreRetentionPeriodInDays: constants.CT_TTL_DAYS
        },
        MagneticStoreWriteProperties: {
            EnableMagneticStoreWrites: true
        }
    };

    const promise = writeClient.createTable(params).promise();

    await promise.then(
        (data) => {
            console.log(`Table ${data.Table.TableName} created successfully`);
        },
        (err) => {
            if (err.code === 'ConflictException') {
                console.log(`Table ${params.TableName} already exists on db ${params.DatabaseName}. Skipping creation.`);
            } else {
                console.log("Error creating table. ", err);
                throw err;
            }
        }
    );
}
```

------
#### [  .NET  ]

```
        public async Task CreateTable()
        {
            Console.WriteLine("Creating Table");

            try
            {
                var createTableRequest = new CreateTableRequest
                {
                    DatabaseName = Constants.DATABASE_NAME,
                    TableName = Constants.TABLE_NAME,
                    RetentionProperties = new RetentionProperties
                    {
                        MagneticStoreRetentionPeriodInDays = Constants.CT_TTL_DAYS,
                        MemoryStoreRetentionPeriodInHours = Constants.HT_TTL_HOURS
                    },
                    // Enable MagneticStoreWrite
                    MagneticStoreWriteProperties = new MagneticStoreWriteProperties 
                    {
                        EnableMagneticStoreWrites = true,
                    }
                };
                CreateTableResponse response = await writeClient.CreateTableAsync(createTableRequest);
                Console.WriteLine($"Table {Constants.TABLE_NAME} created");
            }
            catch (ConflictException)
            {
                Console.WriteLine("Table already exists.");
            }
            catch (Exception e)
            {
                Console.WriteLine("Create table failed:" + e.ToString());
            }

        }
```

------

# Describe table
<a name="code-samples.describe-table"></a>

You can use the following code snippets to get information about the attributes of your table.

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
    public void describeTable() {
        System.out.println("Describing table");
        final DescribeTableRequest describeTableRequest = new DescribeTableRequest();
        describeTableRequest.setDatabaseName(DATABASE_NAME);
        describeTableRequest.setTableName(TABLE_NAME);
        try {
            DescribeTableResult result = amazonTimestreamWrite.describeTable(describeTableRequest);
            String tableId = result.getTable().getArn();
            System.out.println("Table " + TABLE_NAME + " has id " + tableId);
        } catch (final Exception e) {
            System.out.println("Table " + TABLE_NAME + " doesn't exist = " + e);
            throw e;
        }
    }
```

------
#### [  Java v2  ]

```
    public void describeTable() {
        System.out.println("Describing table");
        final DescribeTableRequest describeTableRequest = DescribeTableRequest.builder()
                .databaseName(DATABASE_NAME).tableName(TABLE_NAME).build();
        try {
            DescribeTableResponse response = timestreamWriteClient.describeTable(describeTableRequest);
            String tableId = response.table().arn();
            System.out.println("Table " + TABLE_NAME + " has id " + tableId);
        } catch (final Exception e) {
            System.out.println("Table " + TABLE_NAME + " doesn't exist = " + e);
            throw e;
        }
    }
```

------
#### [  Go  ]

```
// Describe table.
    describeTableInput := &timestreamwrite.DescribeTableInput{
        DatabaseName: aws.String(*databaseName),
        TableName:    aws.String(*tableName),
    }
    describeTableOutput, err := writeSvc.DescribeTable(describeTableInput)

    if err != nil {
        fmt.Println("Error:")
        fmt.Println(err)
    } else {
        fmt.Println("Describe table is successful, below is the output:")
        fmt.Println(describeTableOutput)
    }
```

------
#### [  Python  ]

```
    def describe_table(self):
        print("Describing table")
        try:
            result = self.client.describe_table(DatabaseName=Constant.DATABASE_NAME, TableName=Constant.TABLE_NAME)
            print("Table [%s] has id [%s]" % (Constant.TABLE_NAME, result['Table']['Arn']))
        except self.client.exceptions.ResourceNotFoundException:
            print("Table doesn't exist")
        except Exception as err:
            print("Describe table failed:", err)
```

------
#### [  Node.js  ]

The following snippet uses AWS SDK for JavaScript v3. For more information about how to install the client and usage, see [Timestream Write Client - AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/index.html).

Also see [Class DescribeTableCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/classes/describedatabasecommand.html) and [DescribeTable](https://docs.aws.amazon.com/timestream/latest/developerguide/API_DescribeTable.html).

```
import { TimestreamWriteClient, DescribeTableCommand } from "@aws-sdk/client-timestream-write";
const writeClient = new TimestreamWriteClient({ region: "us-east-1" });

const params = {
    DatabaseName: "testDbFromNode",
    TableName: "testTableFromNode"
};

const command = new DescribeTableCommand(params);

try {
    const data = await writeClient.send(command);
    console.log(`Table ${data.Table.TableName} has id ${data.Table.Arn}`);
} catch (error) {
    if (error.code === 'ResourceNotFoundException') {
        console.log("Table or Database doesn't exist.");
    } else {
        console.log("Describe table failed.", error);
        throw error;
    }
}
```

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
async function describeTable() {
    console.log("Describing Table");
    const params = {
        DatabaseName: constants.DATABASE_NAME,
        TableName: constants.TABLE_NAME
    };

    const promise = writeClient.describeTable(params).promise();

    await promise.then(
        (data) => {
            console.log(`Table ${data.Table.TableName} has id ${data.Table.Arn}`);
        },
        (err) => {
            if (err.code === 'ResourceNotFoundException') {
                console.log("Table or Database doesn't exists.");
            } else {
                console.log("Describe table failed.", err);
                throw err;
            }
        }
    );
}
```

------
#### [  .NET  ]

```
        public async Task DescribeTable()
        {
            Console.WriteLine("Describing Table");

            try
            {
                var describeTableRequest = new DescribeTableRequest
                {
                    DatabaseName = Constants.DATABASE_NAME,
                    TableName = Constants.TABLE_NAME
                };
                DescribeTableResponse response = await writeClient.DescribeTableAsync(describeTableRequest);
                Console.WriteLine($"Table {Constants.TABLE_NAME} has id:{response.Table.Arn}");
            }
            catch (ResourceNotFoundException)
            {
                Console.WriteLine("Table does not exist.");
            }
            catch (Exception e)
            {
                Console.WriteLine("Describe table failed:" + e.ToString());
            }

        }
```

------

# Update table
<a name="code-samples.update-table"></a>

You can use the following code snippets to update a table.

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
    public void updateTable() {
        System.out.println("Updating table");
        UpdateTableRequest updateTableRequest = new UpdateTableRequest();
        updateTableRequest.setDatabaseName(DATABASE_NAME);
        updateTableRequest.setTableName(TABLE_NAME);

        final RetentionProperties retentionProperties = new RetentionProperties()
                .withMemoryStoreRetentionPeriodInHours(HT_TTL_HOURS)
                .withMagneticStoreRetentionPeriodInDays(CT_TTL_DAYS);

        updateTableRequest.setRetentionProperties(retentionProperties);

        amazonTimestreamWrite.updateTable(updateTableRequest);
        System.out.println("Table updated");
    }
```

------
#### [  Java v2  ]

```
    public void updateTable() {
        System.out.println("Updating table");

        final RetentionProperties retentionProperties = RetentionProperties.builder()
                .memoryStoreRetentionPeriodInHours(HT_TTL_HOURS)
                .magneticStoreRetentionPeriodInDays(CT_TTL_DAYS).build();
        final UpdateTableRequest updateTableRequest = UpdateTableRequest.builder()
                .databaseName(DATABASE_NAME).tableName(TABLE_NAME).retentionProperties(retentionProperties).build();

        timestreamWriteClient.updateTable(updateTableRequest);
        System.out.println("Table updated");
    }
```

------
#### [  Go  ]

```
// Update table.
    magneticStoreRetentionPeriodInDays := int64(7 * 365)
    memoryStoreRetentionPeriodInHours := int64(24)

    updateTableInput := &timestreamwrite.UpdateTableInput{
        DatabaseName: aws.String(*databaseName),
        TableName:    aws.String(*tableName),
        RetentionProperties: &timestreamwrite.RetentionProperties{
            MagneticStoreRetentionPeriodInDays: &magneticStoreRetentionPeriodInDays,
            MemoryStoreRetentionPeriodInHours:  &memoryStoreRetentionPeriodInHours,
        },
    }
    updateTableOutput, err := writeSvc.UpdateTable(updateTableInput)

    if err != nil {
        fmt.Println("Error:")
        fmt.Println(err)
    } else {
        fmt.Println("Update table is successful, below is the output:")
        fmt.Println(updateTableOutput)
    }
```

------
#### [  Python  ]

```
    def update_table(self):
        print("Updating table")
        retention_properties = {
            'MemoryStoreRetentionPeriodInHours': Constant.HT_TTL_HOURS,
            'MagneticStoreRetentionPeriodInDays': Constant.CT_TTL_DAYS
        }
        try:
            self.client.update_table(DatabaseName=Constant.DATABASE_NAME, TableName=Constant.TABLE_NAME,
                                     RetentionProperties=retention_properties)
            print("Table updated.")
        except Exception as err:
            print("Update table failed:", err)
```

------
#### [  Node.js  ]

The following snippet uses AWS SDK for JavaScript v3. For more information about how to install the client and usage, see [Timestream Write Client - AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/index.html).

Also see [Class UpdateTableCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/classes/updatetablecommand.html) and [UpdateTable](https://docs.aws.amazon.com/timestream/latest/developerguide/API_UpdateTable.html).

```
import { TimestreamWriteClient, UpdateTableCommand } from "@aws-sdk/client-timestream-write";
const writeClient = new TimestreamWriteClient({ region: "us-east-1" });

const params = {
    DatabaseName: "testDbFromNode",
    TableName: "testTableFromNode",
    RetentionProperties: {
        MemoryStoreRetentionPeriodInHours: 24,
        MagneticStoreRetentionPeriodInDays: 180
    }
};

const command = new UpdateTableCommand(params);

try {
    const data = await writeClient.send(command);
    console.log("Table updated")
} catch (error) {
    console.log("Error updating table. ", error);
}
```

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
async function updateTable() {
    console.log("Updating Table");
    const params = {
        DatabaseName: constants.DATABASE_NAME,
        TableName: constants.TABLE_NAME,
        RetentionProperties: {
            MemoryStoreRetentionPeriodInHours: constants.HT_TTL_HOURS,
            MagneticStoreRetentionPeriodInDays: constants.CT_TTL_DAYS
        }
    };

    const promise = writeClient.updateTable(params).promise();

    await promise.then(
        (data) => {
            console.log("Table updated")
        },
        (err) => {
            console.log("Error updating table. ", err);
            throw err;
        }
    );
}
```

------
#### [  .NET  ]

```
        public async Task UpdateTable()
        {
            Console.WriteLine("Updating Table");

            try
            {
                var updateTableRequest = new UpdateTableRequest
                {
                    DatabaseName = Constants.DATABASE_NAME,
                    TableName = Constants.TABLE_NAME,
                    RetentionProperties = new RetentionProperties
                    {
                        MagneticStoreRetentionPeriodInDays = Constants.CT_TTL_DAYS,
                        MemoryStoreRetentionPeriodInHours = Constants.HT_TTL_HOURS
                    }
                };
                UpdateTableResponse response = await writeClient.UpdateTableAsync(updateTableRequest);
                Console.WriteLine($"Table {Constants.TABLE_NAME} updated");
            }
            catch (ResourceNotFoundException)
            {
                Console.WriteLine("Table does not exist.");
            }
            catch (Exception e)
            {
                Console.WriteLine("Update table failed:" + e.ToString());
            }

        }
```

------

# Delete table
<a name="code-samples.delete-table"></a>

You can use the following code snippets to delete a table.

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
    public void deleteTable() {
        System.out.println("Deleting table");
        final DeleteTableRequest deleteTableRequest = new DeleteTableRequest();
        deleteTableRequest.setDatabaseName(DATABASE_NAME);
        deleteTableRequest.setTableName(TABLE_NAME);
        try {
            DeleteTableResult result =
                    amazonTimestreamWrite.deleteTable(deleteTableRequest);
            System.out.println("Delete table status: " + result.getSdkHttpMetadata().getHttpStatusCode());
        } catch (final ResourceNotFoundException e) {
            System.out.println("Table " + TABLE_NAME + " doesn't exist = " + e);
            throw e;
        } catch (final Exception e) {
            System.out.println("Could not delete table " + TABLE_NAME + " = " + e);
            throw e;
        }
    }
```

------
#### [  Java v2  ]

```
    public void deleteTable() {
        System.out.println("Deleting table");
        final DeleteTableRequest deleteTableRequest = DeleteTableRequest.builder()
                .databaseName(DATABASE_NAME).tableName(TABLE_NAME).build();
        try {
            DeleteTableResponse response =
                    timestreamWriteClient.deleteTable(deleteTableRequest);
            System.out.println("Delete table status: " + response.sdkHttpResponse().statusCode());
        } catch (final ResourceNotFoundException e) {
            System.out.println("Table " + TABLE_NAME + " doesn't exist = " + e);
            throw e;
        } catch (final Exception e) {
            System.out.println("Could not delete table " + TABLE_NAME + " = " + e);
            throw e;
        }
    }
```

------
#### [  Go  ]

```
deleteTableInput := &timestreamwrite.DeleteTableInput{
        DatabaseName:   aws.String(*databaseName),
        TableName:    aws.String(*tableName),
    }
    _, err = writeSvc.DeleteTable(deleteTableInput)

    if err != nil {
        fmt.Println("Error:")
        fmt.Println(err)
    } else {
        fmt.Println("Table deleted", *tableName)
    }
```

------
#### [  Python  ]

```
    def delete_table(self):
        print("Deleting Table")
        try:
            result = self.client.delete_table(DatabaseName=Constant.DATABASE_NAME, TableName=Constant.TABLE_NAME)
            print("Delete table status [%s]" % result['ResponseMetadata']['HTTPStatusCode'])
        except self.client.exceptions.ResourceNotFoundException:
            print("Table [%s] doesn't exist" % Constant.TABLE_NAME)
        except Exception as err:
            print("Delete table failed:", err)
```

------
#### [  Node.js  ]

The following snippet uses AWS SDK for JavaScript v3. For more information about how to install the client and usage, see [Timestream Write Client - AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/index.html).

Also see [Class DeleteTableCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/classes/deletetablecommand.html) and [DeleteTable](https://docs.aws.amazon.com/timestream/latest/developerguide/API_DeleteTable.html).

```
import { TimestreamWriteClient, DeleteTableCommand } from "@aws-sdk/client-timestream-write";
const writeClient = new TimestreamWriteClient({ region: "us-east-1" });

const params = {
    DatabaseName: "testDbFromNode",
    TableName: "testTableFromNode"
};

const command = new DeleteTableCommand(params);

try {
    const data = await writeClient.send(command);
    console.log("Deleted table"); 
} catch (error) {
    if (error.code === 'ResourceNotFoundException') { 
        console.log(`Table ${params.TableName} or Database ${params.DatabaseName} doesn't exist.`); 
    } else { 
        console.log("Delete table failed.", error); 
        throw error; 
    } 
}
```

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
async function deleteTable() { 
    console.log("Deleting Table"); 
    const params = { 
        DatabaseName: constants.DATABASE_NAME, 
        TableName: constants.TABLE_NAME 
    }; 
 
    const promise = writeClient.deleteTable(params).promise(); 

    await promise.then( 
        function (data) { 
            console.log("Deleted table"); 
        }, 
        function(err) { 
            if (err.code === 'ResourceNotFoundException') { 
                console.log(`Table ${params.TableName} or Database ${params.DatabaseName} doesn't exists.`); 
            } else { 
                console.log("Delete table failed.", err); 
                throw err; 
            } 
        } 
    ); 
}
```

------
#### [  .NET  ]

```
        public async Task DeleteTable()
        {
            Console.WriteLine("Deleting table");
            try
            {
                var deleteTableRequest = new DeleteTableRequest
                {
                    DatabaseName = Constants.DATABASE_NAME,
                    TableName = Constants.TABLE_NAME
                };
                DeleteTableResponse response = await writeClient.DeleteTableAsync(deleteTableRequest);
                Console.WriteLine($"Table {Constants.TABLE_NAME} delete request status: {response.HttpStatusCode}");
            }
            catch (ResourceNotFoundException)
            {
                Console.WriteLine($"Table {Constants.TABLE_NAME} does not exists");
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception while deleting table:" + e.ToString());
            }
        }
```

------

# List tables
<a name="code-samples.list-table"></a>

You can use the following code snippets to list tables.

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
    public void listTables() {
        System.out.println("Listing tables");
        ListTablesRequest request = new ListTablesRequest();
        request.setDatabaseName(DATABASE_NAME);
        ListTablesResult result = amazonTimestreamWrite.listTables(request);
        printTables(result.getTables());

        String nextToken = result.getNextToken();
        while (nextToken != null && !nextToken.isEmpty()) {
            request.setNextToken(nextToken);
            ListTablesResult nextResult = amazonTimestreamWrite.listTables(request);

            printTables(nextResult.getTables());
            nextToken = nextResult.getNextToken();
        }
    }
    
     private void printTables(List<Table> tables) {
        for (Table table : tables) {
            System.out.println(table.getTableName());
        }
    }
```

------
#### [  Java v2  ]

```
    public void listTables() {
        System.out.println("Listing tables");
        ListTablesRequest request = ListTablesRequest.builder().databaseName(DATABASE_NAME).maxResults(2).build();
        ListTablesIterable listTablesIterable = timestreamWriteClient.listTablesPaginator(request);
        for(ListTablesResponse listTablesResponse : listTablesIterable) {
            final List<Table> tables = listTablesResponse.tables();
            tables.forEach(table -> System.out.println(table.tableName()));
        }
    }
```

------
#### [  Go  ]

```
listTablesMaxResult := int64(15)

    listTablesInput := &timestreamwrite.ListTablesInput{
        DatabaseName: aws.String(*databaseName),
        MaxResults:   &listTablesMaxResult,
    }
    listTablesOutput, err := writeSvc.ListTables(listTablesInput)

    if err != nil {
        fmt.Println("Error:")
        fmt.Println(err)
    } else {
        fmt.Println("List tables is successful, below is the output:")
        fmt.Println(listTablesOutput)
    }
```

------
#### [  Python  ]

```
    def list_tables(self):
        print("Listing tables")
        try:
            result = self.client.list_tables(DatabaseName=Constant.DATABASE_NAME, MaxResults=5)
            self.__print_tables(result['Tables'])
            next_token = result.get('NextToken', None)
            while next_token:
                result = self.client.list_tables(DatabaseName=Constant.DATABASE_NAME,
                                                 NextToken=next_token, MaxResults=5)
                self.__print_tables(result['Tables'])
                next_token = result.get('NextToken', None)
        except Exception as err:
            print("List tables failed:", err)
```

------
#### [  Node.js  ]

The following snippet uses AWS SDK for JavaScript v3. For more information about how to install the client and usage, see [Timestream Write Client - AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/index.html).

Also see [Class ListTablesCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/classes/listtablescommand.html) and [ListTables](https://docs.aws.amazon.com/timestream/latest/developerguide/API_ListTables.html).

```
import { TimestreamWriteClient, ListTablesCommand } from "@aws-sdk/client-timestream-write";
const writeClient = new TimestreamWriteClient({ region: "us-east-1" });

const params = {
    DatabaseName: "testDbFromNode",
    MaxResults: 15
};

const command = new ListTablesCommand(params);

getTablesList(null);

async function getTablesList(nextToken) {
    if (nextToken) {
        params.NextToken = nextToken;
    }

    try {
        const data = await writeClient.send(command);

        data.Tables.forEach(function (table) {
            console.log(table.TableName);
        });

        if (data.NextToken) {
            return getTablesList(data.NextToken);
        }
    } catch (error) {
        console.log("Error while listing tables", error);
    }
}
```

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
async function listTables() {
    console.log("Listing tables:");
    const tables = await getTablesList(null);
    tables.forEach(function(table){
        console.log(table.TableName);
    });
}

function getTablesList(nextToken, tables = []) {
    var params = {
        DatabaseName: constants.DATABASE_NAME,
        MaxResults: 15
    };

    if(nextToken) {
        params.NextToken = nextToken;
    }

    return writeClient.listTables(params).promise()
        .then(
            (data) => {
                tables.push.apply(tables, data.Tables);
                if (data.NextToken) {
                    return getTablesList(data.NextToken, tables);
                } else {
                    return tables;
                }
            },
            (err) => {
                console.log("Error while listing databases", err);
            });
}
```

------
#### [  .NET  ]

```
        public async Task ListTables()
        {
            Console.WriteLine("Listing Tables");

            try
            {
                var listTablesRequest = new ListTablesRequest
                {
                    MaxResults = 5,
                    DatabaseName = Constants.DATABASE_NAME
                };
                ListTablesResponse response = await writeClient.ListTablesAsync(listTablesRequest);
                PrintTables(response.Tables);
                string nextToken = response.NextToken;
                while (nextToken != null)
                {
                    listTablesRequest.NextToken = nextToken;
                    response = await writeClient.ListTablesAsync(listTablesRequest);
                    PrintTables(response.Tables);
                    nextToken = response.NextToken;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("List table failed:" + e.ToString());
            }

        }

        private void PrintTables(List<Table> tables)
        {
            foreach (Table table in tables)
                Console.WriteLine($"Table: {table.TableName}");
        }
```

------

# Write data (inserts and upserts)
<a name="code-samples.write"></a>

**Topics**
+ [Writing batches of records](#code-samples.write.write-batches)
+ [Writing batches of records with common attributes](#code-samples.write.write-batches-common-attrs)
+ [Upserting records](#code-samples.write.upserts)
+ [Multi-measure attribute example](#code-samples.write.data.multivalue)
+ [Handling write failures](#code-samples.write.rejectedRecordException)

## Writing batches of records
<a name="code-samples.write.write-batches"></a>

You can use the following code snippets to write data into an Amazon Timestream table. Writing data in batches helps to optimize the cost of writes. See [Calculating the number of writes](metering-and-pricing.writes.md#metering-and-pricing.writes.write-size-multiple-events) for more information. 

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
  public void writeRecords() {
    System.out.println("Writing records");
    // Specify repeated values for all records
    List<Record> records = new ArrayList<>();
    final long time = System.currentTimeMillis();

    List<Dimension> dimensions = new ArrayList<>();
    final Dimension region = new Dimension().withName("region").withValue("us-east-1");
    final Dimension az = new Dimension().withName("az").withValue("az1");
    final Dimension hostname = new Dimension().withName("hostname").withValue("host1");

    dimensions.add(region);
    dimensions.add(az);
    dimensions.add(hostname);

    Record cpuUtilization = new Record()
        .withDimensions(dimensions)
        .withMeasureName("cpu_utilization")
        .withMeasureValue("13.5")
        .withMeasureValueType(MeasureValueType.DOUBLE)
        .withTime(String.valueOf(time));
    Record memoryUtilization = new Record()
        .withDimensions(dimensions)
        .withMeasureName("memory_utilization")
        .withMeasureValue("40")
        .withMeasureValueType(MeasureValueType.DOUBLE)
        .withTime(String.valueOf(time));

    records.add(cpuUtilization);
    records.add(memoryUtilization);

    WriteRecordsRequest writeRecordsRequest = new WriteRecordsRequest()
        .withDatabaseName(DATABASE_NAME)
        .withTableName(TABLE_NAME)
        .withRecords(records);

    try {
      WriteRecordsResult writeRecordsResult = amazonTimestreamWrite.writeRecords(writeRecordsRequest);
      System.out.println("WriteRecords Status: " + writeRecordsResult.getSdkHttpMetadata().getHttpStatusCode());
    } catch (RejectedRecordsException e) {
      System.out.println("RejectedRecords: " + e);
      for (RejectedRecord rejectedRecord : e.getRejectedRecords()) {
        System.out.println("Rejected Index " + rejectedRecord.getRecordIndex() + ": "
            + rejectedRecord.getReason());
      }
      System.out.println("Other records were written successfully. ");
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }
  }
```

------
#### [  Java v2  ]

```
  public void writeRecords() {
    System.out.println("Writing records");
    // Specify repeated values for all records
    List<Record> records = new ArrayList<>();
    final long time = System.currentTimeMillis();

    List<Dimension> dimensions = new ArrayList<>();
    final Dimension region = Dimension.builder().name("region").value("us-east-1").build();
    final Dimension az = Dimension.builder().name("az").value("az1").build();
    final Dimension hostname = Dimension.builder().name("hostname").value("host1").build();

    dimensions.add(region);
    dimensions.add(az);
    dimensions.add(hostname);

    Record cpuUtilization = Record.builder()
        .dimensions(dimensions)
        .measureValueType(MeasureValueType.DOUBLE)
        .measureName("cpu_utilization")
        .measureValue("13.5")
        .time(String.valueOf(time)).build();

    Record memoryUtilization = Record.builder()
        .dimensions(dimensions)
        .measureValueType(MeasureValueType.DOUBLE)
        .measureName("memory_utilization")
        .measureValue("40")
        .time(String.valueOf(time)).build();

    records.add(cpuUtilization);
    records.add(memoryUtilization);

    WriteRecordsRequest writeRecordsRequest = WriteRecordsRequest.builder()
        .databaseName(DATABASE_NAME).tableName(TABLE_NAME).records(records).build();

    try {
      WriteRecordsResponse writeRecordsResponse = timestreamWriteClient.writeRecords(writeRecordsRequest);
      System.out.println("WriteRecords Status: " + writeRecordsResponse.sdkHttpResponse().statusCode());
    } catch (RejectedRecordsException e) {
      System.out.println("RejectedRecords: " + e);
      for (RejectedRecord rejectedRecord : e.rejectedRecords()) {
        System.out.println("Rejected Index " + rejectedRecord.recordIndex() + ": "
            + rejectedRecord.reason());
      }
      System.out.println("Other records were written successfully. ");
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }
  }
```

------
#### [  Go  ]

```
now := time.Now()
currentTimeInSeconds := now.Unix()
writeRecordsInput := &timestreamwrite.WriteRecordsInput{
  DatabaseName: aws.String(*databaseName),
  TableName:  aws.String(*tableName),
  Records: []*timestreamwrite.Record{
    &timestreamwrite.Record{
      Dimensions: []*timestreamwrite.Dimension{
        &timestreamwrite.Dimension{
          Name:  aws.String("region"),
          Value: aws.String("us-east-1"),
        },
        &timestreamwrite.Dimension{
          Name:  aws.String("az"),
          Value: aws.String("az1"),
        },
        &timestreamwrite.Dimension{
          Name:  aws.String("hostname"),
          Value: aws.String("host1"),
        },
      },
      MeasureName:    aws.String("cpu_utilization"),
      MeasureValue:   aws.String("13.5"),
      MeasureValueType: aws.String("DOUBLE"),
      Time:       aws.String(strconv.FormatInt(currentTimeInSeconds, 10)),
      TimeUnit:  aws.String("SECONDS"),
    },
    &timestreamwrite.Record{
      Dimensions: []*timestreamwrite.Dimension{
        &timestreamwrite.Dimension{
          Name:  aws.String("region"),
          Value: aws.String("us-east-1"),
        },
        &timestreamwrite.Dimension{
          Name:  aws.String("az"),
          Value: aws.String("az1"),
        },
        &timestreamwrite.Dimension{
          Name:  aws.String("hostname"),
          Value: aws.String("host1"),
        },
      },
      MeasureName:    aws.String("memory_utilization"),
      MeasureValue:   aws.String("40"),
      MeasureValueType: aws.String("DOUBLE"),
      Time:       aws.String(strconv.FormatInt(currentTimeInSeconds, 10)),
      TimeUnit:  aws.String("SECONDS"),
    },
  },
}

_, err = writeSvc.WriteRecords(writeRecordsInput)

if err != nil {
  fmt.Println("Error:")
  fmt.Println(err)
} else {
  fmt.Println("Write records is successful")
}
```

------
#### [  Python  ]

```
  def write_records(self):
    print("Writing records")
    current_time = self._current_milli_time()

    dimensions = [
      {'Name': 'region', 'Value': 'us-east-1'},
      {'Name': 'az', 'Value': 'az1'},
      {'Name': 'hostname', 'Value': 'host1'}
    ]

    cpu_utilization = {
      'Dimensions': dimensions,
      'MeasureName': 'cpu_utilization',
      'MeasureValue': '13.5',
      'MeasureValueType': 'DOUBLE',
      'Time': current_time
    }

    memory_utilization = {
      'Dimensions': dimensions,
      'MeasureName': 'memory_utilization',
      'MeasureValue': '40',
      'MeasureValueType': 'DOUBLE',
      'Time': current_time
    }

    records = [cpu_utilization, memory_utilization]

    try:
      result = self.client.write_records(DatabaseName=Constant.DATABASE_NAME, TableName=Constant.TABLE_NAME,
                         Records=records, CommonAttributes={})
      print("WriteRecords Status: [%s]" % result['ResponseMetadata']['HTTPStatusCode'])
    except self.client.exceptions.RejectedRecordsException as err:
      self._print_rejected_records_exceptions(err)
    except Exception as err:
      print("Error:", err)

  @staticmethod
  def _print_rejected_records_exceptions(err):
    print("RejectedRecords: ", err)
    for rr in err.response["RejectedRecords"]:
      print("Rejected Index " + str(rr["RecordIndex"]) + ": " + rr["Reason"])
      if "ExistingVersion" in rr:
        print("Rejected record existing version: ", rr["ExistingVersion"])

  @staticmethod
  def _current_milli_time():
    return str(int(round(time.time() * 1000)))
```

------
#### [  Node.js  ]

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
async function writeRecords() {
  console.log("Writing records");
  const currentTime = Date.now().toString(); // Unix time in milliseconds

  const dimensions = [
    {'Name': 'region', 'Value': 'us-east-1'},
    {'Name': 'az', 'Value': 'az1'},
    {'Name': 'hostname', 'Value': 'host1'}
  ];

  const cpuUtilization = {
    'Dimensions': dimensions,
    'MeasureName': 'cpu_utilization',
    'MeasureValue': '13.5',
    'MeasureValueType': 'DOUBLE',
    'Time': currentTime.toString()
  };

  const memoryUtilization = {
    'Dimensions': dimensions,
    'MeasureName': 'memory_utilization',
    'MeasureValue': '40',
    'MeasureValueType': 'DOUBLE',
    'Time': currentTime.toString()
  };

  const records = [cpuUtilization, memoryUtilization];

  const params = {
    DatabaseName: constants.DATABASE_NAME,
    TableName: constants.TABLE_NAME,
    Records: records
  };

  const request = writeClient.writeRecords(params);

  await request.promise().then(
    (data) => {
      console.log("Write records successful");
    },
    (err) => {
      console.log("Error writing records:", err);
      if (err.code === 'RejectedRecordsException') {
        const responsePayload = JSON.parse(request.response.httpResponse.body.toString());
        console.log("RejectedRecords: ", responsePayload.RejectedRecords);
        console.log("Other records were written successfully. ");
      }
    }
  );
}
```

------
#### [  .NET  ]

```
   public async Task WriteRecords()
   {
     Console.WriteLine("Writing records");

     DateTimeOffset now = DateTimeOffset.UtcNow;
     string currentTimeString = (now.ToUnixTimeMilliseconds()).ToString();

     List<Dimension> dimensions = new List<Dimension>{
       new Dimension { Name = "region", Value = "us-east-1" },
       new Dimension { Name = "az", Value = "az1" },
       new Dimension { Name = "hostname", Value = "host1" }
     };

     var cpuUtilization = new Record
     {
       Dimensions = dimensions,
       MeasureName = "cpu_utilization",
       MeasureValue = "13.6",
       MeasureValueType = MeasureValueType.DOUBLE,
       Time = currentTimeString
     };

     var memoryUtilization = new Record
     {
       Dimensions = dimensions,
       MeasureName = "memory_utilization",
       MeasureValue = "40",
       MeasureValueType = MeasureValueType.DOUBLE,
       Time = currentTimeString
     };


     List<Record> records = new List<Record> {
       cpuUtilization,
       memoryUtilization
     };

     try
     {
       var writeRecordsRequest = new WriteRecordsRequest
       {
         DatabaseName = Constants.DATABASE_NAME,
         TableName = Constants.TABLE_NAME,
         Records = records
       };
       WriteRecordsResponse response = await writeClient.WriteRecordsAsync(writeRecordsRequest);
       Console.WriteLine($"Write records status code: {response.HttpStatusCode.ToString()}");
     }
     catch (RejectedRecordsException e) {
       Console.WriteLine("RejectedRecordsException:" + e.ToString());
       foreach (RejectedRecord rr in e.RejectedRecords) {
         Console.WriteLine("RecordIndex " + rr.RecordIndex + " : " + rr.Reason);
       }
       Console.WriteLine("Other records were written successfully. ");
     }
     catch (Exception e)
     {
       Console.WriteLine("Write records failure:" + e.ToString());
     }
   }
```

------

## Writing batches of records with common attributes
<a name="code-samples.write.write-batches-common-attrs"></a>

If your time series data has measures and/or dimensions that are common across many data points, you can also use the following optimized version of the writeRecords API to insert data into Timestream for LiveAnalytics. Using common attributes with batching can further optimize the cost of writes as described in [Calculating the number of writes](metering-and-pricing.writes.md#metering-and-pricing.writes.write-size-multiple-events). 

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
  public void writeRecordsWithCommonAttributes() {
    System.out.println("Writing records with extracting common attributes");
    // Specify repeated values for all records
    List<Record> records = new ArrayList<>();
    final long time = System.currentTimeMillis();

    List<Dimension> dimensions = new ArrayList<>();
    final Dimension region = new Dimension().withName("region").withValue("us-east-1");
    final Dimension az = new Dimension().withName("az").withValue("az1");
    final Dimension hostname = new Dimension().withName("hostname").withValue("host1");

    dimensions.add(region);
    dimensions.add(az);
    dimensions.add(hostname);

    Record commonAttributes = new Record()
        .withDimensions(dimensions)
        .withMeasureValueType(MeasureValueType.DOUBLE)
        .withTime(String.valueOf(time));

    Record cpuUtilization = new Record()
        .withMeasureName("cpu_utilization")
        .withMeasureValue("13.5");
    Record memoryUtilization = new Record()
        .withMeasureName("memory_utilization")
        .withMeasureValue("40");

    records.add(cpuUtilization);
    records.add(memoryUtilization);

    WriteRecordsRequest writeRecordsRequest = new WriteRecordsRequest()
        .withDatabaseName(DATABASE_NAME)
        .withTableName(TABLE_NAME)
        .withCommonAttributes(commonAttributes);
    writeRecordsRequest.setRecords(records);

    try {
      WriteRecordsResult writeRecordsResult = amazonTimestreamWrite.writeRecords(writeRecordsRequest);
      System.out.println("writeRecordsWithCommonAttributes Status: " + writeRecordsResult.getSdkHttpMetadata().getHttpStatusCode());
    } catch (RejectedRecordsException e) {
      System.out.println("RejectedRecords: " + e);
      for (RejectedRecord rejectedRecord : e.getRejectedRecords()) {
        System.out.println("Rejected Index " + rejectedRecord.getRecordIndex() + ": "
            + rejectedRecord.getReason());
      }
      System.out.println("Other records were written successfully. ");
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }
  }
```

------
#### [  Java v2  ]

```
  public void writeRecordsWithCommonAttributes() {
    System.out.println("Writing records with extracting common attributes");
    // Specify repeated values for all records
    List<Record> records = new ArrayList<>();
    final long time = System.currentTimeMillis();

    List<Dimension> dimensions = new ArrayList<>();
    final Dimension region = Dimension.builder().name("region").value("us-east-1").build();
    final Dimension az = Dimension.builder().name("az").value("az1").build();
    final Dimension hostname = Dimension.builder().name("hostname").value("host1").build();

    dimensions.add(region);
    dimensions.add(az);
    dimensions.add(hostname);

    Record commonAttributes = Record.builder()
        .dimensions(dimensions)
        .measureValueType(MeasureValueType.DOUBLE)
        .time(String.valueOf(time)).build();

    Record cpuUtilization = Record.builder()
        .measureName("cpu_utilization")
        .measureValue("13.5").build();
    Record memoryUtilization = Record.builder()
        .measureName("memory_utilization")
        .measureValue("40").build();

    records.add(cpuUtilization);
    records.add(memoryUtilization);

    WriteRecordsRequest writeRecordsRequest = WriteRecordsRequest.builder()
        .databaseName(DATABASE_NAME)
        .tableName(TABLE_NAME)
        .commonAttributes(commonAttributes)
        .records(records).build();

    try {
      WriteRecordsResponse writeRecordsResponse = timestreamWriteClient.writeRecords(writeRecordsRequest);
      System.out.println("writeRecordsWithCommonAttributes Status: " + writeRecordsResponse.sdkHttpResponse().statusCode());
    } catch (RejectedRecordsException e) {
      System.out.println("RejectedRecords: " + e);
      for (RejectedRecord rejectedRecord : e.rejectedRecords()) {
        System.out.println("Rejected Index " + rejectedRecord.recordIndex() + ": "
            + rejectedRecord.reason());
      }
      System.out.println("Other records were written successfully. ");
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }
  }
```

------
#### [  Go  ]

```
now = time.Now()
currentTimeInSeconds = now.Unix()
writeRecordsCommonAttributesInput := &timestreamwrite.WriteRecordsInput{
	DatabaseName: aws.String(*databaseName),
	TableName:  aws.String(*tableName),
	CommonAttributes: &timestreamwrite.Record{
		Dimensions: []*timestreamwrite.Dimension{
			&timestreamwrite.Dimension{
				Name:  aws.String("region"),
				Value: aws.String("us-east-1"),
			},
			&timestreamwrite.Dimension{
				Name:  aws.String("az"),
				Value: aws.String("az1"),
			},
			&timestreamwrite.Dimension{
				Name:  aws.String("hostname"),
				Value: aws.String("host1"),
			},
		},
		MeasureValueType: aws.String("DOUBLE"),
		Time:       aws.String(strconv.FormatInt(currentTimeInSeconds, 10)),
		TimeUnit:     aws.String("SECONDS"),
	},
	Records: []*timestreamwrite.Record{
		&timestreamwrite.Record{
			MeasureName:  aws.String("cpu_utilization"),
			MeasureValue: aws.String("13.5"),
		},
		&timestreamwrite.Record{
			MeasureName:  aws.String("memory_utilization"),
			MeasureValue: aws.String("40"),
		},
	},
}

_, err = writeSvc.WriteRecords(writeRecordsCommonAttributesInput)

if err != nil {
	fmt.Println("Error:")
	fmt.Println(err)
} else {
	fmt.Println("Ingest records is successful")
}
```

------
#### [  Python  ]

```
  def write_records_with_common_attributes(self):
    print("Writing records extracting common attributes")
    current_time = self._current_milli_time()

    dimensions = [
      {'Name': 'region', 'Value': 'us-east-1'},
      {'Name': 'az', 'Value': 'az1'},
      {'Name': 'hostname', 'Value': 'host1'}
    ]

    common_attributes = {
      'Dimensions': dimensions,
      'MeasureValueType': 'DOUBLE',
      'Time': current_time
    }

    cpu_utilization = {
      'MeasureName': 'cpu_utilization',
      'MeasureValue': '13.5'
    }

    memory_utilization = {
      'MeasureName': 'memory_utilization',
      'MeasureValue': '40'
    }

    records = [cpu_utilization, memory_utilization]

    try:
      result = self.client.write_records(DatabaseName=Constant.DATABASE_NAME, TableName=Constant.TABLE_NAME,
                         Records=records, CommonAttributes=common_attributes)
      print("WriteRecords Status: [%s]" % result['ResponseMetadata']['HTTPStatusCode'])
    except self.client.exceptions.RejectedRecordsException as err:
      self._print_rejected_records_exceptions(err)
    except Exception as err:
      print("Error:", err)

  @staticmethod
  def _print_rejected_records_exceptions(err):
    print("RejectedRecords: ", err)
    for rr in err.response["RejectedRecords"]:
      print("Rejected Index " + str(rr["RecordIndex"]) + ": " + rr["Reason"])
      if "ExistingVersion" in rr:
        print("Rejected record existing version: ", rr["ExistingVersion"])

  @staticmethod
  def _current_milli_time():
    return str(int(round(time.time() * 1000)))
```

------
#### [  Node.js  ]

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
async function writeRecordsWithCommonAttributes() {
  console.log("Writing records with common attributes");
  const currentTime = Date.now().toString(); // Unix time in milliseconds

  const dimensions = [
    {'Name': 'region', 'Value': 'us-east-1'},
    {'Name': 'az', 'Value': 'az1'},
    {'Name': 'hostname', 'Value': 'host1'}
  ];

  const commonAttributes = {
    'Dimensions': dimensions,
    'MeasureValueType': 'DOUBLE',
    'Time': currentTime.toString()
  };

  const cpuUtilization = {
    'MeasureName': 'cpu_utilization',
    'MeasureValue': '13.5'
  };

  const memoryUtilization = {
    'MeasureName': 'memory_utilization',
    'MeasureValue': '40'
  };

  const records = [cpuUtilization, memoryUtilization];

  const params = {
    DatabaseName: constants.DATABASE_NAME,
    TableName: constants.TABLE_NAME,
    Records: records,
    CommonAttributes: commonAttributes
  };

  const request = writeClient.writeRecords(params);

  await request.promise().then(
    (data) => {
      console.log("Write records successful");
    },
    (err) => {
      console.log("Error writing records:", err);
      if (err.code === 'RejectedRecordsException') {
        const responsePayload = JSON.parse(request.response.httpResponse.body.toString());
        console.log("RejectedRecords: ", responsePayload.RejectedRecords);
        console.log("Other records were written successfully. ");
      }
    }
  );
}
```

------
#### [  .NET  ]

```
  public async Task WriteRecordsWithCommonAttributes()
  {
    Console.WriteLine("Writing records with common attributes");

    DateTimeOffset now = DateTimeOffset.UtcNow;
    string currentTimeString = (now.ToUnixTimeMilliseconds()).ToString();

    List<Dimension> dimensions = new List<Dimension>{
      new Dimension { Name = "region", Value = "us-east-1" },
      new Dimension { Name = "az", Value = "az1" },
      new Dimension { Name = "hostname", Value = "host1" }
    };

    var commonAttributes = new Record
    {
      Dimensions = dimensions,
      MeasureValueType = MeasureValueType.DOUBLE,
      Time = currentTimeString
    };

    var cpuUtilization = new Record
    {
      MeasureName = "cpu_utilization",
      MeasureValue = "13.6"
    };

    var memoryUtilization = new Record
    {
      MeasureName = "memory_utilization",
      MeasureValue = "40"
    };


    List<Record> records = new List<Record>();
    records.Add(cpuUtilization);
    records.Add(memoryUtilization);

    try
    {
      var writeRecordsRequest = new WriteRecordsRequest
      {
        DatabaseName = Constants.DATABASE_NAME,
        TableName = Constants.TABLE_NAME,
        Records = records,
        CommonAttributes = commonAttributes
      };
      WriteRecordsResponse response = await writeClient.WriteRecordsAsync(writeRecordsRequest);
      Console.WriteLine($"Write records status code: {response.HttpStatusCode.ToString()}");
    }
    catch (RejectedRecordsException e) {
      Console.WriteLine("RejectedRecordsException:" + e.ToString());
      foreach (RejectedRecord rr in e.RejectedRecords) {
        Console.WriteLine("RecordIndex " + rr.RecordIndex + " : " + rr.Reason);
      }
      Console.WriteLine("Other records were written successfully. ");
    }
    catch (Exception e)
    {
      Console.WriteLine("Write records failure:" + e.ToString());
    }
  }
```

------

## Upserting records
<a name="code-samples.write.upserts"></a>

While the default writes in Amazon Timestream follow the *first writer wins* semantics, where data is stored as append only and duplicate records are rejected, there are applications that require the ability to write data into Amazon Timestream using the *last writer wins* semantics, where the record with the highest version is stored in the system. There are also applications that require the ability to update existing records. To address these scenarios, Amazon Timestream provides the ability to *upsert* data. Upsert is an operation that inserts a record in to the system when the record does not exist or updates the record, when one exists. 

You can upsert records by including the `Version` in record definition while sending a `WriteRecords` request. Amazon Timestream will store the record with the record with highest `Version`. The code sample below shows how you can upsert data:

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
  public void writeRecordsWithUpsert() {
    System.out.println("Writing records with upsert");
    // Specify repeated values for all records
    List<Record> records = new ArrayList<>();
    final long time = System.currentTimeMillis();
    // To achieve upsert (last writer wins) semantic, one example is to use current time as the version if you are writing directly from the data source
    long version = System.currentTimeMillis();

    List<Dimension> dimensions = new ArrayList<>();
    final Dimension region = new Dimension().withName("region").withValue("us-east-1");
    final Dimension az = new Dimension().withName("az").withValue("az1");
    final Dimension hostname = new Dimension().withName("hostname").withValue("host1");

    dimensions.add(region);
    dimensions.add(az);
    dimensions.add(hostname);

    Record commonAttributes = new Record()
        .withDimensions(dimensions)
        .withMeasureValueType(MeasureValueType.DOUBLE)
        .withTime(String.valueOf(time))
        .withVersion(version);

    Record cpuUtilization = new Record()
        .withMeasureName("cpu_utilization")
        .withMeasureValue("13.5");
    Record memoryUtilization = new Record()
        .withMeasureName("memory_utilization")
        .withMeasureValue("40");

    records.add(cpuUtilization);
    records.add(memoryUtilization);

    WriteRecordsRequest writeRecordsRequest = new WriteRecordsRequest()
        .withDatabaseName(DATABASE_NAME)
        .withTableName(TABLE_NAME)
        .withCommonAttributes(commonAttributes);
    writeRecordsRequest.setRecords(records);

    // write records for first time
    try {
      WriteRecordsResult writeRecordsResult = amazonTimestreamWrite.writeRecords(writeRecordsRequest);
      System.out.println("WriteRecords Status for first time: " + writeRecordsResult.getSdkHttpMetadata().getHttpStatusCode());
    } catch (RejectedRecordsException e) {
      printRejectedRecordsException(e);
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }

    // Successfully retry same writeRecordsRequest with same records and versions, because writeRecords API is idempotent.
    try {
      WriteRecordsResult writeRecordsResult = amazonTimestreamWrite.writeRecords(writeRecordsRequest);
      System.out.println("WriteRecords Status for retry: " + writeRecordsResult.getSdkHttpMetadata().getHttpStatusCode());
    } catch (RejectedRecordsException e) {
      printRejectedRecordsException(e);
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }

    // upsert with lower version, this would fail because a higher version is required to update the measure value.
    version -= 1;
    commonAttributes.setVersion(version);

    cpuUtilization.setMeasureValue("14.5");
    memoryUtilization.setMeasureValue("50");

    List<Record> upsertedRecords = new ArrayList<>();
    upsertedRecords.add(cpuUtilization);
    upsertedRecords.add(memoryUtilization);

    WriteRecordsRequest writeRecordsUpsertRequest = new WriteRecordsRequest()
        .withDatabaseName(DATABASE_NAME)
        .withTableName(TABLE_NAME)
        .withCommonAttributes(commonAttributes);
    writeRecordsUpsertRequest.setRecords(upsertedRecords);

    try {
      WriteRecordsResult writeRecordsUpsertResult = amazonTimestreamWrite.writeRecords(writeRecordsUpsertRequest);
      System.out.println("WriteRecords Status for upsert with lower version: " + writeRecordsUpsertResult.getSdkHttpMetadata().getHttpStatusCode());
    } catch (RejectedRecordsException e) {
      System.out.println("WriteRecords Status for upsert with lower version: ");
      printRejectedRecordsException(e);
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }

    // upsert with higher version as new data in generated
    version = System.currentTimeMillis();
    commonAttributes.setVersion(version);

    writeRecordsUpsertRequest = new WriteRecordsRequest()
        .withDatabaseName(DATABASE_NAME)
        .withTableName(TABLE_NAME)
        .withCommonAttributes(commonAttributes);
    writeRecordsUpsertRequest.setRecords(upsertedRecords);

    try {
      WriteRecordsResult writeRecordsUpsertResult = amazonTimestreamWrite.writeRecords(writeRecordsUpsertRequest);
      System.out.println("WriteRecords Status for upsert with higher version: " + writeRecordsUpsertResult.getSdkHttpMetadata().getHttpStatusCode());
    } catch (RejectedRecordsException e) {
      printRejectedRecordsException(e);
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }
  }
```

------
#### [  Java v2  ]

```
  public void writeRecordsWithUpsert() {
    System.out.println("Writing records with upsert");
    // Specify repeated values for all records
    List<Record> records = new ArrayList<>();
    final long time = System.currentTimeMillis();
    // To achieve upsert (last writer wins) semantic, one example is to use current time as the version if you are writing directly from the data source
    long version = System.currentTimeMillis();

    List<Dimension> dimensions = new ArrayList<>();
    final Dimension region = Dimension.builder().name("region").value("us-east-1").build();
    final Dimension az = Dimension.builder().name("az").value("az1").build();
    final Dimension hostname = Dimension.builder().name("hostname").value("host1").build();

    dimensions.add(region);
    dimensions.add(az);
    dimensions.add(hostname);

    Record commonAttributes = Record.builder()
        .dimensions(dimensions)
        .measureValueType(MeasureValueType.DOUBLE)
        .time(String.valueOf(time))
        .version(version)
        .build();

    Record cpuUtilization = Record.builder()
        .measureName("cpu_utilization")
        .measureValue("13.5").build();
    Record memoryUtilization = Record.builder()
        .measureName("memory_utilization")
        .measureValue("40").build();

    records.add(cpuUtilization);
    records.add(memoryUtilization);

    WriteRecordsRequest writeRecordsRequest = WriteRecordsRequest.builder()
        .databaseName(DATABASE_NAME)
        .tableName(TABLE_NAME)
        .commonAttributes(commonAttributes)
        .records(records).build();

    // write records for first time
    try {
      WriteRecordsResponse writeRecordsResponse = timestreamWriteClient.writeRecords(writeRecordsRequest);
      System.out.println("WriteRecords Status for first time: " + writeRecordsResponse.sdkHttpResponse().statusCode());
    } catch (RejectedRecordsException e) {
      printRejectedRecordsException(e);
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }

    // Successfully retry same writeRecordsRequest with same records and versions, because writeRecords API is idempotent.
    try {
      WriteRecordsResponse writeRecordsResponse = timestreamWriteClient.writeRecords(writeRecordsRequest);
      System.out.println("WriteRecords Status for retry: " + writeRecordsResponse.sdkHttpResponse().statusCode());
    } catch (RejectedRecordsException e) {
      printRejectedRecordsException(e);
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }

    // upsert with lower version, this would fail because a higher version is required to update the measure value.
    version -= 1;
    commonAttributes = Record.builder()
        .dimensions(dimensions)
        .measureValueType(MeasureValueType.DOUBLE)
        .time(String.valueOf(time))
        .version(version)
        .build();

    cpuUtilization = Record.builder()
        .measureName("cpu_utilization")
        .measureValue("14.5").build();
    memoryUtilization = Record.builder()
        .measureName("memory_utilization")
        .measureValue("50").build();

    List<Record> upsertedRecords = new ArrayList<>();
    upsertedRecords.add(cpuUtilization);
    upsertedRecords.add(memoryUtilization);

    WriteRecordsRequest writeRecordsUpsertRequest = WriteRecordsRequest.builder()
        .databaseName(DATABASE_NAME)
        .tableName(TABLE_NAME)
        .commonAttributes(commonAttributes)
        .records(upsertedRecords).build();

    try {
      WriteRecordsResponse writeRecordsResponse = timestreamWriteClient.writeRecords(writeRecordsUpsertRequest);
      System.out.println("WriteRecords Status for upsert with lower version: " + writeRecordsResponse.sdkHttpResponse().statusCode());
    } catch (RejectedRecordsException e) {
      System.out.println("WriteRecords Status for upsert with lower version: ");
      printRejectedRecordsException(e);
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }

    // upsert with higher version as new data in generated
    version = System.currentTimeMillis();
    commonAttributes = Record.builder()
        .dimensions(dimensions)
        .measureValueType(MeasureValueType.DOUBLE)
        .time(String.valueOf(time))
        .version(version)
        .build();

    writeRecordsUpsertRequest = WriteRecordsRequest.builder()
        .databaseName(DATABASE_NAME)
        .tableName(TABLE_NAME)
        .commonAttributes(commonAttributes)
        .records(upsertedRecords).build();

    try {
      WriteRecordsResponse writeRecordsUpsertResponse = timestreamWriteClient.writeRecords(writeRecordsUpsertRequest);
      System.out.println("WriteRecords Status for upsert with higher version: " + writeRecordsUpsertResponse.sdkHttpResponse().statusCode());
    } catch (RejectedRecordsException e) {
      printRejectedRecordsException(e);
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }
  }
```

------
#### [  Go  ]

```
// Below code will ingest and upsert cpu_utilization and memory_utilization metric for a host on
// region=us-east-1, az=az1, and hostname=host1
fmt.Println("Ingesting records and set version as currentTimeInMills, hit enter to continue")
reader.ReadString('\n')

// Get current time in seconds.
now = time.Now()
currentTimeInSeconds = now.Unix()
// To achieve upsert (last writer wins) semantic, one example is to use current time as the version if you are writing directly from the data source
version := time.Now().Round(time.Millisecond).UnixNano() / 1e6   // set version as currentTimeInMills

writeRecordsCommonAttributesUpsertInput := &timestreamwrite.WriteRecordsInput{
	DatabaseName: aws.String(*databaseName),
	TableName:  aws.String(*tableName),
	CommonAttributes: &timestreamwrite.Record{
		Dimensions: []*timestreamwrite.Dimension{
			&timestreamwrite.Dimension{
				Name:  aws.String("region"),
				Value: aws.String("us-east-1"),
			},
			&timestreamwrite.Dimension{
				Name:  aws.String("az"),
				Value: aws.String("az1"),
			},
			&timestreamwrite.Dimension{
				Name:  aws.String("hostname"),
				Value: aws.String("host1"),
			},
		},
		MeasureValueType: aws.String("DOUBLE"),
		Time:       aws.String(strconv.FormatInt(currentTimeInSeconds, 10)),
		TimeUnit:  aws.String("SECONDS"),
		Version:      &version,
	},
	Records: []*timestreamwrite.Record{
		&timestreamwrite.Record{
			MeasureName:  aws.String("cpu_utilization"),
			MeasureValue: aws.String("13.5"),
		},
		&timestreamwrite.Record{
			MeasureName:  aws.String("memory_utilization"),
			MeasureValue: aws.String("40"),
		},
	},
}

// write records for first time
_, err = writeSvc.WriteRecords(writeRecordsCommonAttributesUpsertInput)

if err != nil {
	fmt.Println("Error:")
	fmt.Println(err)
} else {
	fmt.Println("Frist-time write records is successful")
}

fmt.Println("Retry same writeRecordsRequest with same records and versions. Because writeRecords API is idempotent, this will success. hit enter to continue")
reader.ReadString('\n')

_, err = writeSvc.WriteRecords(writeRecordsCommonAttributesUpsertInput)

if err != nil {
	fmt.Println("Error:")
	fmt.Println(err)
} else {
	fmt.Println("Retry write records for same request is successful")
}

fmt.Println("Upsert with lower version, this would fail because a higher version is required to update the measure value. hit enter to continue")
reader.ReadString('\n')
version -= 1
writeRecordsCommonAttributesUpsertInput.CommonAttributes.Version = &version

updated_cpu_utilization := &timestreamwrite.Record{
	MeasureName:    aws.String("cpu_utilization"),
	MeasureValue:   aws.String("14.5"),
}
updated_memory_utilization := &timestreamwrite.Record{
	MeasureName:    aws.String("memory_utilization"),
	MeasureValue:   aws.String("50"),
}


writeRecordsCommonAttributesUpsertInput.Records = []*timestreamwrite.Record{
	updated_cpu_utilization,
	updated_memory_utilization,
}

_, err = writeSvc.WriteRecords(writeRecordsCommonAttributesUpsertInput)

if err != nil {
	fmt.Println("Error:")
	fmt.Println(err)
} else {
	fmt.Println("Write records with lower version is successful")
}

fmt.Println("Upsert with higher version as new data in generated, this would success. hit enter to continue")
reader.ReadString('\n')

version = time.Now().Round(time.Millisecond).UnixNano() / 1e6  // set version as currentTimeInMills
writeRecordsCommonAttributesUpsertInput.CommonAttributes.Version = &version

_, err = writeSvc.WriteRecords(writeRecordsCommonAttributesUpsertInput)

if err != nil {
	fmt.Println("Error:")
	fmt.Println(err)
} else {
	fmt.Println("Write records with higher version is successful")
}
```

------
#### [  Python  ]

```
  def write_records_with_upsert(self):
    print("Writing records with upsert")
    current_time = self._current_milli_time()
    # To achieve upsert (last writer wins) semantic, one example is to use current time as the version if you are writing directly from the data source
    version = int(self._current_milli_time())

    dimensions = [
          {'Name': 'region', 'Value': 'us-east-1'},
          {'Name': 'az', 'Value': 'az1'},
          {'Name': 'hostname', 'Value': 'host1'}
        ]

    common_attributes = {
      'Dimensions': dimensions,
      'MeasureValueType': 'DOUBLE',
      'Time': current_time,
      'Version': version
    }

    cpu_utilization = {
      'MeasureName': 'cpu_utilization',
      'MeasureValue': '13.5'
    }

    memory_utilization = {
      'MeasureName': 'memory_utilization',
      'MeasureValue': '40'
    }

    records = [cpu_utilization, memory_utilization]

    # write records for first time
    try:
      result = self.client.write_records(DatabaseName=Constant.DATABASE_NAME, TableName=Constant.TABLE_NAME,
                         Records=records, CommonAttributes=common_attributes)
      print("WriteRecords Status for first time: [%s]" % result['ResponseMetadata']['HTTPStatusCode'])
    except self.client.exceptions.RejectedRecordsException as err:
      self._print_rejected_records_exceptions(err)
    except Exception as err:
      print("Error:", err)

    # Successfully retry same writeRecordsRequest with same records and versions, because writeRecords API is idempotent.
    try:
      result = self.client.write_records(DatabaseName=Constant.DATABASE_NAME, TableName=Constant.TABLE_NAME,
                         Records=records, CommonAttributes=common_attributes)
      print("WriteRecords Status for retry: [%s]" % result['ResponseMetadata']['HTTPStatusCode'])
    except self.client.exceptions.RejectedRecordsException as err:
      self._print_rejected_records_exceptions(err)
    except Exception as err:
      print("Error:", err)

    # upsert with lower version, this would fail because a higher version is required to update the measure value.
    version -= 1
    common_attributes["Version"] = version

    cpu_utilization["MeasureValue"] = '14.5'
    memory_utilization["MeasureValue"] = '50'

    upsertedRecords = [cpu_utilization, memory_utilization]

    try:
      upsertedResult = self.client.write_records(DatabaseName=Constant.DATABASE_NAME, TableName=Constant.TABLE_NAME,
                            Records=upsertedRecords, CommonAttributes=common_attributes)
      print("WriteRecords Status for upsert with lower version: [%s]" % upsertedResult['ResponseMetadata']['HTTPStatusCode'])
    except self.client.exceptions.RejectedRecordsException as err:
      self._print_rejected_records_exceptions(err)
    except Exception as err:
      print("Error:", err)


    # upsert with higher version as new data is generated
    version = int(self._current_milli_time())
    common_attributes["Version"] = version

    try:
      upsertedResult = self.client.write_records(DatabaseName=Constant.DATABASE_NAME, TableName=Constant.TABLE_NAME,
                            Records=upsertedRecords, CommonAttributes=common_attributes)
      print("WriteRecords Upsert Status: [%s]" % upsertedResult['ResponseMetadata']['HTTPStatusCode'])
    except self.client.exceptions.RejectedRecordsException as err:
      self._print_rejected_records_exceptions(err)
    except Exception as err:
      print("Error:", err)

  @staticmethod
  def _current_milli_time():
    return str(int(round(time.time() * 1000)))
```

------
#### [  Node.js  ]

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
async function writeRecordsWithUpsert() {
  console.log("Writing records with upsert");
  const currentTime = Date.now().toString(); // Unix time in milliseconds
  // To achieve upsert (last writer wins) semantic, one example is to use current time as the version if you are writing directly from the data source
  let version = Date.now();

  const dimensions = [
    {'Name': 'region', 'Value': 'us-east-1'},
    {'Name': 'az', 'Value': 'az1'},
    {'Name': 'hostname', 'Value': 'host1'}
  ];

  const commonAttributes = {
    'Dimensions': dimensions,
    'MeasureValueType': 'DOUBLE',
    'Time': currentTime.toString(),
    'Version': version
  };

  const cpuUtilization = {
    'MeasureName': 'cpu_utilization',
    'MeasureValue': '13.5'
  };

  const memoryUtilization = {
    'MeasureName': 'memory_utilization',
    'MeasureValue': '40'
  };

  const records = [cpuUtilization, memoryUtilization];

  const params = {
    DatabaseName: constants.DATABASE_NAME,
    TableName: constants.TABLE_NAME,
    Records: records,
    CommonAttributes: commonAttributes
  };

  const request = writeClient.writeRecords(params);

  // write records for first time
  await request.promise().then(
    (data) => {
      console.log("Write records successful for first time.");
    },
    (err) => {
      console.log("Error writing records:", err);
      if (err.code === 'RejectedRecordsException') {
        printRejectedRecordsException(request);
      }
    }
  );

  // Successfully retry same writeRecordsRequest with same records and versions, because writeRecords API is idempotent.
  await request.promise().then(
    (data) => {
      console.log("Write records successful for retry.");
    },
    (err) => {
      console.log("Error writing records:", err);
      if (err.code === 'RejectedRecordsException') {
        printRejectedRecordsException(request);
      }
    }
  );

  // upsert with lower version, this would fail because a higher version is required to update the measure value.
  version--;

  const commonAttributesWithLowerVersion = {
    'Dimensions': dimensions,
    'MeasureValueType': 'DOUBLE',
    'Time': currentTime.toString(),
    'Version': version
  };

  const updatedCpuUtilization = {
    'MeasureName': 'cpu_utilization',
    'MeasureValue': '14.5'
  };

  const updatedMemoryUtilization = {
    'MeasureName': 'memory_utilization',
    'MeasureValue': '50'
  };

  const upsertedRecords = [updatedCpuUtilization, updatedMemoryUtilization];

  const upsertedParamsWithLowerVersion = {
    DatabaseName: constants.DATABASE_NAME,
    TableName: constants.TABLE_NAME,
    Records: upsertedRecords,
    CommonAttributes: commonAttributesWithLowerVersion
  };

  const upsertRequestWithLowerVersion = writeClient.writeRecords(upsertedParamsWithLowerVersion);

  await upsertRequestWithLowerVersion.promise().then(
    (data) => {
      console.log("Write records for upsert with lower version successful");
    },
    (err) => {
      console.log("Error writing records:", err);
      if (err.code === 'RejectedRecordsException') {
        printRejectedRecordsException(upsertRequestWithLowerVersion);
      }
    }
  );

  // upsert with higher version as new data in generated
  version = Date.now();

  const commonAttributesWithHigherVersion = {
    'Dimensions': dimensions,
    'MeasureValueType': 'DOUBLE',
    'Time': currentTime.toString(),
    'Version': version
  };

  const upsertedParamsWithHigherVerion = {
    DatabaseName: constants.DATABASE_NAME,
    TableName: constants.TABLE_NAME,
    Records: upsertedRecords,
    CommonAttributes: commonAttributesWithHigherVersion
  };

  const upsertRequestWithHigherVersion = writeClient.writeRecords(upsertedParamsWithHigherVerion);

  await upsertRequestWithHigherVersion.promise().then(
    (data) => {
      console.log("Write records upsert successful with higher version");
    },
    (err) => {
      console.log("Error writing records:", err);
      if (err.code === 'RejectedRecordsException') {
        printRejectedRecordsException(upsertedParamsWithHigherVerion);
      }
    }
  );

}
```

------
#### [  .NET  ]

```
  public async Task WriteRecordsWithUpsert()
  {
    Console.WriteLine("Writing records with upsert");

    DateTimeOffset now = DateTimeOffset.UtcNow;
    string currentTimeString = (now.ToUnixTimeMilliseconds()).ToString();
    // To achieve upsert (last writer wins) semantic, one example is to use current time as the version if you are writing directly from the data source
    long version = now.ToUnixTimeMilliseconds();

    List<Dimension> dimensions = new List<Dimension>{
      new Dimension { Name = "region", Value = "us-east-1" },
      new Dimension { Name = "az", Value = "az1" },
      new Dimension { Name = "hostname", Value = "host1" }
    };

    var commonAttributes = new Record
    {
      Dimensions = dimensions,
      MeasureValueType = MeasureValueType.DOUBLE,
      Time = currentTimeString,
      Version = version
    };

    var cpuUtilization = new Record
    {
      MeasureName = "cpu_utilization",
      MeasureValue = "13.6"
    };

    var memoryUtilization = new Record
    {
      MeasureName = "memory_utilization",
      MeasureValue = "40"
    };


    List<Record> records = new List<Record>();
    records.Add(cpuUtilization);
    records.Add(memoryUtilization);

    // write records for first time
    try
    {
      var writeRecordsRequest = new WriteRecordsRequest
      {
        DatabaseName = Constants.DATABASE_NAME,
        TableName = Constants.TABLE_NAME,
        Records = records,
        CommonAttributes = commonAttributes
      };
      WriteRecordsResponse response = await writeClient.WriteRecordsAsync(writeRecordsRequest);
      Console.WriteLine($"WriteRecords Status for first time: {response.HttpStatusCode.ToString()}");
    }
    catch (RejectedRecordsException e) {
      PrintRejectedRecordsException(e);
    }
    catch (Exception e)
    {
      Console.WriteLine("Write records failure:" + e.ToString());
    }

    // Successfully retry same writeRecordsRequest with same records and versions, because writeRecords API is idempotent.
    try
    {
      var writeRecordsRequest = new WriteRecordsRequest
      {
        DatabaseName = Constants.DATABASE_NAME,
        TableName = Constants.TABLE_NAME,
        Records = records,
        CommonAttributes = commonAttributes
      };
      WriteRecordsResponse response = await writeClient.WriteRecordsAsync(writeRecordsRequest);
      Console.WriteLine($"WriteRecords Status for retry: {response.HttpStatusCode.ToString()}");
    }
    catch (RejectedRecordsException e) {
      PrintRejectedRecordsException(e);
    }
    catch (Exception e)
    {
      Console.WriteLine("Write records failure:" + e.ToString());
    }

    // upsert with lower version, this would fail because a higher version is required to update the measure value.
    version--;
    Type recordType = typeof(Record);
    recordType.GetProperty("Version").SetValue(commonAttributes, version);
    recordType.GetProperty("MeasureValue").SetValue(cpuUtilization, "14.6");
    recordType.GetProperty("MeasureValue").SetValue(memoryUtilization, "50");

    List<Record> upsertedRecords = new List<Record> {
      cpuUtilization,
      memoryUtilization
    };

    try
    {
      var writeRecordsUpsertRequest = new WriteRecordsRequest
      {
        DatabaseName = Constants.DATABASE_NAME,
        TableName = Constants.TABLE_NAME,
        Records = upsertedRecords,
        CommonAttributes = commonAttributes
      };
      WriteRecordsResponse upsertResponse = await writeClient.WriteRecordsAsync(writeRecordsUpsertRequest);
      Console.WriteLine($"WriteRecords Status for upsert with lower version: {upsertResponse.HttpStatusCode.ToString()}");
    }
    catch (RejectedRecordsException e) {
      PrintRejectedRecordsException(e);
    }
    catch (Exception e)
    {
      Console.WriteLine("Write records failure:" + e.ToString());
    }

    // upsert with higher version as new data in generated
    now = DateTimeOffset.UtcNow;
    version = now.ToUnixTimeMilliseconds();
    recordType.GetProperty("Version").SetValue(commonAttributes, version);

    try
    {
      var writeRecordsUpsertRequest = new WriteRecordsRequest
      {
        DatabaseName = Constants.DATABASE_NAME,
        TableName = Constants.TABLE_NAME,
        Records = upsertedRecords,
        CommonAttributes = commonAttributes
      };
      WriteRecordsResponse upsertResponse = await writeClient.WriteRecordsAsync(writeRecordsUpsertRequest);
      Console.WriteLine($"WriteRecords Status for upsert with higher version:  {upsertResponse.HttpStatusCode.ToString()}");
    }
    catch (RejectedRecordsException e) {
      PrintRejectedRecordsException(e);
    }
    catch (Exception e)
    {
      Console.WriteLine("Write records failure:" + e.ToString());
    }
  }
```

------

## Multi-measure attribute example
<a name="code-samples.write.data.multivalue"></a>

This example illustrates writing multi-mearure attributes. [Multi-measure attributes](data-modeling.md#data-modeling-multiVsinglerecords) are useful when a device or an application you are tracking emits multiple metrics or events at the same timestamp..

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
package com.amazonaws.services.timestream;

import static com.amazonaws.services.timestream.Main.DATABASE_NAME;
import static com.amazonaws.services.timestream.Main.REGION;
import static com.amazonaws.services.timestream.Main.TABLE_NAME;

import java.util.ArrayList;
import java.util.List;

import com.amazonaws.services.timestreamwrite.AmazonTimestreamWrite;
import com.amazonaws.services.timestreamwrite.model.Dimension;
import com.amazonaws.services.timestreamwrite.model.MeasureValue;
import com.amazonaws.services.timestreamwrite.model.MeasureValueType;
import com.amazonaws.services.timestreamwrite.model.Record;
import com.amazonaws.services.timestreamwrite.model.RejectedRecordsException;
import com.amazonaws.services.timestreamwrite.model.WriteRecordsRequest;
import com.amazonaws.services.timestreamwrite.model.WriteRecordsResult;


public class multimeasureAttributeExample {
  AmazonTimestreamWrite timestreamWriteClient;

  public multimeasureAttributeExample(AmazonTimestreamWrite client) {
    this.timestreamWriteClient = client;
  }

  public void writeRecordsMultiMeasureValueSingleRecord() {
    System.out.println("Writing records with multi value attributes");

    List<Record> records = new ArrayList<>();
    final long time = System.currentTimeMillis();
    long version = System.currentTimeMillis();

    List<Dimension> dimensions = new ArrayList<>();
    final Dimension region = new Dimension().withName("region").withValue(REGION);
    final Dimension az = new Dimension().withName("az").withValue("az1");
    final Dimension hostname = new Dimension().withName("hostname").withValue("host1");

    dimensions.add(region);
    dimensions.add(az);
    dimensions.add(hostname);

    Record commonAttributes = new Record()
        .withDimensions(dimensions)
        .withTime(String.valueOf(time))
        .withVersion(version);

    MeasureValue cpuUtilization = new MeasureValue()
        .withName("cpu_utilization")
        .withType(MeasureValueType.DOUBLE)
        .withValue("13.5");
    MeasureValue memoryUtilization = new MeasureValue()
        .withName("memory_utilization")
        .withType(MeasureValueType.DOUBLE)
        .withValue("40");
    Record computationalResources = new Record()
        .withMeasureName("cpu_memory")
        .withMeasureValues(cpuUtilization, memoryUtilization)
        .withMeasureValueType(MeasureValueType.MULTI);

    records.add(computationalResources);

    WriteRecordsRequest writeRecordsRequest = new WriteRecordsRequest()
        .withDatabaseName(DATABASE_NAME)
        .withTableName(TABLE_NAME)
        .withCommonAttributes(commonAttributes)
        .withRecords(records);

    // write records for first time
    try {
      WriteRecordsResult writeRecordResult = timestreamWriteClient.writeRecords(writeRecordsRequest);
      System.out.println(
          "WriteRecords Status for multi value attributes: " + writeRecordResult
              .getSdkHttpMetadata().getHttpStatusCode());
    } catch (RejectedRecordsException e) {
      printRejectedRecordsException(e);
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }
  }

  public void writeRecordsMultiMeasureValueMultipleRecords() {
    System.out.println(
        "Writing records with multi value attributes mixture type");

    List<Record> records = new ArrayList<>();
    final long time = System.currentTimeMillis();
    long version = System.currentTimeMillis();

    List<Dimension> dimensions = new ArrayList<>();
    final Dimension region = new Dimension().withName("region").withValue(REGION);
    final Dimension az = new Dimension().withName("az").withValue("az1");
    final Dimension hostname = new Dimension().withName("hostname").withValue("host1");

    dimensions.add(region);
    dimensions.add(az);
    dimensions.add(hostname);

    Record commonAttributes = new Record()
        .withDimensions(dimensions)
        .withTime(String.valueOf(time))
        .withVersion(version);

    MeasureValue cpuUtilization = new MeasureValue()
        .withName("cpu_utilization")
        .withType(MeasureValueType.DOUBLE)
        .withValue("13");
    MeasureValue memoryUtilization =new MeasureValue()
        .withName("memory_utilization")
        .withType(MeasureValueType.DOUBLE)
        .withValue("40");
    MeasureValue activeCores = new MeasureValue()
        .withName("active_cores")
        .withType(MeasureValueType.BIGINT)
        .withValue("4");


    Record computationalResources = new Record()
        .withMeasureName("computational_utilization")
        .withMeasureValues(cpuUtilization, memoryUtilization, activeCores)
        .withMeasureValueType(MeasureValueType.MULTI);

    records.add(computationalResources);

    WriteRecordsRequest writeRecordsRequest = new WriteRecordsRequest()
        .withDatabaseName(DATABASE_NAME)
        .withTableName(TABLE_NAME)
        .withCommonAttributes(commonAttributes)
        .withRecords(records);

    // write records for first time
    try {
      WriteRecordsResult writeRecordResult = timestreamWriteClient.writeRecords(writeRecordsRequest);
      System.out.println(
          "WriteRecords Status for multi value attributes: " + writeRecordResult
              .getSdkHttpMetadata().getHttpStatusCode());
    } catch (RejectedRecordsException e) {
      printRejectedRecordsException(e);
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }
  }

  private void printRejectedRecordsException(RejectedRecordsException e) {
    System.out.println("RejectedRecords: " + e);
    e.getRejectedRecords().forEach(System.out::println);
  }
}
```

------
#### [  Java v2  ]

```
package com.amazonaws.services.timestream;

import java.util.ArrayList;
import java.util.List;

import software.amazon.awssdk.services.timestreamwrite.TimestreamWriteClient;
import software.amazon.awssdk.services.timestreamwrite.model.Dimension;
import software.amazon.awssdk.services.timestreamwrite.model.MeasureValue;
import software.amazon.awssdk.services.timestreamwrite.model.MeasureValueType;
import software.amazon.awssdk.services.timestreamwrite.model.Record;
import software.amazon.awssdk.services.timestreamwrite.model.RejectedRecordsException;
import software.amazon.awssdk.services.timestreamwrite.model.WriteRecordsRequest;
import software.amazon.awssdk.services.timestreamwrite.model.WriteRecordsResponse;

import static com.amazonaws.services.timestream.Main.DATABASE_NAME;
import static com.amazonaws.services.timestream.Main.TABLE_NAME;


public class multimeasureAttributeExample {

  TimestreamWriteClient timestreamWriteClient;

  public multimeasureAttributeExample(TimestreamWriteClient client) {
    this.timestreamWriteClient = client;
  }

  public void writeRecordsMultiMeasureValueSingleRecord() {
    System.out.println("Writing records with multi value attributes");

    List<Record> records = new ArrayList<>();
    final long time = System.currentTimeMillis();
    long version = System.currentTimeMillis();

    List<Dimension> dimensions = new ArrayList<>();
    final Dimension region =
        Dimension.builder().name("region").value("us-east-1").build();
    final Dimension az = Dimension.builder().name("az").value("az1").build();
    final Dimension hostname =
        Dimension.builder().name("hostname").value("host1").build();

    dimensions.add(region);
    dimensions.add(az);
    dimensions.add(hostname);

    Record commonAttributes = Record.builder()
        .dimensions(dimensions)
        .time(String.valueOf(time))
        .version(version)
        .build();

    MeasureValue cpuUtilization = MeasureValue.builder()
        .name("cpu_utilization")
        .type(MeasureValueType.DOUBLE)
        .value("13.5").build();
    MeasureValue memoryUtilization = MeasureValue.builder()
        .name("memory_utilization")
        .type(MeasureValueType.DOUBLE)
        .value("40").build();
    Record computationalResources = Record
        .builder()
        .measureName("cpu_memory")
        .measureValues(cpuUtilization, memoryUtilization)
        .measureValueType(MeasureValueType.MULTI)
        .build();

    records.add(computationalResources);

    WriteRecordsRequest writeRecordsRequest = WriteRecordsRequest.builder()
        .databaseName(DATABASE_NAME)
        .tableName(TABLE_NAME)
        .commonAttributes(commonAttributes)
        .records(records).build();

    // write records for first time
    try {
      WriteRecordsResponse writeRecordsResponse = timestreamWriteClient.writeRecords(writeRecordsRequest);
      System.out.println(
          "WriteRecords Status for multi value attributes: " + writeRecordsResponse
              .sdkHttpResponse()
              .statusCode());
    } catch (RejectedRecordsException e) {
      printRejectedRecordsException(e);
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }
  }

  public void writeRecordsMultiMeasureValueMultipleRecords() {
    System.out.println(
        "Writing records with multi value attributes mixture type");

    List<Record> records = new ArrayList<>();
    final long time = System.currentTimeMillis();
    long version = System.currentTimeMillis();

    List<Dimension> dimensions = new ArrayList<>();
    final Dimension region =
        Dimension.builder().name("region").value("us-east-1").build();
    final Dimension az = Dimension.builder().name("az").value("az1").build();
    final Dimension hostname =
        Dimension.builder().name("hostname").value("host1").build();

    dimensions.add(region);
    dimensions.add(az);
    dimensions.add(hostname);

    Record commonAttributes = Record.builder()
        .dimensions(dimensions)
        .time(String.valueOf(time))
        .version(version)
        .build();

    MeasureValue cpuUtilization = MeasureValue.builder()
        .name("cpu_utilization")
        .type(MeasureValueType.DOUBLE)
        .value("13.5").build();
    MeasureValue memoryUtilization = MeasureValue.builder()
        .name("memory_utilization")
        .type(MeasureValueType.DOUBLE)
        .value("40").build();
    MeasureValue activeCores = MeasureValue.builder()
        .name("active_cores")
        .type(MeasureValueType.BIGINT)
        .value("4").build();


    Record computationalResources = Record
        .builder()
        .measureName("computational_utilization")
        .measureValues(cpuUtilization, memoryUtilization, activeCores)
        .measureValueType(MeasureValueType.MULTI)
        .build();

    records.add(computationalResources);

    WriteRecordsRequest writeRecordsRequest = WriteRecordsRequest.builder()
        .databaseName(DATABASE_NAME)
        .tableName(TABLE_NAME)
        .commonAttributes(commonAttributes)
        .records(records).build();

    // write records for first time
    try {
      WriteRecordsResponse writeRecordsResponse = timestreamWriteClient.writeRecords(writeRecordsRequest);
      System.out.println(
          "WriteRecords Status for multi value attributes: " + writeRecordsResponse
              .sdkHttpResponse()
              .statusCode());
    } catch (RejectedRecordsException e) {
      printRejectedRecordsException(e);
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }
  }

  private void printRejectedRecordsException(RejectedRecordsException e) {
    System.out.println("RejectedRecords: " + e);
    e.rejectedRecords().forEach(System.out::println);
  }
}
```

------
#### [  Go  ]

```
  now := time.Now()
  currentTimeInSeconds := now.Unix()
  writeRecordsInput := &timestreamwrite.WriteRecordsInput{
    DatabaseName: aws.String(*databaseName),
    TableName:  aws.String(*tableName),
    Records: []*timestreamwrite.Record{
    &timestreamwrite.Record{
      Dimensions: []*timestreamwrite.Dimension{
      &timestreamwrite.Dimension{
        Name:  aws.String("region"),
        Value: aws.String("us-east-1"),
      },
      &timestreamwrite.Dimension{
        Name:  aws.String("az"),
        Value: aws.String("az1"),
      },
      &timestreamwrite.Dimension{
        Name:  aws.String("hostname"),
        Value: aws.String("host1"),
      },
      },
      MeasureName:  aws.String("metrics"),
      MeasureValueType: aws.String("MULTI"),
      Time:     aws.String(strconv.FormatInt(currentTimeInSeconds, 10)),
      TimeUnit:  aws.String("SECONDS"),
      MeasureValues: []*timestreamwrite.MeasureValue{
      &timestreamwrite.MeasureValue{
        Name:  aws.String("cpu_utilization"),
        Value: aws.String("13.5"),
        Type:  aws.String("DOUBLE"),
      }, 
      &timestreamwrite.MeasureValue{
        Name:  aws.String("memory_utilization"),
        Value: aws.String("40"),
        Type:  aws.String("DOUBLE"),
      },
      },
    },
    },
  }
   
  _, err = writeSvc.WriteRecords(writeRecordsInput)
   
  if err != nil {
    fmt.Println("Error:")
    fmt.Println(err)
  } else {
    fmt.Println("Write records is successful")
  }
```

------
#### [  Python  ]

```
import time
import boto3
import psutil
import os

from botocore.config import Config

DATABASE_NAME = os.environ['DATABASE_NAME']
TABLE_NAME = os.environ['TABLE_NAME']

COUNTRY = "UK"
CITY = "London"
HOSTNAME = "MyHostname" # You can make it dynamic using socket.gethostname()

INTERVAL = 1 # Seconds

def prepare_common_attributes():
  common_attributes = {
    'Dimensions': [
      {'Name': 'country', 'Value': COUNTRY},
      {'Name': 'city', 'Value': CITY},
      {'Name': 'hostname', 'Value': HOSTNAME}
    ],
    'MeasureName': 'utilization',
    'MeasureValueType': 'MULTI'
  }
  return common_attributes


def prepare_record(current_time):
  record = {
    'Time': str(current_time),
    'MeasureValues': []
  }
  return record


def prepare_measure(measure_name, measure_value):
  measure = {
    'Name': measure_name,
    'Value': str(measure_value),
    'Type': 'DOUBLE'
  }
  return measure


def write_records(records, common_attributes):
  try:
    result = write_client.write_records(DatabaseName=DATABASE_NAME,
                                        TableName=TABLE_NAME,
                                        CommonAttributes=common_attributes,
                                        Records=records)
    status = result['ResponseMetadata']['HTTPStatusCode']
    print("Processed %d records. WriteRecords HTTPStatusCode: %s" %
        (len(records), status))
  except Exception as err:
    print("Error:", err)


if __name__ == '__main__':

  print("writing data to database {} table {}".format(
    DATABASE_NAME, TABLE_NAME))

  session = boto3.Session()
  write_client = session.client('timestream-write', config=Config(
    read_timeout=20, max_pool_connections=5000, retries={'max_attempts': 10}))
  query_client = session.client('timestream-query') # Not used

  common_attributes = prepare_common_attributes()

  records = []

  while True:

    current_time = int(time.time() * 1000)
    cpu_utilization = psutil.cpu_percent()
    memory_utilization = psutil.virtual_memory().percent
    swap_utilization = psutil.swap_memory().percent
    disk_utilization = psutil.disk_usage('/').percent

    record = prepare_record(current_time)
    record['MeasureValues'].append(prepare_measure('cpu', cpu_utilization))
    record['MeasureValues'].append(prepare_measure('memory', memory_utilization))
    record['MeasureValues'].append(prepare_measure('swap', swap_utilization))
    record['MeasureValues'].append(prepare_measure('disk', disk_utilization))

    records.append(record)

    print("records {} - cpu {} - memory {} - swap {} - disk {}".format(
      len(records), cpu_utilization, memory_utilization,
      swap_utilization, disk_utilization))

    if len(records) == 100:
      write_records(records, common_attributes)
      records = []

    time.sleep(INTERVAL)
```

------
#### [  Node.js  ]

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
  async function writeRecords() {
    console.log("Writing records");
    const currentTime = Date.now().toString(); // Unix time in milliseconds

    const dimensions = [
    {'Name': 'region', 'Value': 'us-east-1'},
    {'Name': 'az', 'Value': 'az1'},
    {'Name': 'hostname', 'Value': 'host1'}
    ];

    const record = {
    'Dimensions': dimensions,
    'MeasureName': 'metrics',
    'MeasureValues': [
      {
        'Name': 'cpu_utilization',
        'Value': '40',
        'Type': 'DOUBLE',
      },
      {
        'Name': 'memory_utilization',
        'Value': '13.5',
        'Type': 'DOUBLE',
      },
      ],
      'MeasureValueType': 'MULTI',
      'Time': currentTime.toString()
    }

    const records = [record];

    const params = {
    DatabaseName: 'DatabaseName',
    TableName: 'TableName',
    Records: records
    };

    const response = await writeClient.writeRecords(params);

    console.log(response);
  }
```

------
#### [  .NET  ]

```
using System;
using System.IO;
using System.Collections.Generic;
using Amazon.TimestreamWrite;
using Amazon.TimestreamWrite.Model;
using System.Threading.Tasks;

namespace TimestreamDotNetSample
{
  static class MultiMeasureValueConstants
  {
    public const string MultiMeasureValueSampleDb = "multiMeasureValueSampleDb";
    public const string MultiMeasureValueSampleTable = "multiMeasureValueSampleTable";
  }

  public class MultiValueAttributesExample
  {
    private readonly AmazonTimestreamWriteClient writeClient;

    public MultiValueAttributesExample(AmazonTimestreamWriteClient writeClient)
    {
      this.writeClient = writeClient;
    }

    public async Task WriteRecordsMultiMeasureValueSingleRecord()
    {
      Console.WriteLine("Writing records with multi value attributes");

      DateTimeOffset now = DateTimeOffset.UtcNow;
      string currentTimeString = (now.ToUnixTimeMilliseconds()).ToString();

      List<Dimension> dimensions = new List<Dimension>{
        new Dimension { Name = "region", Value = "us-east-1" },
        new Dimension { Name = "az", Value = "az1" },
        new Dimension { Name = "hostname", Value = "host1" }
      };

      var commonAttributes = new Record
      {
        Dimensions = dimensions,
        Time = currentTimeString
      };

      var cpuUtilization = new MeasureValue
      {
        Name = "cpu_utilization",
        Value = "13.6",
        Type = "DOUBLE"
      };

      var memoryUtilization = new MeasureValue
      {
        Name = "memory_utilization",
        Value = "40",
        Type = "DOUBLE"
      };

      var computationalRecord = new Record
      {
        MeasureName = "cpu_memory",
        MeasureValues = new List<MeasureValue> {cpuUtilization, memoryUtilization},
        MeasureValueType = "MULTI"
      };


      List<Record> records = new List<Record>();
      records.Add(computationalRecord);

      try
      {
        var writeRecordsRequest = new WriteRecordsRequest
        {
          DatabaseName = MultiMeasureValueConstants.MultiMeasureValueSampleDb,
          TableName = MultiMeasureValueConstants.MultiMeasureValueSampleTable,
          Records = records,
          CommonAttributes = commonAttributes
        };
        WriteRecordsResponse response = await writeClient.WriteRecordsAsync(writeRecordsRequest);
        Console.WriteLine($"Write records status code: {response.HttpStatusCode.ToString()}");
      }
      catch (Exception e)
      {
        Console.WriteLine("Write records failure:" + e.ToString());
      }
    }

    public async Task WriteRecordsMultiMeasureValueMultipleRecords()
    {
      Console.WriteLine("Writing records with multi value attributes mixture type");

      DateTimeOffset now = DateTimeOffset.UtcNow;
      string currentTimeString = (now.ToUnixTimeMilliseconds()).ToString();

      List<Dimension> dimensions = new List<Dimension>{
        new Dimension { Name = "region", Value = "us-east-1" },
        new Dimension { Name = "az", Value = "az1" },
        new Dimension { Name = "hostname", Value = "host1" }
      };

      var commonAttributes = new Record
      {
        Dimensions = dimensions,
        Time = currentTimeString
      };

      var cpuUtilization = new MeasureValue
      {
        Name = "cpu_utilization",
        Value = "13.6",
        Type = "DOUBLE"
      };

      var memoryUtilization = new MeasureValue
      {
        Name = "memory_utilization",
        Value = "40",
        Type = "DOUBLE"
      };

      var activeCores = new MeasureValue
      {
        Name = "active_cores",
        Value = "4",
        Type = "BIGINT"
      };

      var computationalRecord = new Record
      {
        MeasureName = "computational_utilization",
        MeasureValues = new List<MeasureValue> {cpuUtilization, memoryUtilization, activeCores},
        MeasureValueType = "MULTI"
      };

      var aliveRecord = new Record
      {
        MeasureName = "is_healthy",
        MeasureValue = "true",
        MeasureValueType = "BOOLEAN"
      };

      List<Record> records = new List<Record>();
      records.Add(computationalRecord);
      records.Add(aliveRecord);

      try
      {
        var writeRecordsRequest = new WriteRecordsRequest
        {
          DatabaseName = MultiMeasureValueConstants.MultiMeasureValueSampleDb,
          TableName = MultiMeasureValueConstants.MultiMeasureValueSampleTable,
          Records = records,
          CommonAttributes = commonAttributes
        };
        WriteRecordsResponse response = await writeClient.WriteRecordsAsync(writeRecordsRequest);
        Console.WriteLine($"Write records status code: {response.HttpStatusCode.ToString()}");
      }
      catch (Exception e)
      {
        Console.WriteLine("Write records failure:" + e.ToString());
      }
    }
  }
}
```

------

## Handling write failures
<a name="code-samples.write.rejectedRecordException"></a>

Writes in Amazon Timestream can fail for one or more of the following reasons:
+ There are records with timestamps that lie outside the retention duration of the memory store.
+ There are records containing dimensions and/or measures that exceed the Timestream defined limits.
+ Amazon Timestream has detected duplicate records. Records are marked as duplicate, when there are multiple records with the same dimensions, timestamps, and measure names but:
  + Measure values are different.
  + Version is not present in the request or the value of version in the new record is equal to or lower than the existing value. If Amazon Timestream rejects data for this reason, the `ExistingVersion` field in the `RejectedRecords` will contain the record's current version as stored in Amazon Timestream. To force an update, you can resend the request with a version for the record set to a value greater than the `ExistingVersion`.

For more information about errors and rejected records, see [Errors](https://docs.aws.amazon.com/timestream/latest/developerguide/API_WriteRecords.html#API_WriteRecords_Errors) and [RejectedRecord](https://docs.aws.amazon.com/timestream/latest/developerguide/API_RejectedRecord.html).

If your application receives a `RejectedRecordsException` when attempting to write records to Timestream, you can parse the rejected records to learn more about the write failures as shown below.

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
  try {
    WriteRecordsResult writeRecordsResult = amazonTimestreamWrite.writeRecords(writeRecordsRequest);
    System.out.println("WriteRecords Status: " + writeRecordsResult.getSdkHttpMetadata().getHttpStatusCode());
  } catch (RejectedRecordsException e) {
    System.out.println("RejectedRecords: " + e);
    for (RejectedRecord rejectedRecord : e.getRejectedRecords()) {
      System.out.println("Rejected Index " + rejectedRecord.getRecordIndex() + ": "
          + rejectedRecord.getReason());
    }
    System.out.println("Other records were written successfully. ");
  } catch (Exception e) {
    System.out.println("Error: " + e);
  }
```

------
#### [  Java v2  ]

```
    try {
      WriteRecordsResponse writeRecordsResponse = timestreamWriteClient.writeRecords(writeRecordsRequest);
      System.out.println("writeRecordsWithCommonAttributes Status: " + writeRecordsResponse.sdkHttpResponse().statusCode());
    } catch (RejectedRecordsException e) {
      System.out.println("RejectedRecords: " + e);
      for (RejectedRecord rejectedRecord : e.rejectedRecords()) {
        System.out.println("Rejected Index " + rejectedRecord.recordIndex() + ": "
            + rejectedRecord.reason());
      }
      System.out.println("Other records were written successfully. ");
    } catch (Exception e) {
      System.out.println("Error: " + e);
    }
```

------
#### [  Go  ]

```
_, err = writeSvc.WriteRecords(writeRecordsInput)

if err != nil {
  fmt.Println("Error:")
  fmt.Println(err)
} else {
  fmt.Println("Write records is successful")
}
```

------
#### [  Python  ]

```
try:
  result = self.client.write_records(DatabaseName=Constant.DATABASE_NAME, TableName=Constant.TABLE_NAME, Records=records, CommonAttributes=common_attributes)
  print("WriteRecords Status: [%s]" % result['ResponseMetadata']['HTTPStatusCode'])
except self.client.exceptions.RejectedRecordsException as err:
  print("RejectedRecords: ", err)
  for rr in err.response["RejectedRecords"]:
    print("Rejected Index " + str(rr["RecordIndex"]) + ": " + rr["Reason"])
  print("Other records were written successfully. ")
except Exception as err:
  print("Error:", err)
```

------
#### [  Node.js  ]

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
await request.promise().then(
    (data) => {
      console.log("Write records successful");
    },
    (err) => {
      console.log("Error writing records:", err);
      if (err.code === 'RejectedRecordsException') {
        const responsePayload = JSON.parse(request.response.httpResponse.body.toString());
        console.log("RejectedRecords: ", responsePayload.RejectedRecords);
        console.log("Other records were written successfully. ");
      }
    }
  );
```

------
#### [  .NET  ]

```
  try
  {
    var writeRecordsRequest = new WriteRecordsRequest
    {
      DatabaseName = Constants.DATABASE_NAME,
      TableName = Constants.TABLE_NAME,
      Records = records,
      CommonAttributes = commonAttributes
    };
    WriteRecordsResponse response = await writeClient.WriteRecordsAsync(writeRecordsRequest);
    Console.WriteLine($"Write records status code: {response.HttpStatusCode.ToString()}");
  }
  catch (RejectedRecordsException e) {
    Console.WriteLine("RejectedRecordsException:" + e.ToString());
    foreach (RejectedRecord rr in e.RejectedRecords) {
      Console.WriteLine("RecordIndex " + rr.RecordIndex + " : " + rr.Reason);
    }
    Console.WriteLine("Other records were written successfully. ");
  }
  catch (Exception e)
  {
    Console.WriteLine("Write records failure:" + e.ToString());
  }
```

------

# Run query
<a name="code-samples.run-query"></a>

**Topics**
+ [Paginating results](#code-samples.run-query.pagination)
+ [Parsing result sets](#code-samples.run-query.parsing)
+ [Accessing the query status](#code-samples.run-query.query-status)

## Paginating results
<a name="code-samples.run-query.pagination"></a>

When you run a query, Timestream returns the result set in a paginated manner to optimize the responsiveness of your applications. The code snippet below shows how you can paginate through the result set. You must loop through all the result set pages until you encounter a null value. Pagination tokens expire 3 hours after being issued by Timestream for LiveAnalytics. 

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
    private void runQuery(String queryString) {
        try {
            QueryRequest queryRequest = new QueryRequest();
            queryRequest.setQueryString(queryString);
            QueryResult queryResult = queryClient.query(queryRequest);
            while (true) {
                parseQueryResult(queryResult);
                if (queryResult.getNextToken() == null) {
                    break;
                }
                queryRequest.setNextToken(queryResult.getNextToken());
                queryResult = queryClient.query(queryRequest);
            }
        } catch (Exception e) {
            // Some queries might fail with 500 if the result of a sequence function has more than 10000 entries
            e.printStackTrace();
        }
    }
```

------
#### [  Java v2  ]

```
    private void runQuery(String queryString) {
        try {
            QueryRequest queryRequest = QueryRequest.builder().queryString(queryString).build();
            final QueryIterable queryResponseIterator = timestreamQueryClient.queryPaginator(queryRequest);
            for(QueryResponse queryResponse : queryResponseIterator) {
                parseQueryResult(queryResponse);
            }
        } catch (Exception e) {
            // Some queries might fail with 500 if the result of a sequence function has more than 10000 entries
            e.printStackTrace();
        }
    }
```

------
#### [  Go  ]

```
func runQuery(queryPtr *string, querySvc *timestreamquery.TimestreamQuery, f *os.File) {
    queryInput := &timestreamquery.QueryInput{
        QueryString: aws.String(*queryPtr),
    }
    fmt.Println("QueryInput:")
    fmt.Println(queryInput)
    // execute the query
    err := querySvc.QueryPages(queryInput,
        func(page *timestreamquery.QueryOutput, lastPage bool) bool {
            // process query response
            queryStatus := page.QueryStatus
            fmt.Println("Current query status:", queryStatus)
            // query response metadata
            // includes column names and types
            metadata := page.ColumnInfo
            // fmt.Println("Metadata:")
            fmt.Println(metadata)
            header := ""
            for i := 0; i < len(metadata); i++ {
                header += *metadata[i].Name
                if i != len(metadata)-1 {
                    header += ", "
                }
            }
            write(f, header)

            // query response data
            fmt.Println("Data:")
            // process rows
            rows := page.Rows
            for i := 0; i < len(rows); i++ {
                data := rows[i].Data
                value := processRowType(data, metadata)
                fmt.Println(value)
                write(f, value)
            }
            fmt.Println("Number of rows:", len(page.Rows))
            return true
        })
    if err != nil {
        fmt.Println("Error:")
        fmt.Println(err)
    }
}
```

------
#### [  Python  ]

```
    def run_query(self, query_string):
        try:
            page_iterator = self.paginator.paginate(QueryString=query_string)
            for page in page_iterator:
                self._parse_query_result(page)
        except Exception as err:
            print("Exception while running query:", err)
```

------
#### [  Node.js  ]

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
async function getAllRows(query, nextToken) {
    const params = {
        QueryString: query
    };

    if (nextToken) {
        params.NextToken = nextToken;
    }

    await queryClient.query(params).promise()
        .then(
            (response) => {
                parseQueryResult(response);
                if (response.NextToken) {
                    getAllRows(query, response.NextToken);
                }
            },
            (err) => {
                console.error("Error while querying:", err);
            });
}
```

------
#### [  .NET  ]

```
        private async Task RunQueryAsync(string queryString)
        {
            try
            {
                QueryRequest queryRequest = new QueryRequest();
                queryRequest.QueryString = queryString;
                QueryResponse queryResponse = await queryClient.QueryAsync(queryRequest);
                while (true)
                {
                    ParseQueryResult(queryResponse);
                    if (queryResponse.NextToken == null)
                    {
                        break;
                    }
                    queryRequest.NextToken = queryResponse.NextToken;
                    queryResponse = await queryClient.QueryAsync(queryRequest);
                }
            } catch(Exception e)
            {
                // Some queries might fail with 500 if the result of a sequence function has more than 10000 entries
                Console.WriteLine(e.ToString());
            }
        }
```

------

## Parsing result sets
<a name="code-samples.run-query.parsing"></a>

You can use the following code snippets to extract data from the result set. Query results are accessible for up to 24 hours after a query completes.

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
    private static final DateTimeFormatter TIMESTAMP_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSSSS");
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss.SSSSSSSSS");
    
    private static final long ONE_GB_IN_BYTES = 1073741824L;
    
    private void parseQueryResult(QueryResult response) {
        final QueryStatus currentStatusOfQuery = queryResult.getQueryStatus();
    
        System.out.println("Query progress so far: " + currentStatusOfQuery.getProgressPercentage() + "%");
        
        double bytesScannedSoFar = ((double) currentStatusOfQuery.getCumulativeBytesScanned() / ONE_GB_IN_BYTES);
        System.out.println("Bytes scanned so far: " + bytesScannedSoFar + " GB");
        
        double bytesMeteredSoFar = ((double) currentStatusOfQuery.getCumulativeBytesMetered() / ONE_GB_IN_BYTES);
        System.out.println("Bytes metered so far: " + bytesMeteredSoFar + " GB");
        
        List<ColumnInfo> columnInfo = response.getColumnInfo();
        List<Row> rows = response.getRows();
 
        System.out.println("Metadata: " + columnInfo);
        System.out.println("Data: ");
 
        // iterate every row
        for (Row row : rows) {
            System.out.println(parseRow(columnInfo, row));
        }
    }
 
    private String parseRow(List<ColumnInfo> columnInfo, Row row) {
        List<Datum> data = row.getData();
        List<String> rowOutput = new ArrayList<>();
        // iterate every column per row
        for (int j = 0; j < data.size(); j++) {
            ColumnInfo info = columnInfo.get(j);
            Datum datum = data.get(j);
            rowOutput.add(parseDatum(info, datum));
        }
        return String.format("{%s}", rowOutput.stream().map(Object::toString).collect(Collectors.joining(",")));
    }
 
    private String parseDatum(ColumnInfo info, Datum datum) {
        if (datum.isNullValue() != null && datum.isNullValue()) {
            return info.getName() + "=" + "NULL";
        }
        Type columnType = info.getType();
        // If the column is of TimeSeries Type
        if (columnType.getTimeSeriesMeasureValueColumnInfo() != null) {
            return parseTimeSeries(info, datum);
        }
        // If the column is of Array Type
        else if (columnType.getArrayColumnInfo() != null) {
            List<Datum> arrayValues = datum.getArrayValue();
            return info.getName() + "=" + parseArray(info.getType().getArrayColumnInfo(), arrayValues);
        }
        // If the column is of Row Type
        else if (columnType.getRowColumnInfo() != null) {
            List<ColumnInfo> rowColumnInfo = info.getType().getRowColumnInfo();
            Row rowValues = datum.getRowValue();
            return parseRow(rowColumnInfo, rowValues);
        }
        // If the column is of Scalar Type
        else {
            return parseScalarType(info, datum);
        }
    }
 
    private String parseTimeSeries(ColumnInfo info, Datum datum) {
        List<String> timeSeriesOutput = new ArrayList<>();
        for (TimeSeriesDataPoint dataPoint : datum.getTimeSeriesValue()) {
            timeSeriesOutput.add("{time=" + dataPoint.getTime() + ", value=" +
                    parseDatum(info.getType().getTimeSeriesMeasureValueColumnInfo(), dataPoint.getValue()) + "}");
        }
        return String.format("[%s]", timeSeriesOutput.stream().map(Object::toString).collect(Collectors.joining(",")));
    }
 
    private String parseScalarType(ColumnInfo info, Datum datum) {
        switch (ScalarType.fromValue(info.getType().getScalarType())) {
            case VARCHAR:
                return parseColumnName(info) + datum.getScalarValue();
            case BIGINT:
                Long longValue = Long.valueOf(datum.getScalarValue());
                return parseColumnName(info) + longValue;
            case INTEGER:
                Integer intValue = Integer.valueOf(datum.getScalarValue());
                return parseColumnName(info) + intValue;
            case BOOLEAN:
                Boolean booleanValue = Boolean.valueOf(datum.getScalarValue());
                return parseColumnName(info) + booleanValue;
            case DOUBLE:
                Double doubleValue = Double.valueOf(datum.getScalarValue());
                return parseColumnName(info) + doubleValue;
            case TIMESTAMP:
                return parseColumnName(info) + LocalDateTime.parse(datum.getScalarValue(), TIMESTAMP_FORMATTER);
            case DATE:
                return parseColumnName(info) + LocalDate.parse(datum.getScalarValue(), DATE_FORMATTER);
            case TIME:
                return parseColumnName(info) + LocalTime.parse(datum.getScalarValue(), TIME_FORMATTER);
            case INTERVAL_DAY_TO_SECOND:
            case INTERVAL_YEAR_TO_MONTH:
                return parseColumnName(info) + datum.getScalarValue();
            case UNKNOWN:
                return parseColumnName(info) + datum.getScalarValue();
            default:
                throw new IllegalArgumentException("Given type is not valid: " + info.getType().getScalarType());
        }
    }
 
    private String parseColumnName(ColumnInfo info) {
        return info.getName() == null ? "" : info.getName() + "=";
    }
 
    private String parseArray(ColumnInfo arrayColumnInfo, List<Datum> arrayValues) {
        List<String> arrayOutput = new ArrayList<>();
        for (Datum datum : arrayValues) {
            arrayOutput.add(parseDatum(arrayColumnInfo, datum));
        }
        return String.format("[%s]", arrayOutput.stream().map(Object::toString).collect(Collectors.joining(",")));
    }
```

------
#### [  Java v2  ]

```
    private static final long ONE_GB_IN_BYTES = 1073741824L;

    private void parseQueryResult(QueryResponse response) {
        final QueryStatus currentStatusOfQuery = response.queryStatus();

        System.out.println("Query progress so far: " + currentStatusOfQuery.progressPercentage() + "%");
        
        double bytesScannedSoFar = ((double) currentStatusOfQuery.cumulativeBytesScanned() / ONE_GB_IN_BYTES);
        System.out.println("Bytes scanned so far: " + bytesScannedSoFar + " GB");
        
        double bytesMeteredSoFar = ((double) currentStatusOfQuery.cumulativeBytesMetered() / ONE_GB_IN_BYTES);
        System.out.println("Bytes metered so far: " + bytesMeteredSoFar + " GB");
        
        List<ColumnInfo> columnInfo = response.columnInfo();
        List<Row> rows = response.rows();

        System.out.println("Metadata: " + columnInfo);
        System.out.println("Data: ");

        // iterate every row
        for (Row row : rows) {
            System.out.println(parseRow(columnInfo, row));
        }
    }

    private String parseRow(List<ColumnInfo> columnInfo, Row row) {
        List<Datum> data = row.data();
        List<String> rowOutput = new ArrayList<>();
        // iterate every column per row
        for (int j = 0; j < data.size(); j++) {
            ColumnInfo info = columnInfo.get(j);
            Datum datum = data.get(j);
            rowOutput.add(parseDatum(info, datum));
        }
        return String.format("{%s}", rowOutput.stream().map(Object::toString).collect(Collectors.joining(",")));
    }

    private String parseDatum(ColumnInfo info, Datum datum) {
        if (datum.nullValue() != null && datum.nullValue()) {
            return info.name() + "=" + "NULL";
        }
        Type columnType = info.type();
        // If the column is of TimeSeries Type
        if (columnType.timeSeriesMeasureValueColumnInfo() != null) {
            return parseTimeSeries(info, datum);
        }
        // If the column is of Array Type
        else if (columnType.arrayColumnInfo() != null) {
            List<Datum> arrayValues = datum.arrayValue();
            return info.name() + "=" + parseArray(info.type().arrayColumnInfo(), arrayValues);
        }
        // If the column is of Row Type
        else if (columnType.rowColumnInfo() != null && columnType.rowColumnInfo().size() > 0) {
            List<ColumnInfo> rowColumnInfo = info.type().rowColumnInfo();
            Row rowValues = datum.rowValue();
            return parseRow(rowColumnInfo, rowValues);
        }
        // If the column is of Scalar Type
        else {
            return parseScalarType(info, datum);
        }
    }

    private String parseTimeSeries(ColumnInfo info, Datum datum) {
        List<String> timeSeriesOutput = new ArrayList<>();
        for (TimeSeriesDataPoint dataPoint : datum.timeSeriesValue()) {
            timeSeriesOutput.add("{time=" + dataPoint.time() + ", value=" +
                    parseDatum(info.type().timeSeriesMeasureValueColumnInfo(), dataPoint.value()) + "}");
        }
        return String.format("[%s]", timeSeriesOutput.stream().map(Object::toString).collect(Collectors.joining(",")));
    }

    private String parseScalarType(ColumnInfo info, Datum datum) {
        return parseColumnName(info) + datum.scalarValue();
    }

    private String parseColumnName(ColumnInfo info) {
        return info.name() == null ? "" : info.name() + "=";
    }

    private String parseArray(ColumnInfo arrayColumnInfo, List<Datum> arrayValues) {
        List<String> arrayOutput = new ArrayList<>();
        for (Datum datum : arrayValues) {
            arrayOutput.add(parseDatum(arrayColumnInfo, datum));
        }
        return String.format("[%s]", arrayOutput.stream().map(Object::toString).collect(Collectors.joining(",")));
    }
```

------
#### [  Go  ]

```
func processScalarType(data *timestreamquery.Datum) string {
    return *data.ScalarValue
}

func processTimeSeriesType(data []*timestreamquery.TimeSeriesDataPoint, columnInfo *timestreamquery.ColumnInfo) string {
    value := ""
    for k := 0; k < len(data); k++ {
        time := data[k].Time
        value += *time + ":"
        if columnInfo.Type.ScalarType != nil {
            value += processScalarType(data[k].Value)
        } else if columnInfo.Type.ArrayColumnInfo != nil {
            value += processArrayType(data[k].Value.ArrayValue, columnInfo.Type.ArrayColumnInfo)
        } else if columnInfo.Type.RowColumnInfo != nil {
            value += processRowType(data[k].Value.RowValue.Data, columnInfo.Type.RowColumnInfo)
        } else {
            fail("Bad data type")
        }
        if k != len(data)-1 {
            value += ", "
        }
    }
    return value
}

func processArrayType(datumList []*timestreamquery.Datum, columnInfo *timestreamquery.ColumnInfo) string {
    value := ""
    for k := 0; k < len(datumList); k++ {
        if columnInfo.Type.ScalarType != nil {
            value += processScalarType(datumList[k])
        } else if columnInfo.Type.TimeSeriesMeasureValueColumnInfo != nil {
            value += processTimeSeriesType(datumList[k].TimeSeriesValue, columnInfo.Type.TimeSeriesMeasureValueColumnInfo)
        } else if columnInfo.Type.ArrayColumnInfo != nil {
            value += "["
            value += processArrayType(datumList[k].ArrayValue, columnInfo.Type.ArrayColumnInfo)
            value += "]"
        } else if columnInfo.Type.RowColumnInfo != nil {
            value += "["
            value += processRowType(datumList[k].RowValue.Data, columnInfo.Type.RowColumnInfo)
            value += "]"
        } else {
            fail("Bad column type")
        }

        if k != len(datumList)-1 {
            value += ", "
        }
    }
    return value
}

func processRowType(data []*timestreamquery.Datum, metadata []*timestreamquery.ColumnInfo) string {
    value := ""
    for j := 0; j < len(data); j++ {
        if metadata[j].Type.ScalarType != nil {
            // process simple data types
            value += processScalarType(data[j])
        } else if metadata[j].Type.TimeSeriesMeasureValueColumnInfo != nil {
            // fmt.Println("Timeseries measure value column info")
            // fmt.Println(metadata[j].Type.TimeSeriesMeasureValueColumnInfo.Type)
            datapointList := data[j].TimeSeriesValue
            value += "["
            value += processTimeSeriesType(datapointList, metadata[j].Type.TimeSeriesMeasureValueColumnInfo)
            value += "]"
        } else if metadata[j].Type.ArrayColumnInfo != nil {
            columnInfo := metadata[j].Type.ArrayColumnInfo
            // fmt.Println("Array column info")
            // fmt.Println(columnInfo)
            datumList := data[j].ArrayValue
            value += "["
            value += processArrayType(datumList, columnInfo)
            value += "]"
        } else if metadata[j].Type.RowColumnInfo != nil {
            columnInfo := metadata[j].Type.RowColumnInfo
            datumList := data[j].RowValue.Data
            value += "["
            value += processRowType(datumList, columnInfo)
            value += "]"
        } else {
            panic("Bad column type")
        }
        // comma seperated column values
        if j != len(data)-1 {
            value += ", "
        }
    }
    return value
}
```

------
#### [  Python  ]

```
    def _parse_query_result(self, query_result):
        query_status = query_result["QueryStatus"]

        progress_percentage = query_status["ProgressPercentage"]
        print(f"Query progress so far: {progress_percentage}%")

        bytes_scanned = float(query_status["CumulativeBytesScanned"]) / ONE_GB_IN_BYTES
        print(f"Data scanned so far: {bytes_scanned} GB")

        bytes_metered = float(query_status["CumulativeBytesMetered"]) / ONE_GB_IN_BYTES
        print(f"Data metered so far: {bytes_metered} GB")

        column_info = query_result['ColumnInfo']

        print("Metadata: %s" % column_info)
        print("Data: ")
        for row in query_result['Rows']:
            print(self._parse_row(column_info, row))

    def _parse_row(self, column_info, row):
        data = row['Data']
        row_output = []
        for j in range(len(data)):
            info = column_info[j]
            datum = data[j]
            row_output.append(self._parse_datum(info, datum))

        return "{%s}" % str(row_output)

    def _parse_datum(self, info, datum):
        if datum.get('NullValue', False):
            return "%s=NULL" % info['Name'],

        column_type = info['Type']

        # If the column is of TimeSeries Type
        if 'TimeSeriesMeasureValueColumnInfo' in column_type:
            return self._parse_time_series(info, datum)

        # If the column is of Array Type
        elif 'ArrayColumnInfo' in column_type:
            array_values = datum['ArrayValue']
            return "%s=%s" % (info['Name'], self._parse_array(info['Type']['ArrayColumnInfo'], array_values))

        # If the column is of Row Type
        elif 'RowColumnInfo' in column_type:
            row_column_info = info['Type']['RowColumnInfo']
            row_values = datum['RowValue']
            return self._parse_row(row_column_info, row_values)

        # If the column is of Scalar Type
        else:
            return self._parse_column_name(info) + datum['ScalarValue']

    def _parse_time_series(self, info, datum):
        time_series_output = []
        for data_point in datum['TimeSeriesValue']:
            time_series_output.append("{time=%s, value=%s}"
                                      % (data_point['Time'],
                                         self._parse_datum(info['Type']['TimeSeriesMeasureValueColumnInfo'],
                                                           data_point['Value'])))
        return "[%s]" % str(time_series_output)

    def _parse_array(self, array_column_info, array_values):
        array_output = []
        for datum in array_values:
            array_output.append(self._parse_datum(array_column_info, datum))

        return "[%s]" % str(array_output)
        
    @staticmethod
    def _parse_column_name(info):
        if 'Name' in info:
            return info['Name'] + "="
        else:
            return ""
```

------
#### [  Node.js  ]

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
function parseQueryResult(response) {
    const queryStatus = response.QueryStatus;
    console.log("Current query status: " + JSON.stringify(queryStatus));
    
    const columnInfo = response.ColumnInfo;
    const rows = response.Rows;

    console.log("Metadata: " + JSON.stringify(columnInfo));
    console.log("Data: ");

    rows.forEach(function (row) {
        console.log(parseRow(columnInfo, row));
    });
}

function parseRow(columnInfo, row) {
    const data = row.Data;
    const rowOutput = [];

    var i;
    for ( i = 0; i < data.length; i++ ) {
        info = columnInfo[i];
        datum = data[i];
        rowOutput.push(parseDatum(info, datum));
    }

    return `{${rowOutput.join(", ")}}`
}

function parseDatum(info, datum) {
    if (datum.NullValue != null && datum.NullValue === true) {
        return `${info.Name}=NULL`;
    }

    const columnType = info.Type;

    // If the column is of TimeSeries Type
    if (columnType.TimeSeriesMeasureValueColumnInfo != null) {
        return parseTimeSeries(info, datum);
    }
    // If the column is of Array Type
    else if (columnType.ArrayColumnInfo != null) {
        const arrayValues = datum.ArrayValue;
        return `${info.Name}=${parseArray(info.Type.ArrayColumnInfo, arrayValues)}`;
    }
    // If the column is of Row Type
    else if (columnType.RowColumnInfo != null) {
        const rowColumnInfo = info.Type.RowColumnInfo;
        const rowValues = datum.RowValue;
        return parseRow(rowColumnInfo, rowValues);
    }
    // If the column is of Scalar Type
    else {
        return parseScalarType(info, datum);
    }
}

function parseTimeSeries(info, datum) {
    const timeSeriesOutput = [];
    datum.TimeSeriesValue.forEach(function (dataPoint) {
        timeSeriesOutput.push(`{time=${dataPoint.Time}, value=${parseDatum(info.Type.TimeSeriesMeasureValueColumnInfo, dataPoint.Value)}}`)
    });

    return `[${timeSeriesOutput.join(", ")}]`
}

function parseScalarType(info, datum) {
    return parseColumnName(info) + datum.ScalarValue;
}

function parseColumnName(info) {
    return info.Name == null ? "" : `${info.Name}=`;
}

function parseArray(arrayColumnInfo, arrayValues) {
    const arrayOutput = [];
    arrayValues.forEach(function (datum) {
        arrayOutput.push(parseDatum(arrayColumnInfo, datum));
    });
    return `[${arrayOutput.join(", ")}]`
}
```

------
#### [  .NET  ]

```
        private void ParseQueryResult(QueryResponse response)
        {
            List<ColumnInfo> columnInfo = response.ColumnInfo;
            var options = new JsonSerializerOptions
            {
                IgnoreNullValues = true
            };
            List<String> columnInfoStrings = columnInfo.ConvertAll(x => JsonSerializer.Serialize(x, options));
            List<Row> rows = response.Rows;
            
            QueryStatus queryStatus = response.QueryStatus;
            Console.WriteLine("Current Query status:" + JsonSerializer.Serialize(queryStatus, options));
            
            Console.WriteLine("Metadata:" + string.Join(",", columnInfoStrings));
            Console.WriteLine("Data:");

            foreach (Row row in rows)
            {
                Console.WriteLine(ParseRow(columnInfo, row));
            }
        }

        private string ParseRow(List<ColumnInfo> columnInfo, Row row)
        {
            List<Datum> data = row.Data;
            List<string> rowOutput = new List<string>();
            for (int j = 0; j < data.Count; j++)
            {
                ColumnInfo info = columnInfo[j];
                Datum datum = data[j];
                rowOutput.Add(ParseDatum(info, datum));
            }
            return $"{{{string.Join(",", rowOutput)}}}";
        }

        private string ParseDatum(ColumnInfo info, Datum datum)
        {
            if (datum.NullValue)
            {
                return $"{info.Name}=NULL";
            }

            Amazon.TimestreamQuery.Model.Type columnType = info.Type;
            if (columnType.TimeSeriesMeasureValueColumnInfo != null)
            {
                return ParseTimeSeries(info, datum);
            }
            else if (columnType.ArrayColumnInfo != null)
            {
                List<Datum> arrayValues = datum.ArrayValue;
                return $"{info.Name}={ParseArray(info.Type.ArrayColumnInfo, arrayValues)}";
            }
            else if (columnType.RowColumnInfo != null && columnType.RowColumnInfo.Count > 0)
            {
                List<ColumnInfo> rowColumnInfo = info.Type.RowColumnInfo;
                Row rowValue = datum.RowValue;
                return ParseRow(rowColumnInfo, rowValue);
            }
            else
            {
                return ParseScalarType(info, datum);
            }
        }

        private string ParseTimeSeries(ColumnInfo info, Datum datum)
        {
            var timeseriesString = datum.TimeSeriesValue
                .Select(value => $"{{time={value.Time}, value={ParseDatum(info.Type.TimeSeriesMeasureValueColumnInfo, value.Value)}}}")
                .Aggregate((current, next) => current + "," + next);

            return $"[{timeseriesString}]";
        }

        private string ParseScalarType(ColumnInfo info, Datum datum)
        {
            return ParseColumnName(info) + datum.ScalarValue;
        }

        private string ParseColumnName(ColumnInfo info)
        {
            return info.Name == null ? "" : (info.Name + "=");
        }

        private string ParseArray(ColumnInfo arrayColumnInfo, List<Datum> arrayValues)
        {
            return $"[{arrayValues.Select(value => ParseDatum(arrayColumnInfo, value)).Aggregate((current, next) => current + "," + next)}]";
        }
```

------

## Accessing the query status
<a name="code-samples.run-query.query-status"></a>

 You can access the query status through `QueryResponse`, which contains information about progress of a query, the bytes scanned by a query and the bytes metered by a query. The `bytesMetered` and `bytesScanned` values are cumulative and continuously updated while paging query results. You can use this information to understand the bytes scanned by an individual query and also use it to make certain decisions. For example, assuming that the query price is \$10.01 per GB scanned, you may want to cancel queries that exceed \$125 per query, or `X` GB. The code snippet below shows how this can be done. 

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
    private static final long ONE_GB_IN_BYTES = 1073741824L;
    private static final double QUERY_COST_PER_GB_IN_DOLLARS = 0.01; // Assuming the price of query is $0.01 per GB

    public void cancelQueryBasedOnQueryStatus() {
        System.out.println("Starting query: " + SELECT_ALL_QUERY);
        QueryRequest queryRequest = new QueryRequest();
        queryRequest.setQueryString(SELECT_ALL_QUERY);
        QueryResult queryResult = queryClient.query(queryRequest);

        while (true) {
            final QueryStatus currentStatusOfQuery = queryResult.getQueryStatus();
            System.out.println("Query progress so far: " + currentStatusOfQuery.getProgressPercentage() + "%");
            double bytesMeteredSoFar = ((double) currentStatusOfQuery.getCumulativeBytesMetered() / ONE_GB_IN_BYTES);
            System.out.println("Bytes metered so far: " + bytesMeteredSoFar + " GB");
            // Cancel query if its costing more than 1 cent
            if (bytesMeteredSoFar * QUERY_COST_PER_GB_IN_DOLLARS > 0.01) {
                cancelQuery(queryResult);
                break;
            }

            if (queryResult.getNextToken() == null) {
                break;
            }
            queryRequest.setNextToken(queryResult.getNextToken());
            queryResult = queryClient.query(queryRequest);
        }
    }
```

------
#### [  Java v2  ]

```
    private static final long ONE_GB_IN_BYTES = 1073741824L;
    private static final double QUERY_COST_PER_GB_IN_DOLLARS = 0.01; // Assuming the price of query is $0.01 per GB

    public void cancelQueryBasedOnQueryStatus() {
        System.out.println("Starting query: " + SELECT_ALL_QUERY);
        QueryRequest queryRequest = QueryRequest.builder().queryString(SELECT_ALL_QUERY).build();

        final QueryIterable queryResponseIterator = timestreamQueryClient.queryPaginator(queryRequest);
        for(QueryResponse queryResponse : queryResponseIterator) {
            final QueryStatus currentStatusOfQuery = queryResponse.queryStatus();
            System.out.println("Query progress so far: " + currentStatusOfQuery.progressPercentage() + "%");
            double bytesMeteredSoFar = ((double) currentStatusOfQuery.cumulativeBytesMetered() / ONE_GB_IN_BYTES);
            System.out.println("Bytes metered so far: " + bytesMeteredSoFar + "GB");
            // Cancel query if its costing more than 1 cent
            if (bytesMeteredSoFar * QUERY_COST_PER_GB_IN_DOLLARS > 0.01) {
                cancelQuery(queryResponse);
                break;
            }
        }
    }
```

------
#### [  Go  ]

```
const OneGbInBytes = 1073741824
// Assuming the price of query is $0.01 per GB
const QueryCostPerGbInDollars = 0.01

func cancelQueryBasedOnQueryStatus(queryPtr *string, querySvc *timestreamquery.TimestreamQuery, f *os.File) {
    queryInput := &timestreamquery.QueryInput{
        QueryString: aws.String(*queryPtr),
    }
    fmt.Println("QueryInput:")
    fmt.Println(queryInput)
    // execute the query
    err := querySvc.QueryPages(queryInput,
        func(page *timestreamquery.QueryOutput, lastPage bool) bool {
            // process query response
            queryStatus := page.QueryStatus
            fmt.Println("Current query status:", queryStatus)
            bytes_metered := float64(*queryStatus.CumulativeBytesMetered) / float64(ONE_GB_IN_BYTES)
            if bytes_metered * QUERY_COST_PER_GB_IN_DOLLARS > 0.01 {
                cancelQuery(page, querySvc)
                return true
            }
            // query response metadata
            // includes column names and types
            metadata := page.ColumnInfo
            // fmt.Println("Metadata:")
            fmt.Println(metadata)
            header := ""
            for i := 0; i < len(metadata); i++ {
                header += *metadata[i].Name
                if i != len(metadata)-1 {
                    header += ", "
                }
            }
            write(f, header)

            // query response data
            fmt.Println("Data:")
            // process rows
            rows := page.Rows
            for i := 0; i < len(rows); i++ {
                data := rows[i].Data
                value := processRowType(data, metadata)
                fmt.Println(value)
                write(f, value)
            }
            fmt.Println("Number of rows:", len(page.Rows))
            return true
        })
    if err != nil {
        fmt.Println("Error:")
        fmt.Println(err)
    }
}
```

------
#### [  Python  ]

```
ONE_GB_IN_BYTES = 1073741824
# Assuming the price of query is $0.01 per GB
QUERY_COST_PER_GB_IN_DOLLARS = 0.01 

    def cancel_query_based_on_query_status(self):
        try:
            print("Starting query: " + self.SELECT_ALL)
            page_iterator = self.paginator.paginate(QueryString=self.SELECT_ALL)
            for page in page_iterator:
                query_status = page["QueryStatus"]
                progress_percentage = query_status["ProgressPercentage"]
                print("Query progress so far: " + str(progress_percentage) + "%")
                bytes_metered = query_status["CumulativeBytesMetered"] / self.ONE_GB_IN_BYTES
                print("Bytes Metered so far: " + str(bytes_metered) + " GB")
                if bytes_metered * self.QUERY_COST_PER_GB_IN_DOLLARS > 0.01:
                    self.cancel_query_for(page)
                    break
        except Exception as err:
            print("Exception while running query:", err)
            traceback.print_exc(file=sys.stderr)
```

------
#### [  Node.js  ]

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
function parseQueryResult(response) {
    const queryStatus = response.QueryStatus;
    console.log("Current query status: " + JSON.stringify(queryStatus));
    
    const columnInfo = response.ColumnInfo;
    const rows = response.Rows;

    console.log("Metadata: " + JSON.stringify(columnInfo));
    console.log("Data: ");

    rows.forEach(function (row) {
        console.log(parseRow(columnInfo, row));
    });
}

function parseRow(columnInfo, row) {
    const data = row.Data;
    const rowOutput = [];

    var i;
    for ( i = 0; i < data.length; i++ ) {
        info = columnInfo[i];
        datum = data[i];
        rowOutput.push(parseDatum(info, datum));
    }

    return `{${rowOutput.join(", ")}}`
}

function parseDatum(info, datum) {
    if (datum.NullValue != null && datum.NullValue === true) {
        return `${info.Name}=NULL`;
    }

    const columnType = info.Type;

    // If the column is of TimeSeries Type
    if (columnType.TimeSeriesMeasureValueColumnInfo != null) {
        return parseTimeSeries(info, datum);
    }
    // If the column is of Array Type
    else if (columnType.ArrayColumnInfo != null) {
        const arrayValues = datum.ArrayValue;
        return `${info.Name}=${parseArray(info.Type.ArrayColumnInfo, arrayValues)}`;
    }
    // If the column is of Row Type
    else if (columnType.RowColumnInfo != null) {
        const rowColumnInfo = info.Type.RowColumnInfo;
        const rowValues = datum.RowValue;
        return parseRow(rowColumnInfo, rowValues);
    }
    // If the column is of Scalar Type
    else {
        return parseScalarType(info, datum);
    }
}

function parseTimeSeries(info, datum) {
    const timeSeriesOutput = [];
    datum.TimeSeriesValue.forEach(function (dataPoint) {
        timeSeriesOutput.push(`{time=${dataPoint.Time}, value=${parseDatum(info.Type.TimeSeriesMeasureValueColumnInfo, dataPoint.Value)}}`)
    });

    return `[${timeSeriesOutput.join(", ")}]`
}

function parseScalarType(info, datum) {
    return parseColumnName(info) + datum.ScalarValue;
}

function parseColumnName(info) {
    return info.Name == null ? "" : `${info.Name}=`;
}

function parseArray(arrayColumnInfo, arrayValues) {
    const arrayOutput = [];
    arrayValues.forEach(function (datum) {
        arrayOutput.push(parseDatum(arrayColumnInfo, datum));
    });
    return `[${arrayOutput.join(", ")}]`
}
```

------
#### [  .NET  ]

```
private static readonly long ONE_GB_IN_BYTES = 1073741824L;
private static readonly double QUERY_COST_PER_GB_IN_DOLLARS = 0.01; // Assuming the price of query is $0.01 per GB

private async Task CancelQueryBasedOnQueryStatus(string queryString)
{
    try
    {
        QueryRequest queryRequest = new QueryRequest();
        queryRequest.QueryString = queryString;
        QueryResponse queryResponse = await queryClient.QueryAsync(queryRequest);
        while (true)
        {
            QueryStatus queryStatus = queryResponse.QueryStatus;
            double bytesMeteredSoFar = ((double) queryStatus.CumulativeBytesMetered / ONE_GB_IN_BYTES);
            // Cancel query if its costing more than 1 cent
            if (bytesMeteredSoFar * QUERY_COST_PER_GB_IN_DOLLARS > 0.01)
            {
                await CancelQuery(queryResponse);
                break;
            }

            ParseQueryResult(queryResponse);
            if (queryResponse.NextToken == null)
            {
                break;
            }
            queryRequest.NextToken = queryResponse.NextToken;
            queryResponse = await queryClient.QueryAsync(queryRequest);
       }
    } catch(Exception e)
    {
        // Some queries might fail with 500 if the result of a sequence function has more than 10000 entries
        Console.WriteLine(e.ToString());
    }
}
```

------

 For additional details on how to cancel a query, see [Cancel query](code-samples.cancel-query.md). 

# Run UNLOAD query
<a name="code-samples.run-query-unload"></a>

The following code examples call an UNLOAD query. For information about `UNLOAD`, see [Using UNLOAD to export query results to S3 from Timestream for LiveAnalytics](export-unload.md). For examples of `UNLOAD` queries, see [Example use case for UNLOAD from Timestream for LiveAnalytics](export-unload-example-use-case.md).

**Topics**
+ [Build and run an UNLOAD query](#code-samples.run-query-unload-build-and-run)
+ [Parse UNLOAD response, and get row count, manifest link, and metadata link](#code-samples.run-query-unload-parse-response)
+ [Read and parse manifest content](#code-samples.run-query-unload-parse-manifest)
+ [Read and parse metadata content](#code-samples.run-query-unload-parse-metadata)

## Build and run an UNLOAD query
<a name="code-samples.run-query-unload-build-and-run"></a>

------
#### [  Java  ]

```
// When you have a SELECT like below

String QUERY_1 = "SELECT user_id, ip_address, event, session_id, measure_name, time, query, quantity, product_id, channel FROM "
        + DATABASE_NAME + "." + UNLOAD_TABLE_NAME
        + " WHERE time BETWEEN ago(2d) AND now()";

// You can construct UNLOAD query as follows
UnloadQuery unloadQuery = UnloadQuery.builder()
        .selectQuery(QUERY_1)
        .bucketName("timestream-sample-<region>-<accountId>")
        .resultsPrefix("without_partition")
        .format(CSV)
        .compression(UnloadQuery.Compression.GZIP)
        .build();
QueryResult unloadResult = runQuery(unloadQuery.getUnloadQuery());

// Run UNLOAD query (Similar to how you run SELECT query)
// https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.run-query.html#code-samples.run-query.pagination
    private QueryResult runQuery(String queryString) {
        QueryResult queryResult = null;
        try {
            QueryRequest queryRequest = new QueryRequest();
            queryRequest.setQueryString(queryString);
            queryResult = queryClient.query(queryRequest);
            while (true) {
                parseQueryResult(queryResult);
                if (queryResult.getNextToken() == null) {
                    break;
                }
                queryRequest.setNextToken(queryResult.getNextToken());
                queryResult = queryClient.query(queryRequest);
            }
        } catch (Exception e) {
            // Some queries might fail with 500 if the result of a sequence function has more than 10000 entries
            e.printStackTrace();
        }
        return queryResult;
    }

// Utility that helps to construct UNLOAD query

@Builder
static class UnloadQuery {
    private String selectQuery;
    private String bucketName;
    private String resultsPrefix;
    private Format format;
    private Compression compression;
    private EncryptionType encryptionType;
    private List<String> partitionColumns;
    private String kmsKey;
    private Character csvFieldDelimiter;
    private Character csvEscapeCharacter;

    public String getUnloadQuery() {
        String destination = constructDestination();
        String withClause = constructOptionalParameters();
        return String.format("UNLOAD (%s) TO '%s' %s", selectQuery, destination, withClause);
    }

    private String constructDestination() {
        return "s3://" + this.bucketName + "/" + this.resultsPrefix + "/";
    }

    private String constructOptionalParameters() {
        boolean isOptionalParametersPresent = Objects.nonNull(format)
                || Objects.nonNull(compression)
                || Objects.nonNull(encryptionType)
                || Objects.nonNull(partitionColumns)
                || Objects.nonNull(kmsKey)
                || Objects.nonNull(csvFieldDelimiter)
                || Objects.nonNull(csvEscapeCharacter);

        String withClause = "";
        if (isOptionalParametersPresent) {
            StringJoiner optionalParameters = new StringJoiner(",");
            if (Objects.nonNull(format)) {
                optionalParameters.add("format = '" + format + "'");
            }
            if (Objects.nonNull(compression)) {
                optionalParameters.add("compression = '" + compression + "'");
            }
            if (Objects.nonNull(encryptionType)) {
                optionalParameters.add("encryption = '" + encryptionType + "'");
            }
            if (Objects.nonNull(kmsKey)) {
                optionalParameters.add("kms_key = '" + kmsKey + "'");
            }
            if (Objects.nonNull(csvFieldDelimiter)) {
                optionalParameters.add("field_delimiter = '" + csvFieldDelimiter + "'");
            }
            if (Objects.nonNull(csvEscapeCharacter)) {
                optionalParameters.add("escaped_by = '" + csvEscapeCharacter + "'");
            }
            if (Objects.nonNull(partitionColumns) && !partitionColumns.isEmpty()) {
                final StringJoiner partitionedByList = new StringJoiner(",");
                partitionColumns.forEach(column -> partitionedByList.add("'" + column + "'"));
                optionalParameters.add(String.format("partitioned_by = ARRAY[%s]", partitionedByList));
            }
            withClause = String.format("WITH (%s)", optionalParameters);
        }
        return withClause;
    }

    public enum Format {
        CSV, PARQUET
    }

    public enum Compression {
        GZIP, NONE
    }

    public enum EncryptionType {
        SSE_S3, SSE_KMS
    }

    @Override
    public String toString() {
        return getUnloadQuery();
    }
}
```

------
#### [  Java v2  ]

```
// When you have a SELECT like below

String QUERY_1 = "SELECT user_id, ip_address, event, session_id, measure_name, time, query, quantity, product_id, channel FROM "
        + DATABASE_NAME + "." + UNLOAD_TABLE_NAME
        + " WHERE time BETWEEN ago(2d) AND now()";

//You can construct UNLOAD query as follows
UnloadQuery unloadQuery = UnloadQuery.builder()
        .selectQuery(QUERY_1)
        .bucketName("timestream-sample-<region>-<accountId>")
        .resultsPrefix("without_partition")
        .format(CSV)
        .compression(UnloadQuery.Compression.GZIP)
        .build();

QueryResponse unloadResponse = runQuery(unloadQuery.getUnloadQuery());


// Run UNLOAD query (Similar to how you run SELECT query)
// https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.run-query.html#code-samples.run-query.pagination
private QueryResponse runQuery(String queryString) {
   QueryResponse finalResponse = null;
    try {
        QueryRequest queryRequest = QueryRequest.builder().queryString(queryString).build();
        final QueryIterable queryResponseIterator = timestreamQueryClient.queryPaginator(queryRequest);
        for(QueryResponse queryResponse : queryResponseIterator) {
            parseQueryResult(queryResponse);
           finalResponse = queryResponse;
        }
    } catch (Exception e) {
        // Some queries might fail with 500 if the result of a sequence function has more than 10000 entries
        e.printStackTrace();
    }
   return finalResponse;
}

// Utility that helps to construct UNLOAD query
@Builder
static class UnloadQuery {
    private String selectQuery;
    private String bucketName;
    private String resultsPrefix;
    private Format format;
    private Compression compression;
    private EncryptionType encryptionType;
    private List<String> partitionColumns;
    private String kmsKey;
    private Character csvFieldDelimiter;
    private Character csvEscapeCharacter;

    public String getUnloadQuery() {
        String destination = constructDestination();
        String withClause = constructOptionalParameters();
        return String.format("UNLOAD (%s) TO '%s' %s", selectQuery, destination, withClause);
    }

    private String constructDestination() {
        return "s3://" + this.bucketName + "/" + this.resultsPrefix + "/";
    }

    private String constructOptionalParameters() {
        boolean isOptionalParametersPresent = Objects.nonNull(format)
                || Objects.nonNull(compression)
                || Objects.nonNull(encryptionType)
                || Objects.nonNull(partitionColumns)
                || Objects.nonNull(kmsKey)
                || Objects.nonNull(csvFieldDelimiter)
                || Objects.nonNull(csvEscapeCharacter);

        String withClause = "";
        if (isOptionalParametersPresent) {
            StringJoiner optionalParameters = new StringJoiner(",");
            if (Objects.nonNull(format)) {
                optionalParameters.add("format = '" + format + "'");
            }
            if (Objects.nonNull(compression)) {
                optionalParameters.add("compression = '" + compression + "'");
            }
            if (Objects.nonNull(encryptionType)) {
                optionalParameters.add("encryption = '" + encryptionType + "'");
            }
            if (Objects.nonNull(kmsKey)) {
                optionalParameters.add("kms_key = '" + kmsKey + "'");
            }
            if (Objects.nonNull(csvFieldDelimiter)) {
                optionalParameters.add("field_delimiter = '" + csvFieldDelimiter + "'");
            }
            if (Objects.nonNull(csvEscapeCharacter)) {
                optionalParameters.add("escaped_by = '" + csvEscapeCharacter + "'");
            }
            if (Objects.nonNull(partitionColumns) && !partitionColumns.isEmpty()) {
                final StringJoiner partitionedByList = new StringJoiner(",");
                partitionColumns.forEach(column -> partitionedByList.add("'" + column + "'"));
                optionalParameters.add(String.format("partitioned_by = ARRAY[%s]", partitionedByList));
            }
            withClause = String.format("WITH (%s)", optionalParameters);
        }
        return withClause;
    }

    public enum Format {
        CSV, PARQUET
    }

    public enum Compression {
        GZIP, NONE
    }

    public enum EncryptionType {
        SSE_S3, SSE_KMS
    }

    @Override
    public String toString() {
        return getUnloadQuery();
    }
}
```

------
#### [  Go  ]

```
// When you have a SELECT like below
var Query = "SELECT user_id, ip_address, event, session_id, measure_name, time, query, quantity, product_id, channel FROM "
+ *databaseName + "." + *tableName + " WHERE time BETWEEN ago(2d) AND now()"

// You can construct UNLOAD query as follows
var unloadQuery = UnloadQuery{
    Query: "SELECT user_id, ip_address, session_id, measure_name, time, query, quantity, product_id, channel, event FROM " + *databaseName + "." + *tableName + 
    " WHERE time BETWEEN ago(2d) AND now()",
    Partitioned_by: []string{},
    Compression: "GZIP",
    Format: "CSV",
    S3Location: bucketName,
    ResultPrefix: "without_partition",
}


// Run UNLOAD query (Similar to how you run SELECT query)
// https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.run-query.html#code-samples.run-query.pagination

queryInput := &timestreamquery.QueryInput{
    QueryString: build_query(unloadQuery),
}

err := querySvc.QueryPages(queryInput,
    func(page *timestreamquery.QueryOutput, lastPage bool) bool {
        if (lastPage) {
            var response = parseQueryResult(page)
            var unloadFiles = getManifestAndMetadataFiles(s3Svc, response)
            displayColumns(unloadFiles, unloadQuery.Partitioned_by)
            displayResults(s3Svc, unloadFiles)
        }
        return true
    })

if err != nil {
    fmt.Println("Error:")
    fmt.Println(err)
}

// Utility that helps to construct UNLOAD query
type UnloadQuery struct {
    Query string
    Partitioned_by []string
    Format string
    S3Location string
    ResultPrefix string
    Compression string
}

func build_query(unload_query UnloadQuery) *string {
    var query_results_s3_path = "'s3://" + unload_query.S3Location + "/" + unload_query.ResultPrefix + "/'"
    var query = "UNLOAD(" + unload_query.Query + ") TO " + query_results_s3_path + " WITH ( "
    if (len(unload_query.Partitioned_by) > 0) {
        query = query + "partitioned_by=ARRAY["
        for i, column := range unload_query.Partitioned_by {
            if i == 0 {
                query = query + "'" + column + "'"
            } else {
                query = query + ",'" + column + "'"
            }
        }
        query = query + "],"
    }
    query = query + " format='" + unload_query.Format + "', "
    query = query + "  compression='" + unload_query.Compression + "')"
    fmt.Println(query)
    return aws.String(query)
}
```

------
#### [  Python  ]

```
# When you have a SELECT like below
QUERY_1 = "SELECT user_id, ip_address, event, session_id, measure_name, time, query, quantity, product_id, channel FROM "
        + database_name + "." + table_name + " WHERE time BETWEEN ago(2d) AND now()"
# You can construct UNLOAD query as follows
UNLOAD_QUERY_1 = UnloadQuery(QUERY_1, "timestream-sample-<region>-<accountId>", "without_partition", "CSV", "GZIP", "")

# Run UNLOAD query (Similar to how you run SELECT query)
# https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.run-query.html#code-samples.run-query.pagination
def run_query(self, query_string):
    try:
        page_iterator = self.paginator.paginate(QueryString=UNLOAD_QUERY_1)
    except Exception as err:
        print("Exception while running query:", err)

# Utility that helps to construct UNLOAD query
class UnloadQuery:
    def __init__(self, query, s3_bucket_location, results_prefix, format, compression , partition_by):
        self.query = query
        self.s3_bucket_location = s3_bucket_location
        self.results_prefix = results_prefix
        self.format = format
        self.compression = compression
        self.partition_by = partition_by

    def build_query(self):
        query_results_s3_path = "'s3://" + self.s3_bucket_location + "/" + self.results_prefix + "/'"
        unload_query = "UNLOAD("
        unload_query = unload_query + self.query
        unload_query = unload_query + ") "
        unload_query = unload_query + " TO " + query_results_s3_path
        unload_query = unload_query + " WITH ( "

        if(len(self.partition_by) > 0) :
            unload_query = unload_query + " partitioned_by = ARRAY" + str(self.partition_by) + ","

        unload_query = unload_query + " format='" + self.format  + "', "
        unload_query = unload_query + "  compression='" + self.compression + "')"

        return unload_query
```

------
#### [  Node.js ]

```
// When you have a SELECT like below
QUERY_1 = "SELECT user_id, ip_address, event, session_id, measure_name, time, query, quantity, product_id, channel FROM "
        + database_name + "." + table_name + " WHERE time BETWEEN ago(2d) AND now()"
// You can construct UNLOAD query as follows
UNLOAD_QUERY_1 = new UnloadQuery(QUERY_1, "timestream-sample-<region>-<accountId>", "without_partition", "CSV", "GZIP", "")


// Run UNLOAD query (Similar to how you run SELECT query)
// https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.run-query.html#code-samples.run-query.pagination

async runQuery(query = UNLOAD_QUERY_1, nextToken) {
    const params = new QueryCommand({
        QueryString: query
    });

    if (nextToken) {
        params.NextToken = nextToken;
    }

    await queryClient.send(params).then(
            (response) => {
                if (response.NextToken) {
                    runQuery(queryClient, query, response.NextToken);
                } else {
                    await parseAndDisplayResults(response);
                }
            },
            (err) => {
                console.error("Error while querying:", err);
            });
}


class UnloadQuery {
    constructor(query, s3_bucket_location, results_prefix, format, compression , partition_by) {
        this.query = query;
        this.s3_bucket_location = s3_bucket_location
        this.results_prefix = results_prefix
        this.format = format
        this.compression = compression
        this.partition_by = partition_by
    }

    buildQuery() {
        const query_results_s3_path = "'s3://" + this.s3_bucket_location + "/" + this.results_prefix + "/'"
        let unload_query = "UNLOAD("
        unload_query = unload_query + this.query
        unload_query = unload_query + ") "
        unload_query = unload_query + " TO " + query_results_s3_path
        unload_query = unload_query + " WITH ( "

        if(this.partition_by.length > 0) {
            let partitionBy = ""
            this.partition_by.forEach((str, i) => {
                partitionBy = partitionBy + (i ? ",'" : "'") + str + "'"
            })
            unload_query = unload_query + " partitioned_by = ARRAY[" + partitionBy + "],"
        }
        unload_query = unload_query + " format='" + this.format  + "', "
        unload_query = unload_query + "  compression='" + this.compression + "')"

        return unload_query
    }
}
```

------

## Parse UNLOAD response, and get row count, manifest link, and metadata link
<a name="code-samples.run-query-unload-parse-response"></a>

------
#### [  Java  ]

```
// Parsing UNLOAD query response is similar to how you parse SELECT query response: 
// https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.run-query.html#code-samples.run-query.parsing

// But unlike SELECT, UNLOAD only has 1 row * 3 columns outputed
// (rows, metadataFile, manifestFile) => (BIGINT, VARCHAR, VARCHAR)

public UnloadResponse parseResult(QueryResult queryResult) {
    Map<String, String> outputMap = new HashMap<>();
    for (int i = 0; i < queryResult.getColumnInfo().size(); i++) {
        outputMap.put(queryResult.getColumnInfo().get(i).getName(),
                queryResult.getRows().get(0).getData().get(i).getScalarValue());

    }
    return new UnloadResponse(outputMap);
}

@Getter
class UnloadResponse {
    private final String metadataFile;
    private final String manifestFile;
    private final int rows;

    public UnloadResponse(Map<String, String> unloadResponse) {
        this.metadataFile = unloadResponse.get("metadataFile");
        this.manifestFile = unloadResponse.get("manifestFile");
        this.rows = Integer.parseInt(unloadResponse.get("rows"));
    }
}
```

------
#### [  Java v2  ]

```
// Parsing UNLOAD query response is similar to how you parse SELECT query response: 
// https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.run-query.html#code-samples.run-query.parsing

// But unlike SELECT, UNLOAD only has 1 row * 3 columns outputed
// (rows, metadataFile, manifestFile) => (BIGINT, VARCHAR, VARCHAR)

public UnloadResponse parseResult(QueryResponse queryResponse) {
    Map<String, String> outputMap = new HashMap<>();
    for (int i = 0; i < queryResponse.columnInfo().size(); i++) {
        outputMap.put(queryResponse.columnInfo().get(i).name(),
                queryResponse.rows().get(0).data().get(i).scalarValue());

    }
    return new UnloadResponse(outputMap);
}

@Getter
class UnloadResponse {
    private final String metadataFile;
    private final String manifestFile;
    private final int rows;

    public UnloadResponse(Map<String, String> unloadResponse) {
        this.metadataFile = unloadResponse.get("metadataFile");
        this.manifestFile = unloadResponse.get("manifestFile");
        this.rows = Integer.parseInt(unloadResponse.get("rows"));
    }
}
```

------
#### [  Go  ]

```
// Parsing UNLOAD query response is similar to how you parse SELECT query response: 
// https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.run-query.html#code-samples.run-query.parsing

// But unlike SELECT, UNLOAD only has 1 row * 3 columns outputed
// (rows, metadataFile, manifestFile) => (BIGINT, VARCHAR, VARCHAR)

func parseQueryResult(queryOutput *timestreamquery.QueryOutput) map[string]string {
    var columnInfo = queryOutput.ColumnInfo;
    fmt.Println("ColumnInfo", columnInfo)
    fmt.Println("QueryId", queryOutput.QueryId)
    fmt.Println("QueryStatus", queryOutput.QueryStatus)
    return parseResponse(columnInfo, queryOutput.Rows[0])
}

func parseResponse(columnInfo []*timestreamquery.ColumnInfo, row *timestreamquery.Row) map[string]string {
    var datum = row.Data
    response := make(map[string]string)
    for i, column := range columnInfo {
        response[*column.Name] = *datum[i].ScalarValue
    }
    return response
}
```

------
#### [  Python  ]

```
# Parsing UNLOAD query response is similar to how you parse SELECT query response: 
# https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.run-query.html#code-samples.run-query.parsing

# But unlike SELECT, UNLOAD only has 1 row * 3 columns outputed
# (rows, metadataFile, manifestFile) => (BIGINT, VARCHAR, VARCHAR)

for page in page_iterator:
  last_page = page
response = self._parse_unload_query_result(last_page)

def _parse_unload_query_result(self, query_result):
    column_info = query_result['ColumnInfo']

    print("ColumnInfo: %s" % column_info)
    print("QueryId: %s" % query_result['QueryId'])
    print("QueryStatus:%s" % query_result['QueryStatus'])
    return self.parse_unload_response(column_info, query_result['Rows'][0])

def parse_unload_response(self, column_info, row):
    response = {}
    data = row['Data']
    for i, column in enumerate(column_info):
        response[column['Name']] = data[i]['ScalarValue']
   print("Rows: %s" % response['rows'])
   print("Metadata File location: %s" % response['metadataFile'])
   print("Manifest File location: %s" % response['manifestFile'])
   return response
```

------
#### [  Node.js ]

```
# Parsing UNLOAD query response is similar to how you parse SELECT query response: 
# https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.run-query.html#code-samples.run-query.parsing

# But unlike SELECT, UNLOAD only has 1 row * 3 columns outputed
# (rows, metadataFile, manifestFile) => (BIGINT, VARCHAR, VARCHAR)

async parseAndDisplayResults(data, query) {
    const columnInfo = data['ColumnInfo'];
    console.log("ColumnInfo:", columnInfo)
    console.log("QueryId: %s", data['QueryId'])
    console.log("QueryStatus:", data['QueryStatus'])
    await this.parseResponse(columnInfo, data['Rows'][0], query)
}

async parseResponse(columnInfo, row, query) {
    let response = {}
    const data = row['Data']
    columnInfo.forEach((column, i) => {
        response[column['Name']] = data[i]['ScalarValue']
    })
    
   console.log("Manifest file", response['manifestFile']);
   console.log("Metadata file", response['metadataFile']);
   
   return response 
}
```

------

## Read and parse manifest content
<a name="code-samples.run-query-unload-parse-manifest"></a>

------
#### [  Java  ]

```
// Read and parse manifest content
public UnloadManifest getUnloadManifest(UnloadResponse unloadResponse) throws IOException {
   AmazonS3URI s3URI = new AmazonS3URI(unloadResponse.getManifestFile());
    S3Object s3Object = s3Client.getObject(s3URI.getBucket(), s3URI.getKey());
    String manifestFileContent = new String(IOUtils.toByteArray(s3Object.getObjectContent()), StandardCharsets.UTF_8);
    return new Gson().fromJson(manifestFileContent, UnloadManifest.class);
}

class UnloadManifest {
    @Getter
    public class FileMetadata {
        long content_length_in_bytes;
        long row_count;
    }

    @Getter
    public class ResultFile {
        String url;
        FileMetadata file_metadata;
    }

    @Getter
    public class QueryMetadata {
        long total_content_length_in_bytes;
        long total_row_count;
        String result_format;
        String result_version;
    }

    @Getter
    public class Author {
        String name;
        String manifest_file_version;
    }

    @Getter
    private List<ResultFile> result_files;
    @Getter
    private QueryMetadata query_metadata;
    @Getter
    private Author author;
}
```

------
#### [  Java v2  ]

```
// Read and parse manifest content
public UnloadManifest getUnloadManifest(UnloadResponse unloadResponse) throws URISyntaxException {
    // Space needs to encoded to use S3 parseUri function
    S3Uri s3Uri = s3Utilities.parseUri(URI.create(unloadResponse.getManifestFile().replace(" ", "%20")));
    ResponseBytes<GetObjectResponse> objectBytes = s3Client.getObjectAsBytes(GetObjectRequest.builder()
            .bucket(s3Uri.bucket().orElseThrow(() -> new URISyntaxException(unloadResponse.getManifestFile(), "Invalid S3 URI")))
            .key(s3Uri.key().orElseThrow(() -> new URISyntaxException(unloadResponse.getManifestFile(), "Invalid S3 URI")))
            .build());
    String manifestFileContent = new String(objectBytes.asByteArray(), StandardCharsets.UTF_8);
    return new Gson().fromJson(manifestFileContent, UnloadManifest.class);
}

class UnloadManifest {
    @Getter
    public class FileMetadata {
        long content_length_in_bytes;
        long row_count;
    }

    @Getter
    public class ResultFile {
        String url;
        FileMetadata file_metadata;
    }

    @Getter
    public class QueryMetadata {
        long total_content_length_in_bytes;
        long total_row_count;
        String result_format;
        String result_version;
    }

    @Getter
    public class Author {
        String name;
        String manifest_file_version;
    }

    @Getter
    private List<ResultFile> result_files;
    @Getter
    private QueryMetadata query_metadata;
    @Getter
    private Author author;
}
```

------
#### [  Go  ]

```
// Read and parse manifest content

func getManifestFile(s3Svc *s3.S3, response map[string]string) Manifest {
    var manifestBuf = getObject(s3Svc, response["manifestFile"])
    var manifest Manifest
    json.Unmarshal(manifestBuf.Bytes(), &manifest)
    return manifest
}

func getObject(s3Svc *s3.S3, s3Uri string) *bytes.Buffer {
    u,_ := url.Parse(s3Uri)
    getObjectInput := &s3.GetObjectInput{
        Key:    aws.String(u.Path),
        Bucket: aws.String(u.Host),
    }
    getObjectOutput, err := s3Svc.GetObject(getObjectInput)
    if err != nil {
        fmt.Println("Error: %s\n", err.Error())
    }
    buf := new(bytes.Buffer)
    buf.ReadFrom(getObjectOutput.Body)
    return buf
}

// Unload's Manifest structure

type Manifest struct {
    Author interface{}
    Query_metadata map[string]any
    Result_files  []struct {
        File_metadata interface{}
        Url string
    }
}}
```

------
#### [  Python  ]

```
def __get_manifest_file(self, response):
    manifest = self.get_object(response['manifestFile']).read().decode('utf-8')
    parsed_manifest = json.loads(manifest)
    print("Manifest contents: \n%s" % parsed_manifest)

def get_object(self, uri):
    try:
        bucket, key = uri.replace("s3://", "").split("/", 1)
        s3_client = boto3.client('s3', region_name=<region>)
        response = s3_client.get_object(Bucket=bucket, Key=key)
        return response['Body']
    except Exception as err:
        print("Failed to get the object for URI:", uri)
        raise err
```

------
#### [  Node.js ]

```
// Read and parse manifest content

async getManifestFile(response) {
    let manifest;
    await this.getS3Object(response['manifestFile']).then(
        (data) => {
            manifest = JSON.parse(data);
        }
    );
    return manifest;
}

async getS3Object(uri) {
    const {bucketName, key} = this.getBucketAndKey(uri);
    const params = new GetObjectCommand({
        Bucket: bucketName,
        Key: key
    })
    const response = await this.s3Client.send(params);
    return await response.Body.transformToString();
}

getBucketAndKey(uri) {
    const [bucketName] = uri.replace("s3://", "").split("/", 1);
    const key = uri.replace("s3://", "").split('/').slice(1).join('/');
    return {bucketName, key};
}
```

------

## Read and parse metadata content
<a name="code-samples.run-query-unload-parse-metadata"></a>

------
#### [  Java  ]

```
// Read and parse metadata content
public UnloadMetadata getUnloadMetadata(UnloadResponse unloadResponse) throws IOException {
   AmazonS3URI s3URI = new AmazonS3URI(unloadResponse.getMetadataFile());
   S3Object s3Object = s3Client.getObject(s3URI.getBucket(), s3URI.getKey());
    String metadataFileContent = new String(IOUtils.toByteArray(s3Object.getObjectContent()), StandardCharsets.UTF_8);
    final Gson gson = new GsonBuilder()
            .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
            .create();
    return gson.fromJson(metadataFileContent, UnloadMetadata.class);
}

class UnloadMetadata {
    @JsonProperty("ColumnInfo")
    List<ColumnInfo> columnInfo;
    @JsonProperty("Author")
    Author author;

    @Data
    public class Author {
        @JsonProperty("Name")
        String name;
        @JsonProperty("MetadataFileVersion")
        String metadataFileVersion;
    }
}
```

------
#### [  Java v2  ]

```
// Read and parse metadata content

public UnloadMetadata getUnloadMetadata(UnloadResponse unloadResponse) throws URISyntaxException {
   // Space needs to encoded to use S3 parseUri function
    S3Uri s3Uri = s3Utilities.parseUri(URI.create(unloadResponse.getMetadataFile().replace(" ", "%20")));
    ResponseBytes<GetObjectResponse> objectBytes = s3Client.getObjectAsBytes(GetObjectRequest.builder()
            .bucket(s3Uri.bucket().orElseThrow(() -> new URISyntaxException(unloadResponse.getMetadataFile(), "Invalid S3 URI")))
            .key(s3Uri.key().orElseThrow(() -> new URISyntaxException(unloadResponse.getMetadataFile(), "Invalid S3 URI")))
            .build());
    String metadataFileContent = new String(objectBytes.asByteArray(), StandardCharsets.UTF_8);
    final Gson gson = new GsonBuilder()
            .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
            .create();
    return gson.fromJson(metadataFileContent, UnloadMetadata.class);
}

class UnloadMetadata {
    @JsonProperty("ColumnInfo")
    List<ColumnInfo> columnInfo;
    @JsonProperty("Author")
    Author author;

    @Data
    public class Author {
        @JsonProperty("Name")
        String name;
        @JsonProperty("MetadataFileVersion")
        String metadataFileVersion;
    }
}
```

------
#### [  Go  ]

```
// Read and parse metadata content

func getMetadataFile(s3Svc *s3.S3, response map[string]string) Metadata {
    var metadataBuf = getObject(s3Svc, response["metadataFile"])
    var metadata Metadata
    json.Unmarshal(metadataBuf.Bytes(), &metadata)
    return metadata
}

func getObject(s3Svc *s3.S3, s3Uri string) *bytes.Buffer {
    u,_ := url.Parse(s3Uri)
    getObjectInput := &s3.GetObjectInput{
        Key:    aws.String(u.Path),
        Bucket: aws.String(u.Host),
    }
    getObjectOutput, err := s3Svc.GetObject(getObjectInput)
    if err != nil {
        fmt.Println("Error: %s\n", err.Error())
    }
    buf := new(bytes.Buffer)
    buf.ReadFrom(getObjectOutput.Body)
    return buf
}

// Unload's Metadata structure

type Metadata struct {
    Author interface{}
    ColumnInfo []struct {
        Name string
        Type map[string]string
    }
}
```

------
#### [  Python  ]

```
def __get_metadata_file(self, response):
    metadata = self.get_object(response['metadataFile']).read().decode('utf-8')
    parsed_metadata = json.loads(metadata)
   print("Metadata contents: \n%s" % parsed_metadata)
    
def get_object(self, uri):
    try:
        bucket, key = uri.replace("s3://", "").split("/", 1)
        s3_client = boto3.client('s3', region_name=<region>)
        response = s3_client.get_object(Bucket=bucket, Key=key)
        return response['Body']
    except Exception as err:
        print("Failed to get the object for URI:", uri)
        raise err
```

------
#### [  Node.js ]

```
// Read and parse metadata content
async getMetadataFile(response) {
    let metadata;
    await this.getS3Object(response['metadataFile']).then(
        (data) => {
            metadata = JSON.parse(data);
        }
    );
    return metadata;
}

async getS3Object(uri) {
    const {bucketName, key} = this.getBucketAndKey(uri);
    const params = new GetObjectCommand({
        Bucket: bucketName,
        Key: key
    })
    const response = await this.s3Client.send(params);
    return await response.Body.transformToString();
}

getBucketAndKey(uri) {
    const [bucketName] = uri.replace("s3://", "").split("/", 1);
    const key = uri.replace("s3://", "").split('/').slice(1).join('/');
    return {bucketName, key};
}
```

------

# Cancel query
<a name="code-samples.cancel-query"></a>

You can use the following code snippets to cancel a query.

**Note**  
These code snippets are based on full sample applications on [GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/master/sample_apps). For more information about how to get started with the sample applications, see [Sample application](sample-apps.md).

------
#### [  Java  ]

```
    public void cancelQuery() {
        System.out.println("Starting query: " + SELECT_ALL_QUERY);
        QueryRequest queryRequest = new QueryRequest();
        queryRequest.setQueryString(SELECT_ALL_QUERY);
        QueryResult queryResult = queryClient.query(queryRequest);
 
        System.out.println("Cancelling the query: " + SELECT_ALL_QUERY);
        final CancelQueryRequest cancelQueryRequest = new CancelQueryRequest();
        cancelQueryRequest.setQueryId(queryResult.getQueryId());
        try {
            queryClient.cancelQuery(cancelQueryRequest);
            System.out.println("Query has been successfully cancelled");
        } catch (Exception e) {
            System.out.println("Could not cancel the query: " + SELECT_ALL_QUERY + " = " + e);
        }
    }
```

------
#### [  Java v2  ]

```
    public void cancelQuery() {
        System.out.println("Starting query: " + SELECT_ALL_QUERY);
        QueryRequest queryRequest = QueryRequest.builder().queryString(SELECT_ALL_QUERY).build();
        QueryResponse queryResponse = timestreamQueryClient.query(queryRequest);

        System.out.println("Cancelling the query: " + SELECT_ALL_QUERY);
        final CancelQueryRequest cancelQueryRequest = CancelQueryRequest.builder()
                .queryId(queryResponse.queryId()).build();
        try {
            timestreamQueryClient.cancelQuery(cancelQueryRequest);
            System.out.println("Query has been successfully cancelled");
        } catch (Exception e) {
            System.out.println("Could not cancel the query: " + SELECT_ALL_QUERY + " = " + e);
        }
    }
```

------
#### [  Go  ]

```
cancelQueryInput := &timestreamquery.CancelQueryInput{
      QueryId: aws.String(*queryOutput.QueryId),
  }

  fmt.Println("Submitting cancellation for the query")
  fmt.Println(cancelQueryInput)

  // submit the query
  cancelQueryOutput, err := querySvc.CancelQuery(cancelQueryInput)

  if err != nil {
      fmt.Println("Error:")
      fmt.Println(err)
  } else {
    fmt.Println("Query has been cancelled successfully")
    fmt.Println(cancelQueryOutput)
  }
```

------
#### [  Python  ]

```
    def cancel_query(self):
        print("Starting query: " + self.SELECT_ALL)
        result = self.client.query(QueryString=self.SELECT_ALL)
        print("Cancelling query: " + self.SELECT_ALL)
        try:
            self.client.cancel_query(QueryId=result['QueryId'])
            print("Query has been successfully cancelled")
        except Exception as err:
            print("Cancelling query failed:", err)
```

------
#### [  Node.js  ]

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/sample_apps/js).

```
async function tryCancelQuery() { 
    const params = { 
        QueryString: SELECT_ALL_QUERY 
    }; 
    console.log(`Running query: ${SELECT_ALL_QUERY}`); 
  
    await queryClient.query(params).promise() 
        .then( 
            async (response) => { 
                await cancelQuery(response.QueryId); 
            }, 
            (err) => { 
                console.error("Error while executing select all query:", err); 
            }); 
} 
  
async function cancelQuery(queryId) { 
    const cancelParams = { 
        QueryId: queryId 
    }; 
    console.log(`Sending cancellation for query: ${SELECT_ALL_QUERY}`); 
    await queryClient.cancelQuery(cancelParams).promise() 
        .then( 
            (response) => { 
                console.log("Query has been cancelled successfully"); 
            }, 
            (err) => { 
                console.error("Error while cancelling select all:", err); 
            }); 
}
```

------
#### [  .NET  ]

```
        public async Task CancelQuery()
        {
            Console.WriteLine("Starting query: " + SELECT_ALL_QUERY);
            QueryRequest queryRequest = new QueryRequest();
            queryRequest.QueryString = SELECT_ALL_QUERY;
            QueryResponse queryResponse = await queryClient.QueryAsync(queryRequest);

            Console.WriteLine("Cancelling query: " + SELECT_ALL_QUERY);
            CancelQueryRequest cancelQueryRequest = new CancelQueryRequest();
            cancelQueryRequest.QueryId = queryResponse.QueryId;

            try
            {
                await queryClient.CancelQueryAsync(cancelQueryRequest);
                Console.WriteLine("Query has been successfully cancelled.");
            } catch(Exception e)
            {
                Console.WriteLine("Could not cancel the query: " + SELECT_ALL_QUERY + " = " + e);
            }
        }
```

------

# Create batch load task
<a name="code-samples.create-batch-load"></a>

You can use the following code snippets to create batch load tasks.

------
#### [  Java  ]

```
package com.example.tryit;

import java.util.Arrays;

import software.amazon.awssdk.services.timestreamwrite.model.CreateBatchLoadTaskRequest;
import software.amazon.awssdk.services.timestreamwrite.model.CreateBatchLoadTaskResponse;
import software.amazon.awssdk.services.timestreamwrite.model.DataModel;
import software.amazon.awssdk.services.timestreamwrite.model.DataModelConfiguration;
import software.amazon.awssdk.services.timestreamwrite.model.DataSourceConfiguration;
import software.amazon.awssdk.services.timestreamwrite.model.DataSourceS3Configuration;
import software.amazon.awssdk.services.timestreamwrite.model.DimensionMapping;
import software.amazon.awssdk.services.timestreamwrite.model.MultiMeasureAttributeMapping;
import software.amazon.awssdk.services.timestreamwrite.model.MultiMeasureMappings;
import software.amazon.awssdk.services.timestreamwrite.model.ReportConfiguration;
import software.amazon.awssdk.services.timestreamwrite.model.ReportS3Configuration;
import software.amazon.awssdk.services.timestreamwrite.model.ScalarMeasureValueType;
import software.amazon.awssdk.services.timestreamwrite.model.TimeUnit;
import software.amazon.awssdk.services.timestreamwrite.TimestreamWriteClient;

public class BatchLoadExample {
    public static final String DATABASE_NAME = <database name>;
    public static final String TABLE_NAME = <table name>;
    public static final String INPUT_BUCKET = <S3 location>;
    public static final String INPUT_OBJECT_KEY_PREFIX = <CSV filename>;
    public static final String REPORT_BUCKET = <S3 location>;
    public static final long HT_TTL_HOURS = 24L;
    public static final long CT_TTL_DAYS = 7L;

    TimestreamWriteClient amazonTimestreamWrite;

    public BatchLoadExample(TimestreamWriteClient client) {
        this.amazonTimestreamWrite = client;
    }

    public String createBatchLoadTask() {
        System.out.println("Creating batch load task");

        CreateBatchLoadTaskRequest request = CreateBatchLoadTaskRequest.builder()
                .dataModelConfiguration(DataModelConfiguration.builder()
                        .dataModel(DataModel.builder()
                                .timeColumn("timestamp")
                                .timeUnit(TimeUnit.SECONDS)
                                .dimensionMappings(Arrays.asList(
                                        DimensionMapping.builder()
                                                .sourceColumn("vehicle")
                                                .build(),
                                        DimensionMapping.builder()
                                                .sourceColumn("registration")
                                                .destinationColumn("license")
                                                .build()))
                                .multiMeasureMappings(MultiMeasureMappings.builder()
                                        .targetMultiMeasureName("mva_measure_name")
                                        .multiMeasureAttributeMappings(Arrays.asList(
                                                MultiMeasureAttributeMapping.builder()
                                                        .sourceColumn("wgt")
                                                        .targetMultiMeasureAttributeName("weight")
                                                        .measureValueType(ScalarMeasureValueType.DOUBLE)
                                                        .build(),
                                                MultiMeasureAttributeMapping.builder()
                                                        .sourceColumn("spd")
                                                        .targetMultiMeasureAttributeName("speed")
                                                        .measureValueType(ScalarMeasureValueType.DOUBLE)
                                                        .build(),
                                                MultiMeasureAttributeMapping.builder()
                                                        .sourceColumn("fuel")
                                                        .measureValueType(ScalarMeasureValueType.DOUBLE)
                                                        .build(),
                                                MultiMeasureAttributeMapping.builder()
                                                        .sourceColumn("miles")
                                                        .measureValueType(ScalarMeasureValueType.DOUBLE)
                                                        .build()))
                                        .build())
                                .build())
                        .build())
                .dataSourceConfiguration(DataSourceConfiguration.builder()
                        .dataSourceS3Configuration(
                                DataSourceS3Configuration.builder()
                                        .bucketName(INPUT_BUCKET)
                                        .objectKeyPrefix(INPUT_OBJECT_KEY_PREFIX)
                                        .build())
                        .dataFormat("CSV")                
                        .build())
                .reportConfiguration(ReportConfiguration.builder()
                        .reportS3Configuration(ReportS3Configuration.builder()
                                .bucketName(REPORT_BUCKET)
                                .build())
                        .build())
                .targetDatabaseName(DATABASE_NAME)
                .targetTableName(TABLE_NAME)
                .build();
        try {
            final CreateBatchLoadTaskResponse createBatchLoadTaskResponse = amazonTimestreamWrite.createBatchLoadTask(request);
            String taskId = createBatchLoadTaskResponse.taskId();
            System.out.println("Successfully created batch load task: " + taskId);
            return taskId;
        } catch (Exception e) {
            System.out.println("Failed to create batch load task: " + e);
            throw e;
        }
    }
}
```

------
#### [  Go  ]

```
package main

import (
	"fmt"
	"context"
	"log"
	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/timestreamwrite"
	"github.com/aws/aws-sdk-go-v2/service/timestreamwrite/types"
)

func main() {
	customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{})(aws.Endpoint, error) {
		if service == timestreamwrite.ServiceID &&  region == "us-west-2" {
		    return aws.Endpoint{
		        PartitionID:   "aws",
		        URL:           <URL>,
		        SigningRegion: "us-west-2",
		    }, nil
		}
		return aws.Endpoint{}, &  aws.EndpointNotFoundError{}
	})

	cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithEndpointResolverWithOptions(customResolver), config.WithRegion("us-west-2"))

	if err != nil {
  		log.Fatalf("failed to load configuration, %v", err)
	}

	client := timestreamwrite.NewFromConfig(cfg)

	response, err := client.CreateBatchLoadTask(context.TODO(), &  timestreamwrite.CreateBatchLoadTaskInput{
            TargetDatabaseName: aws.String("BatchLoadExampleDatabase"),
            TargetTableName: aws.String("BatchLoadExampleTable"),
          		RecordVersion: aws.Int64(1),
          		DataModelConfiguration: &  types.DataModelConfiguration{
                DataModel: &  types.DataModel{
                    TimeColumn: aws.String("timestamp"),
                    TimeUnit: types.TimeUnitMilliseconds,
                    DimensionMappings: []types.DimensionMapping{
                        {
                            SourceColumn: aws.String("registration"),
                            DestinationColumn: aws.String("license"),
                        },
                    },
                    MultiMeasureMappings: &  types.MultiMeasureMappings{
                        TargetMultiMeasureName: aws.String("mva_measure_name"),
                        MultiMeasureAttributeMappings: []types.MultiMeasureAttributeMapping{
                            {
                                SourceColumn: aws.String("wgt"),
                                TargetMultiMeasureAttributeName: aws.String("weight"),
                                MeasureValueType: types.ScalarMeasureValueTypeDouble,
                            },
                            {
                                SourceColumn: aws.String("spd"),
                                TargetMultiMeasureAttributeName: aws.String("speed"),
                                MeasureValueType: types.ScalarMeasureValueTypeDouble,
                            },
                            {
                                SourceColumn: aws.String("fuel_consumption"),
                                TargetMultiMeasureAttributeName: aws.String("fuel"),
                                MeasureValueType: types.ScalarMeasureValueTypeDouble,
                            },
                        },
                    },
                },
            },
          	DataSourceConfiguration: &  types.DataSourceConfiguration{
                DataSourceS3Configuration: &  types.DataSourceS3Configuration{
                    BucketName: aws.String("test-batch-load-west-2"),
                    ObjectKeyPrefix: aws.String("sample.csv"),
                },
               	DataFormat: types.BatchLoadDataFormatCsv,
            },
          	ReportConfiguration: & types.ReportConfiguration{
                ReportS3Configuration: & types.ReportS3Configuration{
                    BucketName: aws.String("test-batch-load-report-west-2"),
                    EncryptionOption: types.S3EncryptionOptionSseS3,
                },
            },
	})

	fmt.Println(aws.ToString(response.TaskId))
}
```

------
#### [  Python  ]

```
import boto3
from botocore.config import Config

INGEST_ENDPOINT = "<URL>"
REGION = "us-west-2"
HT_TTL_HOURS = 24
CT_TTL_DAYS = 7
DATABASE_NAME = "<database name>"
TABLE_NAME = "<table name>"
INPUT_BUCKET_NAME = "<S3 location>"
INPUT_OBJECT_KEY_PREFIX = "<CSV file name>"
REPORT_BUCKET_NAME = "<S3 location>"


def create_batch_load_task(client, database_name, table_name, input_bucket_name, input_object_key_prefix, report_bucket_name):
    try:
        result = client.create_batch_load_task(TargetDatabaseName=database_name, TargetTableName=table_name,
                                               DataModelConfiguration={"DataModel": {
                                                   "TimeColumn": "timestamp",
                                                   "TimeUnit": "SECONDS",
                                                   "DimensionMappings": [
                                                       {
                                                           "SourceColumn": "vehicle"
                                                       },
                                                       {
                                                           "SourceColumn": "registration",
                                                           "DestinationColumn": "license"
                                                       }
                                                   ],
                                                   "MultiMeasureMappings": {
                                                       "TargetMultiMeasureName": "metrics",
                                                       "MultiMeasureAttributeMappings": [
                                                           {
                                                               "SourceColumn": "wgt",
                                                               "MeasureValueType": "DOUBLE"
                                                           },
                                                           {
                                                               "SourceColumn": "spd",
                                                               "MeasureValueType": "DOUBLE"
                                                           },
                                                           {
                                                               "SourceColumn": "fuel_consumption",
                                                               "TargetMultiMeasureAttributeName": "fuel",
                                                               "MeasureValueType": "DOUBLE"
                                                           },
                                                           {
                                                               "SourceColumn": "miles",
                                                               "MeasureValueType": "DOUBLE"
                                                           }
                                                       ]}
                                               }
                                               },
                                               DataSourceConfiguration={
                                                   "DataSourceS3Configuration": {
                                                       "BucketName": input_bucket_name,
                                                       "ObjectKeyPrefix": input_object_key_prefix
                                                   },
                                                   "DataFormat": "CSV"
                                               },
                                               ReportConfiguration={
                                                   "ReportS3Configuration": {
                                                       "BucketName":  report_bucket_name,
                                                       "EncryptionOption": "SSE_S3"
                                                   }
                                               }
                                               )

        task_id = result["TaskId"]
        print("Successfully created batch load task: ", task_id)
        return task_id
    except Exception as err:
        print("Create batch load task job failed:", err)
        return None


if __name__ == '__main__':
    session = boto3.Session()

    write_client = session.client('timestream-write',
                                  endpoint_url=INGEST_ENDPOINT, region_name=REGION,
                                  config=Config(read_timeout=20, max_pool_connections=5000, retries={'max_attempts': 10}))

    task_id = create_batch_load_task(write_client, DATABASE_NAME, TABLE_NAME,
                                     INPUT_BUCKET_NAME, INPUT_OBJECT_KEY_PREFIX, REPORT_BUCKET_NAME)
```

------
#### [  Node.js  ]

The following snippet uses AWS SDK for JavaScript v3. For more information about how to install the client and usage, see [Timestream Write Client - AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/index.html).

For API details, see [Class CreateBatchLoadCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/classes/createbatchloadtaskcommand.html) and [CreateBatchLoadTask](https://docs.aws.amazon.com/timestream/latest/developerguide/API_CreateBatchLoadTask.html).

```
import { TimestreamWriteClient, CreateBatchLoadTaskCommand } from "@aws-sdk/client-timestream-write";
const writeClient = new TimestreamWriteClient({ region: "us-west-2", endpoint: "https://gamma-ingest-cell3.timestream.us-west-2.amazonaws.com" });

const params = {
    TargetDatabaseName: "BatchLoadExampleDatabase",
    TargetTableName: "BatchLoadExampleTable",
	RecordVersion: 1,
	DataModelConfiguration: {
		DataModel: {
			TimeColumn: "timestamp",
            TimeUnit: "MILLISECONDS",
            DimensionMappings: [
                {
                    SourceColumn: "registration",
                    DestinationColumn: "license"
                }
            ],
            MultiMeasureMappings: {
                TargetMultiMeasureName: "mva_measure_name",
                MultiMeasureAttributeMappings: [
                    {
                        SourceColumn: "wgt",
                        TargetMultiMeasureAttributeName: "weight",
                        MeasureValueType: "DOUBLE"
                    },
                    {
                        SourceColumn: "spd",
                        TargetMultiMeasureAttributeName: "speed",
                        MeasureValueType: "DOUBLE"
                    },
                    {
                        SourceColumn: "fuel_consumption",
                        TargetMultiMeasureAttributeName: "fuel",
                        MeasureValueType: "DOUBLE"
                    }
                ]
            }
        }
    },
	DataSourceConfiguration: {
        DataSourceS3Configuration: {
            BucketName: "test-batch-load-west-2",
            ObjectKeyPrefix: "sample.csv"
        },
        DataFormat: "CSV"
    },
    ReportConfiguration: {
        ReportS3Configuration: {
            BucketName: "test-batch-load-report-west-2",
            EncryptionOption: "SSE_S3"
        }
    }
};

const command = new CreateBatchLoadTaskCommand(params);

try {
    const data = await writeClient.send(command);
    console.log(`Created batch load task ` + data.TaskId);
} catch (error) {
	console.log("Error creating table. ", error);
	throw error;
}
```

------
#### [  .NET  ]

```
using System;
using System.IO;
using System.Collections.Generic;
using Amazon.TimestreamWrite;
using Amazon.TimestreamWrite.Model;
using System.Threading.Tasks;

namespace TimestreamDotNetSample
{
    public class CreateBatchLoadTaskExample
    {
        public const string DATABASE_NAME = "<database name>";
        public const string TABLE_NAME = "<table name>";
        public const string INPUT_BUCKET = "<input bucket name>";
        public const string INPUT_OBJECT_KEY_PREFIX = "<CSV file name>";
        public const string REPORT_BUCKET = "<report bucket name>";
        public const long HT_TTL_HOURS = 24L;
        public const long CT_TTL_DAYS = 7L;
        private readonly AmazonTimestreamWriteClient writeClient;

        public CreateBatchLoadTaskExample(AmazonTimestreamWriteClient writeClient)
        {
            this.writeClient = writeClient;
        }

        public async Task CreateBatchLoadTask()
        {
            try
            {
                var createBatchLoadTaskRequest = new CreateBatchLoadTaskRequest
                {
                    DataModelConfiguration = new DataModelConfiguration
                    {
                        DataModel = new DataModel
                        {
                            TimeColumn = "timestamp",
                            TimeUnit = TimeUnit.SECONDS,
                            DimensionMappings = new List<DimensionMapping>()
                            {
                                new()
                                {
                                        SourceColumn = "vehicle"
                                },
                                new()
                                {
                                        SourceColumn = "registration",
                                        DestinationColumn = "license"
                                }
                            },
                            MultiMeasureMappings = new MultiMeasureMappings
                            {
                                TargetMultiMeasureName = "mva_measure_name",
                                MultiMeasureAttributeMappings = new List<MultiMeasureAttributeMapping>()
                                {
                                        new()
                                        {
                                                SourceColumn = "wgt",
                                                TargetMultiMeasureAttributeName = "weight",
                                                MeasureValueType = ScalarMeasureValueType.DOUBLE
                                        },
                                        new()
                                        {
                                                SourceColumn = "spd",
                                                TargetMultiMeasureAttributeName = "speed",
                                                MeasureValueType = ScalarMeasureValueType.DOUBLE
                                        },
                                        new()
                                        {
                                                SourceColumn = "fuel",
                                                TargetMultiMeasureAttributeName = "fuel",
                                                MeasureValueType = ScalarMeasureValueType.DOUBLE
                                        },
                                        new()
                                        {
                                                SourceColumn = "miles",
                                                TargetMultiMeasureAttributeName = "miles",
                                                MeasureValueType = ScalarMeasureValueType.DOUBLE
                                        }
                                }
                            }
                        }
                    },
                    DataSourceConfiguration = new DataSourceConfiguration
                    {
                        DataSourceS3Configuration = new DataSourceS3Configuration
                        {
                            BucketName = INPUT_BUCKET,
                            ObjectKeyPrefix = INPUT_OBJECT_KEY_PREFIX
                        },
                        DataFormat = "CSV"
                    },
                    ReportConfiguration = new ReportConfiguration
                    {
                        ReportS3Configuration = new ReportS3Configuration
                        {
                            BucketName = REPORT_BUCKET
                        }
                    },
                    TargetDatabaseName = DATABASE_NAME,
                    TargetTableName = TABLE_NAME
                };

                CreateBatchLoadTaskResponse response = await writeClient.CreateBatchLoadTaskAsync(createBatchLoadTaskRequest);
                Console.WriteLine($"Task created: " + response.TaskId);
            }
            catch (Exception e)
            {
                Console.WriteLine("Create batch load task failed:" + e.ToString());
            }
        }
    }
}
```

```
using Amazon.TimestreamWrite;
using Amazon.TimestreamWrite.Model;
using Amazon;
using Amazon.TimestreamQuery;
using System.Threading.Tasks;
using System;
using CommandLine;
static class Constants
{

}
namespace TimestreamDotNetSample
{
    class MainClass
    {
        public class Options
        {

        }
        public static void Main(string[] args)
        {
            Parser.Default.ParseArguments<Options>(args)
                .WithParsed<Options>(o => {
                    MainAsync().GetAwaiter().GetResult();
                });
        }

        static async Task MainAsync()
        {
            var writeClientConfig = new AmazonTimestreamWriteConfig
            {
                ServiceURL =  "<service URL>",
                Timeout = TimeSpan.FromSeconds(20),
                MaxErrorRetry = 10
            };
            
            var writeClient = new AmazonTimestreamWriteClient(writeClientConfig);
            var example = new CreateBatchLoadTaskExample(writeClient);
            await example.CreateBatchLoadTask();
        }
    }
}
```

------

# Describe batch load task
<a name="code-samples.describe-batch-load"></a>

You can use the following code snippets to describe batch load tasks.

------
#### [  Java  ]

```
    public void describeBatchLoadTask(String taskId) {
            final DescribeBatchLoadTaskResponse batchLoadTaskResponse = amazonTimestreamWrite
                            .describeBatchLoadTask(DescribeBatchLoadTaskRequest.builder()
                                            .taskId(taskId)
                                            .build());

            System.out.println("Task id: " + batchLoadTaskResponse.batchLoadTaskDescription().taskId());
            System.out.println("Status: " + batchLoadTaskResponse.batchLoadTaskDescription().taskStatusAsString());
            System.out.println("Records processed: "
                            + batchLoadTaskResponse.batchLoadTaskDescription().progressReport().recordsProcessed());
    }
```

------
#### [  Go  ]

```
package main

import (
	"fmt"
	"context"
	"log"
	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/timestreamwrite"
)

func main() {
	customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
		if service == timestreamwrite.ServiceID && region == "us-west-2" {
		    return aws.Endpoint{
		        PartitionID:   "aws",
		        URL:           <URL>,
		        SigningRegion: "us-west-2",
		    }, nil
		}
		return aws.Endpoint{}, &aws.EndpointNotFoundError{}
	})

	cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithEndpointResolverWithOptions(customResolver), config.WithRegion("us-west-2"))
	
	if err != nil {
  		log.Fatalf("failed to load configuration, %v", err)
	}

	client := timestreamwrite.NewFromConfig(cfg)
	
	response, err := client.DescribeBatchLoadTask(context.TODO(), &timestreamwrite.DescribeBatchLoadTaskInput{
		TaskId: aws.String("<TaskId>"),
	})

	fmt.Println(aws.ToString(response.BatchLoadTaskDescription.TaskId))
}
```

------
#### [  Python  ]

```
import boto3
from botocore.config import Config

INGEST_ENDPOINT="<url>"
REGION="us-west-2"
HT_TTL_HOURS = 24
CT_TTL_DAYS = 7
TASK_ID = "<task id>"

def describe_batch_load_task(client, task_id):
    try:
        result = client.describe_batch_load_task(TaskId=task_id)
        print("Successfully described batch load task: ", result)
    except Exception as err:
        print("Describe batch load task job failed:", err)


if __name__ == '__main__':
    session = boto3.Session()

    write_client = session.client('timestream-write', \
        endpoint_url=INGEST_ENDPOINT, region_name=REGION, \
        config=Config(read_timeout=20, max_pool_connections = 5000, retries={'max_attempts': 10}))

    describe_batch_load_task(write_client, TASK_ID)
```

------
#### [  Node.js  ]

The following snippet uses AWS SDK for JavaScript v3. For more information about how to install the client and usage, see [Timestream Write Client - AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/index.html).

For API details, see [Class DescribeBatchLoadCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/classes/describebatchloadtaskcommand.html) and [DescribeBatchLoadTask](https://docs.aws.amazon.com/timestream/latest/developerguide/API_DescribeBatchLoadTask.html).

```
import { TimestreamWriteClient, DescribeBatchLoadTaskCommand } from "@aws-sdk/client-timestream-write";
const writeClient = new TimestreamWriteClient({ region: "<region>", endpoint: "<endpoint>" });

const params = {
    TaskId: "<TaskId>"
};

const command = new DescribeBatchLoadTaskCommand(params);

try {
    const data = await writeClient.send(command);
    console.log(`Batch load task has id ` + data.BatchLoadTaskDescription.TaskId);
} catch (error) {
    if (error.code === 'ResourceNotFoundException') {
        console.log("Batch load task doesn't exist.");
    } else {
        console.log("Describe batch load task failed.", error);
        throw error;
    }
}
```

------
#### [  .NET  ]

```
using System;
using System.IO;
using System.Collections.Generic;
using Amazon.TimestreamWrite;
using Amazon.TimestreamWrite.Model;
using System.Threading.Tasks;

namespace TimestreamDotNetSample
{
    public class DescribeBatchLoadTaskExample
    {
        private readonly AmazonTimestreamWriteClient writeClient;

        public DescribeBatchLoadTaskExample(AmazonTimestreamWriteClient writeClient)
        {
            this.writeClient = writeClient;
        }

        public async Task DescribeBatchLoadTask(String taskId)
        {
            try
            {
                var describeBatchLoadTaskRequest = new DescribeBatchLoadTaskRequest
                {
                    TaskId = taskId
                };
                DescribeBatchLoadTaskResponse response = await writeClient.DescribeBatchLoadTaskAsync(describeBatchLoadTaskRequest);
                Console.WriteLine($"Task has id:{response.BatchLoadTaskDescription.TaskId}");
            }
            catch (ResourceNotFoundException)
            {
                Console.WriteLine("Batch load task does not exist.");
            }
            catch (Exception e)
            {
                Console.WriteLine("Describe batch load task failed:" + e.ToString());
            }
        }
    }
}
```

```
using Amazon.TimestreamWrite;
using Amazon.TimestreamWrite.Model;
using Amazon;
using Amazon.TimestreamQuery;
using System.Threading.Tasks;
using System;
using CommandLine;
static class Constants
{

}
namespace TimestreamDotNetSample
{
    class MainClass
    {
        public class Options
        {

        }
        public static void Main(string[] args)
        {
            Parser.Default.ParseArguments<Options>(args)
                .WithParsed<Options>(o => {
                    MainAsync().GetAwaiter().GetResult();
                });
        }

        static async Task MainAsync()
        {
            var writeClientConfig = new AmazonTimestreamWriteConfig
            {
                ServiceURL =  "<service URL>",
                Timeout = TimeSpan.FromSeconds(20),
                MaxErrorRetry = 10
            };
            
            var writeClient = new AmazonTimestreamWriteClient(writeClientConfig);
            var example = new DescribeBatchLoadTaskExample(writeClient);
            await example.DescribeBatchLoadTask("<batch load task id>");
        }
    }
}
```

------

# List batch load tasks
<a name="code-samples.list-batch-load-tasks"></a>

You can use the following code snippets to list batch load tasks.

------
#### [  Java  ]

```
    public void listBatchLoadTasks() {
            final ListBatchLoadTasksResponse listBatchLoadTasksResponse = amazonTimestreamWrite
                            .listBatchLoadTasks(ListBatchLoadTasksRequest.builder()
                                            .maxResults(15)
                                            .build());

            for (BatchLoadTask batchLoadTask : listBatchLoadTasksResponse.batchLoadTasks()) {
                    System.out.println(batchLoadTask.taskId());
            }
    }
```

------
#### [  Go  ]

```
package main

import (
	"fmt"
	"context"
	"log"
	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/timestreamwrite"
)

func main() {
	customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
		if service == timestreamwrite.ServiceID && region == "us-west-2" {
		    return aws.Endpoint{
		        PartitionID:   "aws",
		        URL:           <URL>,
		        SigningRegion: "us-west-2",
		    }, nil
		}
		return aws.Endpoint{}, &aws.EndpointNotFoundError{}
	})

	cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithEndpointResolverWithOptions(customResolver), config.WithRegion("us-west-2"))
	
	if err != nil {
  		log.Fatalf("failed to load configuration, %v", err)
	}

	client := timestreamwrite.NewFromConfig(cfg)
	listBatchLoadTasksMaxResult := int32(15)
	
	response, err := client.ListBatchLoadTasks(context.TODO(), &timestreamwrite.ListBatchLoadTasksInput{
		MaxResults: &listBatchLoadTasksMaxResult,
	})

	for i, task := range response.BatchLoadTasks {
		fmt.Println(i, aws.ToString(task.TaskId))
	}
}
```

------
#### [  Python  ]

```
import boto3
from botocore.config import Config

INGEST_ENDPOINT = "<url>"
REGION = "us-west-2"
HT_TTL_HOURS = 24
CT_TTL_DAYS = 7


def print_batch_load_tasks(batch_load_tasks):
    for batch_load_task in batch_load_tasks:
        print(batch_load_task['TaskId'])


def list_batch_load_tasks(client):
    print("\nListing batch load tasks")
    try:
        response = client.list_batch_load_tasks(MaxResults=10)
        print_batch_load_tasks(response['BatchLoadTasks'])
        next_token = response.get('NextToken', None)
        while next_token:
            response = client.list_batch_load_tasks(
                NextToken=next_token, MaxResults=10)
            print_batch_load_tasks(response['BatchLoadTasks'])
            next_token = response.get('NextToken', None)
    except Exception as err:
        print("List batch load tasks failed:", err)
        raise err


if __name__ == '__main__':
    session = boto3.Session()

    write_client = session.client('timestream-write',
                                  endpoint_url=INGEST_ENDPOINT, region_name=REGION,
                                  config=Config(read_timeout=20, max_pool_connections=5000, retries={'max_attempts': 10}))

    list_batch_load_tasks(write_client)
```

------
#### [  Node.js  ]

The following snippet uses AWS SDK for JavaScript v3. For more information about how to install the client and usage, see [Timestream Write Client - AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/index.html).

For API details, see [Class DescribeBatchLoadCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/classes/listbatchloadtaskscommand.html) and [DescribeBatchLoadTask](https://docs.aws.amazon.com/timestream/latest/developerguide/API_DescribeBatchLoadTask.html).

```
import { TimestreamWriteClient, ListBatchLoadTasksCommand } from "@aws-sdk/client-timestream-write";
const writeClient = new TimestreamWriteClient({ region: "<region>", endpoint: "<endpoint>" });

const params = {
    MaxResults: <15>
};

const command = new ListBatchLoadTasksCommand(params);

getBatchLoadTasksList(null);

async function getBatchLoadTasksList(nextToken) {
    if (nextToken) {
        params.NextToken = nextToken;
    }

    try {
        const data = await writeClient.send(command);

        data.BatchLoadTasks.forEach(function (task) {
            console.log(task.TaskId);
        });

        if (data.NextToken) {
            return getBatchLoadTasksList(data.NextToken);
        }
    } catch (error) {
        console.log("Error while listing batch load tasks", error);
    }
}
```

------
#### [  .NET  ]

```
using System;
using System.IO;
using System.Collections.Generic;
using Amazon.TimestreamWrite;
using Amazon.TimestreamWrite.Model;
using System.Threading.Tasks;

namespace TimestreamDotNetSample
{
    public class ListBatchLoadTasksExample
    {
        private readonly AmazonTimestreamWriteClient writeClient;

        public ListBatchLoadTasksExample(AmazonTimestreamWriteClient writeClient)
        {
            this.writeClient = writeClient;
        }

        public async Task ListBatchLoadTasks()
        {
            Console.WriteLine("Listing batch load tasks");

            try
            {
                var listBatchLoadTasksRequest = new ListBatchLoadTasksRequest
                {
                    MaxResults = 15
                };

                ListBatchLoadTasksResponse response = await writeClient.ListBatchLoadTasksAsync(listBatchLoadTasksRequest);

                PrintBatchLoadTasks(response.BatchLoadTasks);
                var nextToken = response.NextToken;

                while (nextToken != null)
                {
                    listBatchLoadTasksRequest.NextToken = nextToken;
                    response = await writeClient.ListBatchLoadTasksAsync(listBatchLoadTasksRequest);
                    PrintBatchLoadTasks(response.BatchLoadTasks);
                    nextToken = response.NextToken;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("List batch load tasks failed:" + e.ToString());
            }
        }

        private void PrintBatchLoadTasks(List<BatchLoadTask> tasks)
        {
            foreach (BatchLoadTask task in tasks)
                Console.WriteLine($"Task:{task.TaskId}");
        }
    }
}
```

```
using Amazon.TimestreamWrite;
using Amazon.TimestreamWrite.Model;
using Amazon;
using Amazon.TimestreamQuery;
using System.Threading.Tasks;
using System;
using CommandLine;
static class Constants
{

}
namespace TimestreamDotNetSample
{
    class MainClass
    {
        public class Options
        {

        }
        public static void Main(string[] args)
        {
            Parser.Default.ParseArguments<Options>(args)
                .WithParsed<Options>(o => {
                    MainAsync().GetAwaiter().GetResult();
                });
        }

        static async Task MainAsync()
        {
            var writeClientConfig = new AmazonTimestreamWriteConfig
            {
                ServiceURL =  "<service URL>",
                Timeout = TimeSpan.FromSeconds(20),
                MaxErrorRetry = 10
            };
            
            var writeClient = new AmazonTimestreamWriteClient(writeClientConfig);
            var example = new ListBatchLoadTasksExample(writeClient);
            await example.ListBatchLoadTasks();
        }
    }
}
```

------

# Resume batch load task
<a name="code-samples.resume-batch-load-task"></a>

You can use the following code snippets to resume batch load tasks.

------
#### [  Java  ]

```
    public void resumeBatchLoadTask(String taskId) {
            try {
                    amazonTimestreamWrite
                                    .resumeBatchLoadTask(ResumeBatchLoadTaskRequest.builder()
                                                    .taskId(taskId)
                                                    .build());

                    System.out.println("Successfully resumed batch load task.");
            } catch (ValidationException validationException) {
                    System.out.println(validationException.getMessage());
            }
    }
```

------
#### [  Go  ]

```
package main

import (
	"fmt"
	"context"
	"log"
	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/timestreamwrite"
)

func main() {
	customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
		if service == timestreamwrite.ServiceID && region == "us-west-2" {
		    return aws.Endpoint{
		        PartitionID:   "aws",
		        URL:           <URL>,
		        SigningRegion: "us-west-2",
		    }, nil
		}
		return aws.Endpoint{}, &aws.EndpointNotFoundError{}
	})

	cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithEndpointResolverWithOptions(customResolver), config.WithRegion("us-west-2"))
	
	if err != nil {
  		log.Fatalf("failed to load configuration, %v", err)
	}

	client := timestreamwrite.NewFromConfig(cfg)
	
	response, err := client.ResumeBatchLoadTask(context.TODO(), &timestreamwrite.ResumeBatchLoadTaskInput{
		TaskId: aws.String("TaskId"),
	})

	if err != nil {
		fmt.Println("Error:")
		fmt.Println(err)
	} else {
		fmt.Println("Resume batch load task is successful")
		fmt.Println(response)
	}
}
```

------
#### [  Python  ]

```
import boto3
from botocore.config import Config

INGEST_ENDPOINT="<url>"
REGION="us-west-2"
HT_TTL_HOURS = 24
CT_TTL_DAYS = 7
TASK_ID = "<TaskId>"

def resume_batch_load_task(client, task_id):
    try:
        result = client.resume_batch_load_task(TaskId=task_id)
        print("Successfully resumed batch load task: ", result)
    except Exception as err:
        print("Resume batch load task failed:", err)


if __name__ == '__main__':
    session = boto3.Session()

    write_client = session.client('timestream-write', \
        endpoint_url=INGEST_ENDPOINT, region_name=REGION, \
        config=Config(read_timeout=20, max_pool_connections = 5000, retries={'max_attempts': 10}))

    resume_batch_load_task(write_client, TASK_ID)
```

------
#### [  Node.js  ]

The following snippet uses AWS SDK for JavaScript v3. For more information about how to install the client and usage, see [Timestream Write Client - AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/index.html).

For API details, see [Class CreateBatchLoadCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/classes/describebatchloadtaskcommand.html) and [CreateBatchLoadTask](https://docs.aws.amazon.com/timestream/latest/developerguide/API_CreateBatchLoadTask.html).

```
import { TimestreamWriteClient, ResumeBatchLoadTaskCommand } from "@aws-sdk/client-timestream-write";
const writeClient = new TimestreamWriteClient({ region: "<region>", endpoint: "<endpoint>" });

const params = {
    TaskId: "<TaskId>"
};

const command = new ResumeBatchLoadTaskCommand(params);

try {
    const data = await writeClient.send(command);
    console.log("Resumed batch load task"); 
} catch (error) {
    console.log("Resume batch load task failed.", error);
	throw error; 
}
```

------
#### [  .NET  ]

```
using System;
using System.IO;
using System.Collections.Generic;
using Amazon.TimestreamWrite;
using Amazon.TimestreamWrite.Model;
using System.Threading.Tasks;

namespace TimestreamDotNetSample
{
    public class ResumeBatchLoadTaskExample
    {
        private readonly AmazonTimestreamWriteClient writeClient;

        public ResumeBatchLoadTaskExample(AmazonTimestreamWriteClient writeClient)
        {
            this.writeClient = writeClient;
        }

        public async Task ResumeBatchLoadTask(String taskId)
        {
            try
            {
                var resumeBatchLoadTaskRequest = new ResumeBatchLoadTaskRequest
                {
                    TaskId = taskId
                };
                ResumeBatchLoadTaskResponse response = await writeClient.ResumeBatchLoadTaskAsync(resumeBatchLoadTaskRequest);
                Console.WriteLine("Successfully resumed batch load task.");
            }
            catch (ResourceNotFoundException)
            {
                Console.WriteLine("Batch load task does not exist.");
            }
            catch (Exception e)
            {
                Console.WriteLine("Resume batch load task failed: " + e.ToString());
            }
        }
    }
}
```

------

# Create scheduled query
<a name="code-samples.create-scheduledquery"></a>

You can use the following code snippets to create a scheduled query with multi-measure mapping.

------
#### [  Java  ]

```
public static String DATABASE_NAME = "devops_sample_application";
public static String TABLE_NAME = "host_metrics_sample_application";
public static String HOSTNAME = "host-24Gju";
public static String SQ_NAME = "daily-sample";
public static String SCHEDULE_EXPRESSION = "cron(0/2 * * * ? *)";

// Find the average, p90, p95, and p99 CPU utilization for a specific EC2 host over the past 2 hours.
public static String QUERY = "SELECT region, az, hostname, BIN(time, 15s) AS binned_timestamp, " +
"ROUND(AVG(cpu_utilization), 2) AS avg_cpu_utilization, " +
"ROUND(APPROX_PERCENTILE(cpu_utilization, 0.9), 2) AS p90_cpu_utilization, " +
"ROUND(APPROX_PERCENTILE(cpu_utilization, 0.95), 2) AS p95_cpu_utilization, " +
"ROUND(APPROX_PERCENTILE(cpu_utilization, 0.99), 2) AS p99_cpu_utilization " +
"FROM " +  DATABASE_NAME + "." +  TABLE_NAME + " " +
"WHERE measure_name = 'metrics' " +
"AND hostname = '" + HOSTNAME + "' " +
"AND time > ago(2h) " +
"GROUP BY region, hostname, az, BIN(time, 15s) " +
"ORDER BY binned_timestamp ASC " +
"LIMIT 5";


public String createScheduledQuery(String topic_arn, 
    String role_arn, 
    String database_name, 
    String table_name) {
    System.out.println("Creating Scheduled Query");

    List<Pair<String, MeasureValueType>> sourceColToMeasureValueTypes = Arrays.asList(
        Pair.of("avg_cpu_utilization", DOUBLE),
        Pair.of("p90_cpu_utilization", DOUBLE),
        Pair.of("p95_cpu_utilization", DOUBLE),
        Pair.of("p99_cpu_utilization", DOUBLE));

    CreateScheduledQueryRequest createScheduledQueryRequest = new CreateScheduledQueryRequest()
            .withName(SQ_NAME)
            .withQueryString(QUERY)
            .withScheduleConfiguration(new ScheduleConfiguration()
                    .withScheduleExpression(SCHEDULE_EXPRESSION))
            .withNotificationConfiguration(new NotificationConfiguration()
                    .withSnsConfiguration(new SnsConfiguration()
                            .withTopicArn(topic_arn)))
            .withTargetConfiguration(new TargetConfiguration().withTimestreamConfiguration(new TimestreamConfiguration()
                    .withDatabaseName(database_name)
                    .withTableName(table_name)
                    .withTimeColumn("binned_timestamp")
                    .withDimensionMappings(Arrays.asList(
                            new DimensionMapping()
                                    .withName("region")
                                    .withDimensionValueType("VARCHAR"),
                            new DimensionMapping()
                                    .withName("az")
                                    .withDimensionValueType("VARCHAR"),
                            new DimensionMapping()
                                    .withName("hostname")
                                    .withDimensionValueType("VARCHAR")
                    ))
                    .withMultiMeasureMappings(new MultiMeasureMappings()
                        .withTargetMultiMeasureName("multi-metrics")
                        .withMultiMeasureAttributeMappings(
                            sourceColToMeasureValueTypes.stream()
                            .map(pair -> new MultiMeasureAttributeMapping()
                                .withMeasureValueType(pair.getValue().name())
                                .withSourceColumn(pair.getKey()))
                            .collect(Collectors.toList())))))
            .withErrorReportConfiguration(new ErrorReportConfiguration()
                    .withS3Configuration(new S3Configuration()
                        .withBucketName(timestreamDependencyHelper.getS3ErrorReportBucketName())))
            .withScheduledQueryExecutionRoleArn(role_arn);

    try {
        final CreateScheduledQueryResult createScheduledQueryResult = queryClient.createScheduledQuery(createScheduledQueryRequest);
        final String scheduledQueryArn = createScheduledQueryResult.getArn();
        System.out.println("Successfully created scheduled query : " + scheduledQueryArn);
        return scheduledQueryArn;
    }
    catch (Exception e) {
        System.out.println("Scheduled Query creation failed: " + e);
        throw e;
    }
}
```

------
#### [  Java v2  ]

```
public static String DATABASE_NAME = "testJavaV2DB";
public static String TABLE_NAME = "testJavaV2Table";
public static String HOSTNAME = "host-24Gju";
public static String SQ_NAME = "daily-sample";
public static String SCHEDULE_EXPRESSION = "cron(0/2 * * * ? *)";

// Find the average, p90, p95, and p99 CPU utilization for a specific EC2 host over the past 2 hours.
public static String VALID_QUERY = "SELECT region, az, hostname, BIN(time, 15s) AS binned_timestamp, " +
"ROUND(AVG(cpu_utilization), 2) AS avg_cpu_utilization, " +
"ROUND(APPROX_PERCENTILE(cpu_utilization, 0.9), 2) AS p90_cpu_utilization, " +
"ROUND(APPROX_PERCENTILE(cpu_utilization, 0.95), 2) AS p95_cpu_utilization, " +
"ROUND(APPROX_PERCENTILE(cpu_utilization, 0.99), 2) AS p99_cpu_utilization " +
"FROM " +  DATABASE_NAME + "." +  TABLE_NAME + " " +
"WHERE measure_name = 'metrics' " +
"AND hostname = '" + HOSTNAME + "' " +
"AND time > ago(2h) " +
"GROUP BY region, hostname, az, BIN(time, 15s) " +
"ORDER BY binned_timestamp ASC " +
"LIMIT 5";


private String createScheduledQueryHelper(String topicArn, String roleArn,
        String s3ErrorReportBucketName, String query, 
        TargetConfiguration targetConfiguration) {
    System.out.println("Creating Scheduled Query");

    CreateScheduledQueryRequest createScheduledQueryRequest = CreateScheduledQueryRequest.builder()
            .name(SQ_NAME)
            .queryString(query)
            .scheduleConfiguration(ScheduleConfiguration.builder()
                    .scheduleExpression(SCHEDULE_EXPRESSION)
                    .build())
            .notificationConfiguration(NotificationConfiguration.builder()
                    .snsConfiguration(SnsConfiguration.builder()
                            .topicArn(topicArn)
                            .build())
                    .build())
            .targetConfiguration(targetConfiguration)
            .errorReportConfiguration(ErrorReportConfiguration.builder()
                    .s3Configuration(S3Configuration.builder()
                            .bucketName(s3ErrorReportBucketName)
                            .objectKeyPrefix(SCHEDULED_QUERY_EXAMPLE)
                            .build())
                    .build())
            .scheduledQueryExecutionRoleArn(roleArn)
            .build();

    try {
        final CreateScheduledQueryResponse response = queryClient.createScheduledQuery(createScheduledQueryRequest);
        final String scheduledQueryArn = response.arn();
        System.out.println("Successfully created scheduled query : " + scheduledQueryArn);
        return scheduledQueryArn;
    }
    catch (Exception e) {
        System.out.println("Scheduled Query creation failed: " + e);
        throw e;
    }
}

public String createScheduledQuery(String topicArn, String roleArn,
        String databaseName, String tableName, String s3ErrorReportBucketName) {
    List<Pair<String, MeasureValueType>> sourceColToMeasureValueTypes = Arrays.asList(
            Pair.of("avg_cpu_utilization", DOUBLE),
            Pair.of("p90_cpu_utilization", DOUBLE),
            Pair.of("p95_cpu_utilization", DOUBLE),
            Pair.of("p99_cpu_utilization", DOUBLE));

    TargetConfiguration targetConfiguration = TargetConfiguration.builder()
            .timestreamConfiguration(TimestreamConfiguration.builder()
            .databaseName(databaseName)
            .tableName(tableName)
            .timeColumn("binned_timestamp")
            .dimensionMappings(Arrays.asList(
                    DimensionMapping.builder()
                            .name("region")
                            .dimensionValueType("VARCHAR")
                            .build(),
                    DimensionMapping.builder()
                            .name("az")
                            .dimensionValueType("VARCHAR")
                            .build(),
                    DimensionMapping.builder()
                            .name("hostname")
                            .dimensionValueType("VARCHAR")
                            .build()
            ))
            .multiMeasureMappings(MultiMeasureMappings.builder()
                    .targetMultiMeasureName("multi-metrics")
                    .multiMeasureAttributeMappings(
                            sourceColToMeasureValueTypes.stream()
                                    .map(pair -> MultiMeasureAttributeMapping.builder()
                                            .measureValueType(pair.getValue().name())
                                            .sourceColumn(pair.getKey())
                                            .build())
                                    .collect(Collectors.toList()))
                    .build())
            .build())
            .build();

    return createScheduledQueryHelper(topicArn, roleArn, s3ErrorReportBucketName, VALID_QUERY, targetConfiguration);
}}
```

------
#### [  Go  ]

```
SQ_ERROR_CONFIGURATION_S3_BUCKET_NAME_PREFIX = "sq-error-configuration-sample-s3-bucket-"
HOSTNAME            = "host-24Gju"
SQ_NAME             = "daily-sample"
SCHEDULE_EXPRESSION = "cron(0/1 * * * ? *)"
QUERY               = "SELECT region, az, hostname, BIN(time, 15s) AS binned_timestamp, " +
    "ROUND(AVG(cpu_utilization), 2) AS avg_cpu_utilization, " +
    "ROUND(APPROX_PERCENTILE(cpu_utilization, 0.9), 2) AS p90_cpu_utilization, " +
    "ROUND(APPROX_PERCENTILE(cpu_utilization, 0.95), 2) AS p95_cpu_utilization, " +
    "ROUND(APPROX_PERCENTILE(cpu_utilization, 0.99), 2) AS p99_cpu_utilization " +
    "FROM %s.%s " +
    "WHERE measure_name = 'metrics' " +
    "AND hostname = '" + HOSTNAME + "' " +
    "AND time > ago(2h) " +
    "GROUP BY region, hostname, az, BIN(time, 15s) " +
    "ORDER BY binned_timestamp ASC " +
    "LIMIT 5"
s3BucketName = utils.SQ_ERROR_CONFIGURATION_S3_BUCKET_NAME_PREFIX + generateRandomStringWithSize(5)

func generateRandomStringWithSize(size int) string {
     rand.Seed(time.Now().UnixNano())
     alphaNumericList := []rune("abcdefghijklmnopqrstuvwxyz0123456789")
     randomPrefix := make([]rune, size)
     for i := range randomPrefix {
         randomPrefix[i] = alphaNumericList[rand.Intn(len(alphaNumericList))]
     }
     return string(randomPrefix)
 }

func (timestreamBuilder TimestreamBuilder) createScheduledQuery(topicArn string, roleArn string, s3ErrorReportBucketName string,
query string, targetConfiguration timestreamquery.TargetConfiguration) (string, error) {

createScheduledQueryInput := &timestreamquery.CreateScheduledQueryInput{
    Name:        aws.String(SQ_NAME),
    QueryString: aws.String(query),
    ScheduleConfiguration: &timestreamquery.ScheduleConfiguration{
        ScheduleExpression: aws.String(SCHEDULE_EXPRESSION),
    },
    NotificationConfiguration: &timestreamquery.NotificationConfiguration{
        SnsConfiguration: &timestreamquery.SnsConfiguration{
            TopicArn: aws.String(topicArn),
        },
    },
    TargetConfiguration: &targetConfiguration,
    ErrorReportConfiguration: &timestreamquery.ErrorReportConfiguration{
        S3Configuration: &timestreamquery.S3Configuration{
            BucketName: aws.String(s3ErrorReportBucketName),
        },
    },
    ScheduledQueryExecutionRoleArn: aws.String(roleArn),
}

createScheduledQueryOutput, err := timestreamBuilder.QuerySvc.CreateScheduledQuery(createScheduledQueryInput)

if err != nil {
    fmt.Printf("Error: %s", err.Error())
} else {
    fmt.Println("createScheduledQueryResult is successful")
    return *createScheduledQueryOutput.Arn, nil
}
return "", err
}

 func (timestreamBuilder TimestreamBuilder) CreateValidScheduledQuery(topicArn string, roleArn string, s3ErrorReportBucketName string,
     sqDatabaseName string, sqTableName string, databaseName string, tableName string) (string, error) {

     targetConfiguration := timestreamquery.TargetConfiguration{
         TimestreamConfiguration: &timestreamquery.TimestreamConfiguration{
             DatabaseName: aws.String(sqDatabaseName),
             TableName:    aws.String(sqTableName),
             TimeColumn:   aws.String("binned_timestamp"),
             DimensionMappings: []*timestreamquery.DimensionMapping{
                 {
                     Name:               aws.String("region"),
                     DimensionValueType: aws.String("VARCHAR"),
                 },
                 {
                     Name:               aws.String("az"),
                     DimensionValueType: aws.String("VARCHAR"),
                 },
                 {
                     Name:               aws.String("hostname"),
                     DimensionValueType: aws.String("VARCHAR"),
                 },
             },
             MultiMeasureMappings: &timestreamquery.MultiMeasureMappings{
                 TargetMultiMeasureName: aws.String("multi-metrics"),
                 MultiMeasureAttributeMappings: []*timestreamquery.MultiMeasureAttributeMapping{
                     {
                         SourceColumn:     aws.String("avg_cpu_utilization"),
                         MeasureValueType: aws.String(timestreamquery.MeasureValueTypeDouble),
                     },
                     {
                         SourceColumn:     aws.String("p90_cpu_utilization"),
                         MeasureValueType: aws.String(timestreamquery.MeasureValueTypeDouble),
                     },
                     {
                         SourceColumn:     aws.String("p95_cpu_utilization"),
                         MeasureValueType: aws.String(timestreamquery.MeasureValueTypeDouble),
                     },
                     {
                         SourceColumn:     aws.String("p99_cpu_utilization"),
                         MeasureValueType: aws.String(timestreamquery.MeasureValueTypeDouble),
                     },
                 },
             },
         },
     }
     return timestreamBuilder.createScheduledQuery(topicArn, roleArn, s3ErrorReportBucketName,
         fmt.Sprintf(QUERY, databaseName, tableName), targetConfiguration)
 }
```

------
#### [  Python  ]

```
HOSTNAME = "host-24Gju"
SQ_NAME = "daily-sample"
ERROR_BUCKET_NAME = "scheduledquerysamplerrorbucket" + ''.join([choice(ascii_lowercase) for _ in range(5)])
QUERY = \
    "SELECT region, az, hostname, BIN(time, 15s) AS binned_timestamp, " \
    "    ROUND(AVG(cpu_utilization), 2) AS avg_cpu_utilization, " \
    "    ROUND(APPROX_PERCENTILE(cpu_utilization, 0.9), 2) AS p90_cpu_utilization, " \
    "    ROUND(APPROX_PERCENTILE(cpu_utilization, 0.95), 2) AS p95_cpu_utilization, " \
    "    ROUND(APPROX_PERCENTILE(cpu_utilization, 0.99), 2) AS p99_cpu_utilization " \
    "FROM " + database_name + "." + table_name + " " \
    "WHERE measure_name = 'metrics' " \
    "AND hostname = '" + self.HOSTNAME + "' " \
    "AND time > ago(2h) " \
    "GROUP BY region, hostname, az, BIN(time, 15s) " \
    "ORDER BY binned_timestamp ASC " \
    "LIMIT 5"

def create_scheduled_query_helper(self, topic_arn, role_arn, query, target_configuration):
    print("\nCreating Scheduled Query")
    schedule_configuration = {
        'ScheduleExpression': 'cron(0/2 * * * ? *)'
    }
    notification_configuration = {
        'SnsConfiguration': {
            'TopicArn': topic_arn
        }
    }
    error_report_configuration = {
        'S3Configuration': {
            'BucketName': ERROR_BUCKET_NAME
        }
    }

    try:
        create_scheduled_query_response = \
            query_client.create_scheduled_query(Name=self.SQ_NAME,
                 QueryString=query,
                 ScheduleConfiguration=schedule_configuration,
                 NotificationConfiguration=notification_configuration,
                 TargetConfiguration=target_configuration,
                 ScheduledQueryExecutionRoleArn=role_arn,
                 ErrorReportConfiguration=error_report_configuration
                 )
        print("Successfully created scheduled query : ", create_scheduled_query_response['Arn'])
        return create_scheduled_query_response['Arn']
    except Exception as err:
        print("Scheduled Query creation failed:", err)
        raise err

def create_valid_scheduled_query(self, topic_arn, role_arn):
    target_configuration = {
        'TimestreamConfiguration': {
            'DatabaseName': self.sq_database_name,
            'TableName': self.sq_table_name,
            'TimeColumn': 'binned_timestamp',
            'DimensionMappings': [
                {'Name': 'region', 'DimensionValueType': 'VARCHAR'},
                {'Name': 'az', 'DimensionValueType': 'VARCHAR'},
                {'Name': 'hostname', 'DimensionValueType': 'VARCHAR'}
            ],
            'MultiMeasureMappings': {
                'TargetMultiMeasureName': 'target_name',
                'MultiMeasureAttributeMappings': [
                    {'SourceColumn': 'avg_cpu_utilization', 'MeasureValueType': 'DOUBLE',
                     'TargetMultiMeasureAttributeName': 'avg_cpu_utilization'},
                    {'SourceColumn': 'p90_cpu_utilization', 'MeasureValueType': 'DOUBLE',
                     'TargetMultiMeasureAttributeName': 'p90_cpu_utilization'},
                    {'SourceColumn': 'p95_cpu_utilization', 'MeasureValueType': 'DOUBLE',
                     'TargetMultiMeasureAttributeName': 'p95_cpu_utilization'},
                    {'SourceColumn': 'p99_cpu_utilization', 'MeasureValueType': 'DOUBLE',
                     'TargetMultiMeasureAttributeName': 'p99_cpu_utilization'},
                ]
            }
        }
    }

    return self.create_scheduled_query_helper(topic_arn, role_arn, QUERY, target_configuration)
```

------
#### [  Node.js  ]

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/sample_apps_reinvent2021/js/schedule-query-example.js).

```
const DATABASE_NAME = 'devops_sample_application';
const TABLE_NAME = 'host_metrics_sample_application';
const SQ_DATABASE_NAME = 'sq_result_database';
const SQ_TABLE_NAME = 'sq_result_table';
const HOSTNAME = "host-24Gju";
const SQ_NAME = "daily-sample";
const SCHEDULE_EXPRESSION = "cron(0/1 * * * ? *)";

// Find the average, p90, p95, and p99 CPU utilization for a specific EC2 host over the past 2 hours.
const VALID_QUERY = "SELECT region, az, hostname, BIN(time, 15s) AS binned_timestamp, " +
    " ROUND(AVG(cpu_utilization), 2) AS avg_cpu_utilization, " +
    " ROUND(APPROX_PERCENTILE(cpu_utilization, 0.9), 2) AS p90_cpu_utilization, " +
    " ROUND(APPROX_PERCENTILE(cpu_utilization, 0.95), 2) AS p95_cpu_utilization, " +
    " ROUND(APPROX_PERCENTILE(cpu_utilization, 0.99), 2) AS p99_cpu_utilization " +
    "FROM " + DATABASE_NAME + "." + TABLE_NAME + " " +
    "WHERE measure_name = 'metrics' " +
    " AND hostname = '" + HOSTNAME + "' " +
    " AND time > ago(2h) " +
    "GROUP BY region, hostname, az, BIN(time, 15s) " +
    "ORDER BY binned_timestamp ASC " +
    "LIMIT 5";

async function createScheduledQuery(topicArn, roleArn, s3ErrorReportBucketName) {
    console.log("Creating Valid Scheduled Query");
    const DimensionMappingList = [{
            'Name': 'region',
            'DimensionValueType': 'VARCHAR'
        },
        {
            'Name': 'az',
            'DimensionValueType': 'VARCHAR'
        },
        {
            'Name': 'hostname',
            'DimensionValueType': 'VARCHAR'
        }
    ];

    const MultiMeasureMappings = {
        TargetMultiMeasureName: "multi-metrics",
        MultiMeasureAttributeMappings: [{
                'SourceColumn': 'avg_cpu_utilization',
                'MeasureValueType': 'DOUBLE'
            },
            {
                'SourceColumn': 'p90_cpu_utilization',
                'MeasureValueType': 'DOUBLE'
            },
            {
                'SourceColumn': 'p95_cpu_utilization',
                'MeasureValueType': 'DOUBLE'
            },
            {
                'SourceColumn': 'p99_cpu_utilization',
                'MeasureValueType': 'DOUBLE'
            },
        ]
    }

    const timestreamConfiguration = {
        DatabaseName: SQ_DATABASE_NAME,
        TableName: SQ_TABLE_NAME,
        TimeColumn: "binned_timestamp",
        DimensionMappings: DimensionMappingList,
        MultiMeasureMappings: MultiMeasureMappings
    }

    const createScheduledQueryRequest = {
        Name: SQ_NAME,
        QueryString: VALID_QUERY,
        ScheduleConfiguration: {
            ScheduleExpression: SCHEDULE_EXPRESSION
        },
        NotificationConfiguration: {
            SnsConfiguration: {
                TopicArn: topicArn
            }
        },
        TargetConfiguration: {
            TimestreamConfiguration: timestreamConfiguration
        },
        ScheduledQueryExecutionRoleArn: roleArn,
        ErrorReportConfiguration: {
            S3Configuration: {
                BucketName: s3ErrorReportBucketName
            }
        }
    };
    try {
        const data = await queryClient.createScheduledQuery(createScheduledQueryRequest).promise();
        console.log("Successfully created scheduled query: " + data.Arn);
        return data.Arn;
    } catch (err) {
        console.log("Scheduled Query creation failed: ", err);
        throw err;
    }
}
```

------
#### [  .NET  ]

```
public const string Hostname = "host-24Gju";
public const string SqName = "timestream-sample";
public const string SqDatabaseName = "sq_result_database";
public const string SqTableName = "sq_result_table";

public const string ErrorConfigurationS3BucketNamePrefix = "error-configuration-sample-s3-bucket-";
public const string ScheduleExpression = "cron(0/2 * * * ? *)";

// Find the average, p90, p95, and p99 CPU utilization for a specific EC2 host over the past 2 hours.
public const string ValidQuery = "SELECT region, az, hostname, BIN(time, 15s) AS binned_timestamp, " +
      "ROUND(AVG(cpu_utilization), 2) AS avg_cpu_utilization, " +
      "ROUND(APPROX_PERCENTILE(cpu_utilization, 0.9), 2) AS p90_cpu_utilization, " +
      "ROUND(APPROX_PERCENTILE(cpu_utilization, 0.95), 2) AS p95_cpu_utilization, " +
      "ROUND(APPROX_PERCENTILE(cpu_utilization, 0.99), 2) AS p99_cpu_utilization " +
      "FROM " + Constants.DATABASE_NAME + "." + Constants.TABLE_NAME + " " +
      "WHERE measure_name = 'metrics' " +
      "AND hostname = '" + Hostname + "' " +
      "AND time > ago(2h) " +
      "GROUP BY region, hostname, az, BIN(time, 15s) " +
      "ORDER BY binned_timestamp ASC " +
      "LIMIT 5";

private async Task<String> CreateValidScheduledQuery(string topicArn, string roleArn,
             string databaseName, string tableName, string s3ErrorReportBucketName)
 {
     List<MultiMeasureAttributeMapping> sourceColToMeasureValueTypes =
         new List<MultiMeasureAttributeMapping>()
         {
             new()
             {
                 SourceColumn = "avg_cpu_utilization",
                 MeasureValueType = MeasureValueType.DOUBLE.Value
             },
             new()
             {
                 SourceColumn = "p90_cpu_utilization",
                 MeasureValueType = MeasureValueType.DOUBLE.Value
             },
             new()
             {
                 SourceColumn = "p95_cpu_utilization",
                 MeasureValueType = MeasureValueType.DOUBLE.Value
             },
             new()
             {
                 SourceColumn = "p99_cpu_utilization",
                 MeasureValueType = MeasureValueType.DOUBLE.Value
             }
         };

     TargetConfiguration targetConfiguration = new TargetConfiguration()
     {
         TimestreamConfiguration = new TimestreamConfiguration()
         {
             DatabaseName = databaseName,
             TableName = tableName,
             TimeColumn = "binned_timestamp",
             DimensionMappings = new List<DimensionMapping>()
             {
                 new()
                 {
                     Name = "region",
                     DimensionValueType = "VARCHAR"
                 },
                 new()
                 {
                     Name = "az",
                     DimensionValueType = "VARCHAR"
                 },
                 new()
                 {
                     Name = "hostname",
                     DimensionValueType = "VARCHAR"
                 }
             },
             MultiMeasureMappings = new MultiMeasureMappings()
             {
                 TargetMultiMeasureName = "multi-metrics",
                 MultiMeasureAttributeMappings = sourceColToMeasureValueTypes
             }
         }
     };
     return await CreateScheduledQuery(topicArn, roleArn, s3ErrorReportBucketName,
         ScheduledQueryConstants.ValidQuery, targetConfiguration);
 }

private async Task<String> CreateScheduledQuery(string topicArn, string roleArn,
             string s3ErrorReportBucketName, string query, TargetConfiguration targetConfiguration)
 {
     try
     {
         Console.WriteLine("Creating Scheduled Query");
         CreateScheduledQueryResponse response = await _amazonTimestreamQuery.CreateScheduledQueryAsync(
             new CreateScheduledQueryRequest()
             {
                 Name = ScheduledQueryConstants.SqName,
                 QueryString = query,
                 ScheduleConfiguration = new ScheduleConfiguration()
                 {
                     ScheduleExpression = ScheduledQueryConstants.ScheduleExpression
                 },
                 NotificationConfiguration = new NotificationConfiguration()
                 {
                     SnsConfiguration = new SnsConfiguration()
                     {
                         TopicArn = topicArn
                     }
                 },
                 TargetConfiguration = targetConfiguration,
                 ErrorReportConfiguration = new ErrorReportConfiguration()
                 {
                     S3Configuration = new S3Configuration()
                     {
                         BucketName = s3ErrorReportBucketName
                     }
                 },
                 ScheduledQueryExecutionRoleArn = roleArn
             });
         Console.WriteLine($"Successfully created scheduled query : {response.Arn}");
         return response.Arn;
     }
     catch (Exception e)
     {
         Console.WriteLine($"Scheduled Query creation failed: {e}");
         throw;
     }
 }
```

------

# List scheduled query
<a name="code-samples.list-scheduledquery"></a>

You can use the following code snippets to list your scheduled queries.

------
#### [  Java  ]

```
public void listScheduledQueries() {
    System.out.println("Listing Scheduled Query");
    try {
        String nextToken = null;
        List<String> scheduledQueries = new ArrayList<>();

        do {
            ListScheduledQueriesResult listScheduledQueriesResult =
                    queryClient.listScheduledQueries(new ListScheduledQueriesRequest()
                            .withNextToken(nextToken).withMaxResults(10));
            List<ScheduledQuery> scheduledQueryList = listScheduledQueriesResult.getScheduledQueries();

            printScheduledQuery(scheduledQueryList);
            nextToken = listScheduledQueriesResult.getNextToken();
        } while (nextToken != null);
    }
    catch (Exception e) {
        System.out.println("List Scheduled Query failed: " + e);
        throw e;
    }
}

public void printScheduledQuery(List<ScheduledQuery> scheduledQueryList) {
    for (ScheduledQuery scheduledQuery: scheduledQueryList) {
        System.out.println(scheduledQuery.getArn());
    }
}
```

------
#### [  Java v2  ]

```
public void listScheduledQueries() {
    System.out.println("Listing Scheduled Query");
    try {
        String nextToken = null;

        do {
            ListScheduledQueriesResponse listScheduledQueriesResult =
                    queryClient.listScheduledQueries(ListScheduledQueriesRequest.builder()
                            .nextToken(nextToken).maxResults(10)
                            .build());
            List<ScheduledQuery> scheduledQueryList = listScheduledQueriesResult.scheduledQueries();

            printScheduledQuery(scheduledQueryList);
            nextToken = listScheduledQueriesResult.nextToken();
        } while (nextToken != null);
    }
    catch (Exception e) {
        System.out.println("List Scheduled Query failed: " + e);
        throw e;
    }
}

public void printScheduledQuery(List<ScheduledQuery> scheduledQueryList) {
    for (ScheduledQuery scheduledQuery: scheduledQueryList) {
        System.out.println(scheduledQuery.arn());
    }
}
```

------
#### [  Go  ]

```
func (timestreamBuilder TimestreamBuilder) ListScheduledQueries() ([]*timestreamquery.ScheduledQuery, error) {
 
     var nextToken *string = nil
     var scheduledQueries []*timestreamquery.ScheduledQuery
     for ok := true; ok; ok = nextToken != nil {
         listScheduledQueriesInput := &timestreamquery.ListScheduledQueriesInput{
             MaxResults: aws.Int64(15),
         }
         if nextToken != nil {
             listScheduledQueriesInput.NextToken = aws.String(*nextToken)
         }
 
         listScheduledQueriesOutput, err := timestreamBuilder.QuerySvc.ListScheduledQueries(listScheduledQueriesInput)
         if err != nil {
             fmt.Printf("Error: %s", err.Error())
             return nil, err
         }
         scheduledQueries = append(scheduledQueries, listScheduledQueriesOutput.ScheduledQueries...)
         nextToken = listScheduledQueriesOutput.NextToken
     }
     return scheduledQueries, nil
 }
```

------
#### [  Python  ]

```
def list_scheduled_queries(self):
    print("\nListing Scheduled Queries")
    try:
        response = self.query_client.list_scheduled_queries(MaxResults=10)
        self.print_scheduled_queries(response['ScheduledQueries'])
        next_token = response.get('NextToken', None)
        while next_token:
            response = self.query_client.list_scheduled_queries(NextToken=next_token, MaxResults=10)
            self.print_scheduled_queries(response['ScheduledQueries'])
            next_token = response.get('NextToken', None)
    except Exception as err:
        print("List scheduled queries failed:", err)
        raise err

@staticmethod
def print_scheduled_queries(scheduled_queries):
    for scheduled_query in scheduled_queries:
        print(scheduled_query['Arn'])
```

------
#### [  Node.js  ]

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/sample_apps_reinvent2021/js/schedule-query-example.js).

```
async function listScheduledQueries() {
     console.log("Listing Scheduled Query");
     try {
         var nextToken = null;
         do {
             var params = {
                 MaxResults: 10,
                 NextToken: nextToken
             }
             var data = await queryClient.listScheduledQueries(params).promise();
             var scheduledQueryList = data.ScheduledQueries;
             printScheduledQuery(scheduledQueryList);
             nextToken = data.NextToken;
         }
         while (nextToken != null);
     }  catch (err) {
         console.log("List Scheduled Query failed: ", err);
         throw err;
     }
 }

 async function printScheduledQuery(scheduledQueryList) {
     scheduledQueryList.forEach(element => console.log(element.Arn));
 }
```

------
#### [  .NET  ]

```
private async Task ListScheduledQueries()
 {
     try
     {
         Console.WriteLine("Listing Scheduled Query");
         string nextToken;
         do
         {
             ListScheduledQueriesResponse response =
                 await _amazonTimestreamQuery.ListScheduledQueriesAsync(new ListScheduledQueriesRequest());
             foreach (var scheduledQuery in response.ScheduledQueries)
             {
                 Console.WriteLine($"{scheduledQuery.Arn}");
             }

             nextToken = response.NextToken;
         } while (nextToken != null);
     }
     catch (Exception e)
     {
         Console.WriteLine($"List Scheduled Query failed: {e}");
         throw;
     }
 }
```

------

# Describe scheduled query
<a name="code-samples.describe-scheduledquery"></a>

You can use the following code snippets to describe a scheduled query.

------
#### [  Java  ]

```
public void describeScheduledQueries(String scheduledQueryArn) {
    System.out.println("Describing Scheduled Query");
    try {
        DescribeScheduledQueryResult describeScheduledQueryResult = queryClient.describeScheduledQuery(new DescribeScheduledQueryRequest().withScheduledQueryArn(scheduledQueryArn));
        System.out.println(describeScheduledQueryResult);
    }
    catch (ResourceNotFoundException e) {
        System.out.println("Scheduled Query doesn't exist");
        throw e;
    }
    catch (Exception e) {
        System.out.println("Describe Scheduled Query failed: " + e);
        throw e;
    }
}
```

------
#### [  Java v2  ]

```
public void describeScheduledQueries(String scheduledQueryArn) {
    System.out.println("Describing Scheduled Query");
    try {
        DescribeScheduledQueryResponse describeScheduledQueryResult =
                queryClient.describeScheduledQuery(DescribeScheduledQueryRequest.builder()
                        .scheduledQueryArn(scheduledQueryArn)
                        .build());
        System.out.println(describeScheduledQueryResult);
    }
    catch (ResourceNotFoundException e) {
        System.out.println("Scheduled Query doesn't exist");
        throw e;
    }
    catch (Exception e) {
        System.out.println("Describe Scheduled Query failed: " + e);
        throw e;
    }
}
```

------
#### [  Go  ]

```
func (timestreamBuilder TimestreamBuilder) DescribeScheduledQuery(scheduledQueryArn string) error {
 
     describeScheduledQueryInput := &timestreamquery.DescribeScheduledQueryInput{
         ScheduledQueryArn: aws.String(scheduledQueryArn),
     }
     describeScheduledQueryOutput, err := timestreamBuilder.QuerySvc.DescribeScheduledQuery(describeScheduledQueryInput)
 
     if err != nil {
         if aerr, ok := err.(awserr.Error); ok {
             switch aerr.Code() {
             case timestreamquery.ErrCodeResourceNotFoundException:
                 fmt.Println(timestreamquery.ErrCodeResourceNotFoundException, aerr.Error())
             default:
                 fmt.Printf("Error: %s", err.Error())
             }
         } else {
             fmt.Printf("Error: %s", aerr.Error())
         }
         return err
     } else {
         fmt.Println("DescribeScheduledQuery is successful, below is the output:")
         fmt.Println(describeScheduledQueryOutput.ScheduledQuery)
         return nil
     }
 }
```

------
#### [  Python  ]

```
def describe_scheduled_query(self, scheduled_query_arn):
    print("\nDescribing Scheduled Query")
    try:
        response = self.query_client.describe_scheduled_query(ScheduledQueryArn=scheduled_query_arn)
        if 'ScheduledQuery' in response:
            response = response['ScheduledQuery']
            for key in response:
                print("{} :{}".format(key, response[key]))
    except self.query_client.exceptions.ResourceNotFoundException as err:
        print("Scheduled Query doesn't exist")
        raise err
    except Exception as err:
        print("Scheduled Query describe failed:", err)
        raise err
```

------
#### [  Node.js  ]

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/sample_apps_reinvent2021/js/schedule-query-example.js).

```
async function describeScheduledQuery(scheduledQueryArn) {
     console.log("Describing Scheduled Query");
     var params = {
         ScheduledQueryArn: scheduledQueryArn
     }
     try {
         const data = await queryClient.describeScheduledQuery(params).promise();
         console.log(data.ScheduledQuery);
     } catch (err) {
         console.log("Describe Scheduled Query failed: ", err);
         throw err;
     }
 }
```

------
#### [  .NET  ]

```
private async Task DescribeScheduledQuery(string scheduledQueryArn)
 {
     try
     {
         Console.WriteLine("Describing Scheduled Query");
         DescribeScheduledQueryResponse response = await _amazonTimestreamQuery.DescribeScheduledQueryAsync(
             new DescribeScheduledQueryRequest()
             {
                 ScheduledQueryArn = scheduledQueryArn
             });
         Console.WriteLine($"{JsonConvert.SerializeObject(response.ScheduledQuery)}");
     }
     catch (ResourceNotFoundException e)
     {
         Console.WriteLine($"Scheduled Query doesn't exist: {e}");
         throw;
     }
     catch (Exception e)
     {
         Console.WriteLine($"Describe Scheduled Query failed: {e}");
         throw;
     }
 }
```

------

# Execute scheduled query
<a name="code-samples.execute-scheduledquery"></a>

You can use the following code snippets to run a scheduled query.

------
#### [  Java  ]

```
public void executeScheduledQueries(String scheduledQueryArn, Date invocationTime) {
    System.out.println("Executing Scheduled Query");
    try {
        ExecuteScheduledQueryResult executeScheduledQueryResult = queryClient.executeScheduledQuery(new ExecuteScheduledQueryRequest()
                .withScheduledQueryArn(scheduledQueryArn)
                .withInvocationTime(invocationTime)
        );

    }
    catch (ResourceNotFoundException e) {
        System.out.println("Scheduled Query doesn't exist");
        throw e;
    }
    catch (Exception e) {
        System.out.println("Execution Scheduled Query failed: " + e);
        throw e;
    }
}
```

------
#### [  Java v2  ]

```
public void executeScheduledQuery(String scheduledQueryArn) {
    System.out.println("Executing Scheduled Query");
    try {
        ExecuteScheduledQueryResponse executeScheduledQueryResult = queryClient.executeScheduledQuery(ExecuteScheduledQueryRequest.builder()
                .scheduledQueryArn(scheduledQueryArn)
                .invocationTime(Instant.now())
                .build()
        );

        System.out.println("Execute ScheduledQuery response code: " + executeScheduledQueryResult.sdkHttpResponse().statusCode());

    }
    catch (ResourceNotFoundException e) {
        System.out.println("Scheduled Query doesn't exist");
        throw e;
    }
    catch (Exception e) {
        System.out.println("Execution Scheduled Query failed: " + e);
        throw e;
    }
}
```

------
#### [  Go  ]

```
func (timestreamBuilder TimestreamBuilder) ExecuteScheduledQuery(scheduledQueryArn string, invocationTime time.Time) error {
 
     executeScheduledQueryInput := &timestreamquery.ExecuteScheduledQueryInput{
         ScheduledQueryArn: aws.String(scheduledQueryArn),
         InvocationTime:    aws.Time(invocationTime),
     }
     executeScheduledQueryOutput, err := timestreamBuilder.QuerySvc.ExecuteScheduledQuery(executeScheduledQueryInput)
 
     if err != nil {
         if aerr, ok := err.(awserr.Error); ok {
             switch aerr.Code() {
             case timestreamquery.ErrCodeResourceNotFoundException:
                 fmt.Println(timestreamquery.ErrCodeResourceNotFoundException, aerr.Error())
             default:
                 fmt.Printf("Error: %s", aerr.Error())
             }
         } else {
             fmt.Printf("Error: %s", err.Error())
         }
         return err
     } else {
         fmt.Println("ExecuteScheduledQuery is successful, below is the output:")
         fmt.Println(executeScheduledQueryOutput.GoString())
         return nil
     }
 }
```

------
#### [  Python  ]

```
def execute_scheduled_query(self, scheduled_query_arn, invocation_time):
    print("\nExecuting Scheduled Query")
    try:
        self.query_client.execute_scheduled_query(ScheduledQueryArn=scheduled_query_arn, InvocationTime=invocation_time)
        print("Successfully started executing scheduled query")
    except self.query_client.exceptions.ResourceNotFoundException as err:
        print("Scheduled Query doesn't exist")
        raise err
    except Exception as err:
        print("Scheduled Query execution failed:", err)
        raise err
```

------
#### [  Node.js  ]

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/sample_apps_reinvent2021/js/schedule-query-example.js).

```
async function executeScheduledQuery(scheduledQueryArn, invocationTime) {
     console.log("Executing Scheduled Query");
     var params = {
         ScheduledQueryArn: scheduledQueryArn,
         InvocationTime: invocationTime
     }
     try {
         await queryClient.executeScheduledQuery(params).promise();
     } catch (err) {
         console.log("Execute Scheduled Query failed: ", err);
         throw err;
     }
 }
```

------
#### [  .NET  ]

```
private async Task ExecuteScheduledQuery(string scheduledQueryArn, DateTime invocationTime)
 {
     try
     {
         Console.WriteLine("Running Scheduled Query");
         await _amazonTimestreamQuery.ExecuteScheduledQueryAsync(new ExecuteScheduledQueryRequest()
         {
             ScheduledQueryArn = scheduledQueryArn,
             InvocationTime = invocationTime
         });
         Console.WriteLine("Successfully started manual run of scheduled query");
     }
     catch (ResourceNotFoundException e)
     {
         Console.WriteLine($"Scheduled Query doesn't exist: {e}");
         throw;
     }
     catch (Exception e)
     {
         Console.WriteLine($"Execute Scheduled Query failed: {e}");
         throw;
     }
 }
```

------

# Update scheduled query
<a name="code-samples.update-scheduledquery"></a>

You can use the following code snippets to update a scheduled query.

------
#### [  Java  ]

```
public void updateScheduledQueries(String scheduledQueryArn) {
    System.out.println("Updating Scheduled Query");
    try {
        queryClient.updateScheduledQuery(new UpdateScheduledQueryRequest()
                .withScheduledQueryArn(scheduledQueryArn)
                .withState(ScheduledQueryState.DISABLED));
        System.out.println("Successfully update scheduled query state");
    }
    catch (ResourceNotFoundException e) {
        System.out.println("Scheduled Query doesn't exist");
        throw e;
    }
    catch (Exception e) {
        System.out.println("Execution Scheduled Query failed: " + e);
        throw e;
    }
}
```

------
#### [  Java v2  ]

```
public void updateScheduledQuery(String scheduledQueryArn, ScheduledQueryState state) {
    System.out.println("Updating Scheduled Query");
    try {
        queryClient.updateScheduledQuery(UpdateScheduledQueryRequest.builder()
                .scheduledQueryArn(scheduledQueryArn)
                .state(state)
                .build());
        System.out.println("Successfully update scheduled query state");
    }
    catch (ResourceNotFoundException e) {
        System.out.println("Scheduled Query doesn't exist");
        throw e;
    }
    catch (Exception e) {
        System.out.println("Execution Scheduled Query failed: " + e);
        throw e;
    }
}
```

------
#### [  Go  ]

```
func (timestreamBuilder TimestreamBuilder) UpdateScheduledQuery(scheduledQueryArn string) error {

     updateScheduledQueryInput := &timestreamquery.UpdateScheduledQueryInput{
         ScheduledQueryArn: aws.String(scheduledQueryArn),
         State:             aws.String(timestreamquery.ScheduledQueryStateDisabled),
     }
     _, err := timestreamBuilder.QuerySvc.UpdateScheduledQuery(updateScheduledQueryInput)

     if err != nil {
         if aerr, ok := err.(awserr.Error); ok {
             switch aerr.Code() {
             case timestreamquery.ErrCodeResourceNotFoundException:
                 fmt.Println(timestreamquery.ErrCodeResourceNotFoundException, aerr.Error())
             default:
                 fmt.Printf("Error: %s", aerr.Error())
             }
         } else {
             fmt.Printf("Error: %s", err.Error())
         }
         return err
     } else {
         fmt.Println("UpdateScheduledQuery is successful")
         return nil
     }
 }
```

------
#### [  Python  ]

```
def update_scheduled_query(self, scheduled_query_arn, state):
    print("\nUpdating Scheduled Query")
    try:
        self.query_client.update_scheduled_query(ScheduledQueryArn=scheduled_query_arn,
                                                 State=state)
        print("Successfully update scheduled query state to", state)
    except self.query_client.exceptions.ResourceNotFoundException as err:
        print("Scheduled Query doesn't exist")
        raise err
    except Exception as err:
        print("Scheduled Query deletion failed:", err)
        raise err
```

------
#### [  Node.js  ]

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/sample_apps_reinvent2021/js/schedule-query-example.js).

```
async function updateScheduledQueries(scheduledQueryArn) {
     console.log("Updating Scheduled Query");
     var params = {
         ScheduledQueryArn: scheduledQueryArn,
         State: "DISABLED"
     }
     try {
         await queryClient.updateScheduledQuery(params).promise();
         console.log("Successfully update scheduled query state");
     } catch (err) {
         console.log("Update Scheduled Query failed: ", err);
         throw err;
     }
 }
```

------
#### [  .NET  ]

```
private async Task UpdateScheduledQuery(string scheduledQueryArn, ScheduledQueryState state)
 {
     try
     {
         Console.WriteLine("Updating Scheduled Query");
         await _amazonTimestreamQuery.UpdateScheduledQueryAsync(new UpdateScheduledQueryRequest()
         {
             ScheduledQueryArn = scheduledQueryArn,
             State = state
         });
         Console.WriteLine("Successfully update scheduled query state");
     }
     catch (ResourceNotFoundException e)
     {
         Console.WriteLine($"Scheduled Query doesn't exist: {e}");
         throw;
     }
     catch (Exception e)
     {
         Console.WriteLine($"Update Scheduled Query failed: {e}");
         throw;
     }
 }
```

------

# Delete scheduled query
<a name="code-samples.delete-scheduledquery"></a>

You can use the following code snippets to delete a scheduled query.

------
#### [  Java  ]

```
public void deleteScheduledQuery(String scheduledQueryArn) {
    System.out.println("Deleting Scheduled Query");

    try {
        queryClient.deleteScheduledQuery(new DeleteScheduledQueryRequest().withScheduledQueryArn(scheduledQueryArn));
        System.out.println("Successfully deleted scheduled query");
    }
    catch (Exception e) {
        System.out.println("Scheduled Query deletion failed: " + e);
    }
}
```

------
#### [  Java v2  ]

```
public void deleteScheduledQuery(String scheduledQueryArn) {
    System.out.println("Deleting Scheduled Query");

    try {
        queryClient.deleteScheduledQuery(DeleteScheduledQueryRequest.builder()
                .scheduledQueryArn(scheduledQueryArn).build());
        System.out.println("Successfully deleted scheduled query");
    }
    catch (Exception e) {
        System.out.println("Scheduled Query deletion failed: " + e);
    }
}
```

------
#### [  Go  ]

```
func (timestreamBuilder TimestreamBuilder) DeleteScheduledQuery(scheduledQueryArn string) error {
 
     deleteScheduledQueryInput := &timestreamquery.DeleteScheduledQueryInput{
         ScheduledQueryArn: aws.String(scheduledQueryArn),
     }
     _, err := timestreamBuilder.QuerySvc.DeleteScheduledQuery(deleteScheduledQueryInput)
 
     if err != nil {
         fmt.Println("Error:")
         if aerr, ok := err.(awserr.Error); ok {
             switch aerr.Code() {
             case timestreamquery.ErrCodeResourceNotFoundException:
                 fmt.Println(timestreamquery.ErrCodeResourceNotFoundException, aerr.Error())
             default:
                 fmt.Printf("Error: %s", aerr.Error())
             }
         } else {
             fmt.Printf("Error: %s", err.Error())
         }
         return err
     } else {
         fmt.Println("DeleteScheduledQuery is successful")
         return nil
     }
 }
```

------
#### [  Python  ]

```
def delete_scheduled_query(self, scheduled_query_arn):
    print("\nDeleting Scheduled Query")
    try:
        self.query_client.delete_scheduled_query(ScheduledQueryArn=scheduled_query_arn)
        print("Successfully deleted scheduled query :", scheduled_query_arn)
    except Exception as err:
        print("Scheduled Query deletion failed:", err)
        raise err
```

------
#### [  Node.js  ]

The following snippet uses the AWS SDK for JavaScript V2 style. It is based on the sample application at [Node.js sample Amazon Timestream for LiveAnalytics application on GitHub](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/sample_apps_reinvent2021/js/schedule-query-example.js).

```
async function deleteScheduleQuery(scheduledQueryArn) {
     console.log("Deleting Scheduled Query");
     const params = {
         ScheduledQueryArn: scheduledQueryArn
     }
     try {
         await queryClient.deleteScheduledQuery(params).promise();
         console.log("Successfully deleted scheduled query");
     } catch (err) {
         console.log("Scheduled Query deletion failed: ", err);
     }
 }
```

------
#### [  .NET  ]

```
private async Task DeleteScheduledQuery(string scheduledQueryArn)
 {
     try
     {
         Console.WriteLine("Deleting Scheduled Query");
         await _amazonTimestreamQuery.DeleteScheduledQueryAsync(new DeleteScheduledQueryRequest()
         {
             ScheduledQueryArn = scheduledQueryArn
         });
         Console.WriteLine($"Successfully deleted scheduled query : {scheduledQueryArn}");
     }
     catch (Exception e)
     {
         Console.WriteLine($"Scheduled Query deletion failed: {e}");
         throw;
     }
 }
```

------

# Using batch load in Timestream for LiveAnalytics
<a name="batch-load"></a>

With *batch load* for Amazon Timestream for LiveAnalytics, you can ingest CSV files stored in Amazon S3 into Timestream in batches. With this new functionality, you can have your data in Timestream for LiveAnalytics without having to rely on other tools or write custom code. You can use batch load for backfilling data with flexible wait times, such as data that isn't immediately required for querying or analysis. 

You can create batch load tasks by using the AWS Management Console, the AWS CLI, and the AWS SDKs. For more information, see [Using batch load with the console](batch-load-using-console.md), [Using batch load with the AWS CLI](batch-load-using-cli.md), and [Using batch load with the AWS SDKs](batch-load-using-sdk.md).

In addition to batch load, you can write multiple records at the same time with the WriteRecords API operation. For guidance about which to use, see [Choosing between the WriteRecords API operation and batch load](writes.writes-or-batch-load.md).

**Topics**
+ [Batch load concepts in Timestream](batch-load-concepts.md)
+ [Batch load prerequisites](batch-load-prerequisites.md)
+ [Batch load best practices](batch-load-best-practices.md)
+ [Preparing a batch load data file](batch-load-preparing-data-file.md)
+ [Data model mappings for batch load](batch-load-data-model-mappings.md)
+ [Using batch load with the console](batch-load-using-console.md)
+ [Using batch load with the AWS CLI](batch-load-using-cli.md)
+ [Using batch load with the AWS SDKs](batch-load-using-sdk.md)
+ [Using batch load error reports](batch-load-using-error-reports.md)

# Batch load concepts in Timestream
<a name="batch-load-concepts"></a>

Review the following concepts to better understand batch load functionality. 

**Batch load task** – The task that defines your source data and destination in Amazon Timestream. You specify additional configuration such as the data model when you create the batch load task. You can create batch load tasks through the AWS Management Console, the AWS CLI, and the AWS SDKs. 

**Import destination** – The destination database and table in Timestream. For information about creating databases and tables, see [Create a database](console_timestream.md#console_timestream.db.using-console) and [Create a table](console_timestream.md#console_timestream.table.using-console).

**Data source** – The source CSV file that is stored in an S3 bucket. For information about preparing the data file, see [Preparing a batch load data file](batch-load-preparing-data-file.md). For information about S3 pricing, see [Amazon S3 pricing](https://aws.amazon.com/s3/pricing/).

**Batch load error report** – A report that stores information about the errors of a batch load task. You define the S3 location for batch load error reports as part of a batch load task. For information about information in the reports, see [Using batch load error reports](batch-load-using-error-reports.md).

**Data model mapping** – A batch load mapping for time, dimensions, and measures that is from a data source in an S3 location to a target Timestream for LiveAnalytics table. For more information, see [Data model mappings for batch load](batch-load-data-model-mappings.md).

# Batch load prerequisites
<a name="batch-load-prerequisites"></a>

This is a list of prerequisites for using batch load. For best practices, see [Batch load best practices](batch-load-best-practices.md).
+ Batch load source data is stored in Amazon S3 in CSV format with headers.
+ For each Amazon S3 source bucket, you must have the following permissions in an attached policy:

  ```
  "s3:GetObject",
  "s3:GetBucketAcl"
  "s3:ListBucket"
  ```

  Similarly, for each Amazon S3 output bucket where reports are written, you must have the following permissions in an attached policy:

  ```
  "s3:PutObject",
  "s3:GetBucketAcl"
  ```

  For example:

------
#### [ JSON ]

****  

  ```
  {
      "Version":"2012-10-17",		 	 	 
      "Statement": [
          {
              "Action": [
                  "s3:GetObject",
                  "s3:GetBucketAcl",
                  "s3:ListBucket"
              ],
              "Resource": [
                  "arn:aws:s3:::amzn-s3-demo-source-bucket1\u201d",
                  "arn:aws:s3:::amzn-s3-demo-source-bucket2\u201d"
              ],
              "Effect": "Allow"
          },
          {
              "Action": [
                  "s3:PutObject",
                  "s3:GetBucketAcl"
              ],
              "Resource": [
                  "arn:aws:s3:::amzn-s3-demo-destination-bucket\u201d"
              ],
              "Effect": "Allow"
          }
      ]
  }
  ```

------
+ Timestream for LiveAnalytics parses the CSV by mapping information that's provided in the data model to CSV headers. The data must have a column that represents the timestamp, at least one dimension column, and at least one measure column.
+ The S3 buckets used with batch load must be in the same region and from the same account as the Timestream for LiveAnalytics table that is used in batch load.
+ The `timestamp` column must be a long data type that represents the time since the Unix epoch. For example, the timestamp `2021-03-25T08:45:21Z` would be represented as `1616661921`. Timestream supports seconds, milliseconds, microseconds, and nanoseconds for the timestamp precision. When using the query language, you can convert between formats with functions such as `to_unixtime`. For more information, see [Date / time functions](date-time-functions.md).
+ Timestream supports the string data type for dimension values. It supports long, double, string, and boolean data types for measure columns.

For batch load limits and quotas, see [Batch load](ts-limits.md#limits.batch-load).

# Batch load best practices
<a name="batch-load-best-practices"></a>

Batch load works best (high throughput) when adhering to the following conditions and recommendations:

1. CSV files submitted for ingestion are small, specifically with a file size of 100 MB–1 GB, to improve parallelism and speed of ingestion.

1. Avoid simultaneously ingesting data into the same table (e.g. using the WriteRecords API operation, or a scheduled query) when the batch load is in progress. This might lead to throttles, and the batch load task will fail.

1. Do not add, modify, or remove files from the S3 bucket used in batch load while the batch load task is running.

1. Do not delete or revoke permissions from tables or source, or report S3 buckets that have scheduled or in-progress batch load tasks.

1. When ingesting data with a high cardinality set of dimension values, follow guidance at [Recommendations for partitioning multi-measure records](data-modeling.md#data-modeling-multi-measure-partitioning).

1. Make sure you test the data for correctness by submitting a small file. You will be charged for any data submitted to batch load regardless of correctness. For more information about pricing, see [Amazon Timestream pricing](https://aws.amazon.com/timestream/pricing/).

1. Do not resume a batch load task unless `ActiveMagneticStorePartitions` are below 250. The job may be throttled and fail. Submiting multiple jobs at the same time for the same database should reduce the number.

The following are console best practices:

1. Use the [builder](batch-load-using-console.md#batch-load-using-visual-builder) only for simpler data modeling that uses only one measure name for multi-measure records.

1. For more complex data modeling, use JSON. For example, use JSON when you use multiple measure names when using multi-measure records. 

For additional Timestream for LiveAnalytics best practices, see [Best practices](best-practices.md).

# Preparing a batch load data file
<a name="batch-load-preparing-data-file"></a>

A source data file has delimiter-separated values. The more specific term, comma-separated values (CSV) is used generically. Valid column separators include commas and pipes. Records are separated by new lines. Files must be stored in Amazon S3. When you create a new batch load task, the location of the source data is specified by an ARN for the file. A file contains headers. One column represents the timestamp. At least one other column represents a measure.

The S3 buckets used with batch load must be in the same Region as the Timestream for LiveAnalytics table that is used in batch load. Don't add or remove files from the S3 bucket used in batch load after the batch load task has been submitted. For information about working with S3 buckets, see [Getting started with Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/GetStartedWithS3.html).

**Note**  
CSV files that are generated by some applications such as Excel might contain a byte order mark (BOM) that conflicts with the expected encoding. Timestream for LiveAnalytics batch load tasks that reference a CSV file with a BOM throw an error when they're processed programmatically. To avoid this, you can remove the BOM, which is an invisible character.  
For example, you can save the file from an application such as Notepad\$1\$1 that lets you specify a new encoding. You can also use a programmatic option that reads the first line, removes the character from the line, and writes the new value over the first line in the file.  
When saving from Excel, there are multiple CSV options. Saving with a different CSV option might prevent the described issue. But you should check the result because a change in encoding can affect some characters.

## CSV format parameters
<a name="batch-load-data-file-options"></a>

You use escape characters when you're representing a value that is otherwise reserved by the format parameters. For example, if the quote character is a double quote, to represent a double quote in the data, place the escape character before the double quote.

For information about when to specify these when creating a batch load task, see [Create a batch load task](batch-load-using-console.md#console_timestream.create-batch-load.using-console).


| Parameter | Options | 
| --- | --- | 
| Column separator | (Comma (',') \$1 Pipe ('\$1') \$1 Semicolon (';') \$1 Tab ('/t') \$1 Blank space (' ')) | 
| Escape character | none | 
| Quote character | Console: (Double quote (") \$1 Single quote (')) | 
| Null value | Blank space (' ') | 
| Trim white space | Console: (No \$1 Yes) | 

# Data model mappings for batch load
<a name="batch-load-data-model-mappings"></a>

The following discusses the schema for data model mappings and gives and example.

## Data model mappings schema
<a name="batch-load-data-model-mappings-schema"></a>

The `CreateBatchLoadTask` request syntax and a `BatchLoadTaskDescription` object returned by a call to `DescribeBatchLoadTask` include a `DataModelConfiguration` object that includes the `DataModel` for batch loading. The `DataModel` defines mappings from source data that's stored in CSV format in an S3 location to a target Timestream for LiveAnalytics database and table. 

The `TimeColumn` field indicates the source data's location for the value to be mapped to the destination table's `time` column in Timestream for LiveAnalytics. The `TimeUnit` specifies the unit for the `TimeColumn`, and can be one of `MILLISECONDS`, `SECONDS`, `MICROSECONDS`, or `NANOSECONDS`. There are also mappings for dimensions and measures. Dimension mappings are composed of source columns and target fields. 

For more information, see [DimensionMapping](https://docs.aws.amazon.com/timestream/latest/developerguide/API_DimensionMapping). The mappings for measures have two options, `MixedMeasureMappings` and `MultiMeasureMappings`.

To summarize, a `DataModel` contains mappings from a data source in an S3 location to a target Timestream for LiveAnalytics table for the following.
+ Time
+ Dimensions
+ Measures

If possible, we recommend that you map measure data to multi-measure records in Timestream for LiveAnalytics. For information about the benefits of multi-measure records, see [Multi-measure records](writes.md#writes.writing-data-multi-measure). 

If multiple measures in the source data are stored in one row, you can map those multiple measures to multi-measure records in Timestream for LiveAnalytics using `MultiMeasureMappings`. If there are values that must map to a single-measure record, you can use `MixedMeasureMappings`. 

`MixedMeasureMappings` and `MultiMeasureMappings` both include `MultiMeasureAttributeMappings`. Multi-measure records are supported regardless of whether single-measure records are needed.

If only multi-measure target records are needed in Timestream for LiveAnalytics, you can define measure mappings in the following structure.

```
CreateBatchLoadTask
    MeasureNameColumn
    MultiMeasureMappings
        TargetMultiMeasureName
        MultiMeasureAttributeMappings array
```

**Note**  
We recommend using `MultiMeasureMappings` whenever possible.

If single-measure target records are needed in Timestream for LiveAnalytics, you can define measure mappings in the following structure.

```
CreateBatchLoadTask
    MeasureNameColumn
    MixedMeasureMappings array
        MixedMeasureMapping
            MeasureName
            MeasureValueType
            SourceColumn
            TargetMeasureName
            MultiMeasureAttributeMappings array
```

When you use `MultiMeasureMappings`, the `MultiMeasureAttributeMappings` array is always required. When you use the `MixedMeasureMappings` array, if the `MeasureValueType` is `MULTI` for a given `MixedMeasureMapping`, `MultiMeasureAttributeMappings` is required for that `MixedMeasureMapping`. Otherwise, `MeasureValueType` indicates the measure type for the single-measure record.

Either way, there is an array of `MultiMeasureAttributeMapping` available. You define the mappings to multi-measure records in each `MultiMeasureAttributeMapping` as follows:

`SourceColumn`  
The column in the source data that is located in Amazon S3.

`TargetMultiMeasureAttributeName`  
The name of the target multi-measure name in the destination table. This input is required when `MeasureNameColumn` is not provided. If `MeasureNameColumn` is provided, the value from that column is used as the multi-measure name.

`MeasureValueType`  
One of `DOUBLE`, `BIGINT` `BOOLEAN`, `VARCHAR`, or `TIMESTAMP`.

## Data model mappings with `MultiMeasureMappings` example
<a name="batch-load-data-model-mappings-example-multi"></a>

This example demonstrates mapping to multi-measure records, the preferred approach, which store each measure value in a dedicated column. You can download a sample CSV at [sample CSV](samples/batch-load-sample-file.csv.zip). The sample has the following headings to map to a target column in a Timestream for LiveAnalytics table.
+ `time`
+ `measure_name`
+ `region`
+ `location`
+ `hostname`
+ `memory_utilization`
+ `cpu_utilization`

Identify the `time` and `measure_name` columns in the CSV file. In this case these map directly to the Timestream for LiveAnalytics table columns of the same names.
+ `time` maps to `time`
+ `measure_name` maps to `measure_name` (or your chosen value)

When using the API, you specify `time` in the `TimeColumn` field and a supported time unit value such as `MILLISECONDS` in the `TimeUnit` field. These correspond to **Source columnn name** and **Timestamp time input** in the console. You can group or partition records using `measure_name` which is defined with the `MeasureNameColumn` key.

In the sample, `region`, `location`, and `hostname` are dimensions. Dimensions are mapped in an array of `DimensionMapping` objects.

For measures, the value `TargetMultiMeasureAttributeName` will become a column in the Timestream for LiveAnalytics table. You can keep the same name such as in this example. Or you can specify a new one. `MeasureValueType` is one of `DOUBLE`, `BIGINT`, `BOOLEAN`, `VARCHAR`, or `TIMESTAMP`. 

```
{
  "TimeColumn": "time",
  "TimeUnit": "MILLISECONDS",
  "DimensionMappings": [
    {
      "SourceColumn": "region",
      "DestinationColumn": "region"
    },
    {
      "SourceColumn": "location",
      "DestinationColumn": "location"
    },
    {
      "SourceColumn": "hostname",
      "DestinationColumn": "hostname"
    }
  ],
  "MeasureNameColumn": "measure_name",
  "MultiMeasureMappings": {
    "MultiMeasureAttributeMappings": [
      {
        "SourceColumn": "memory_utilization",
        "TargetMultiMeasureAttributeName": "memory_utilization",
        "MeasureValueType": "DOUBLE"
      },
      {
        "SourceColumn": "cpu_utilization",
        "TargetMultiMeasureAttributeName": "cpu_utilization",
        "MeasureValueType": "DOUBLE"
      }
    ]
  }
}
```

![\[Visual builder interface showing column mappings for timestream data attributes and types.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/column-mapping.jpg)


## Data model mappings with `MixedMeasureMappings` example
<a name="batch-load-data-model-mappings-example-mixed"></a>

We recommend that you only use this approach when you need to map to single-measure records in Timestream for LiveAnalytics.

# Using batch load with the console
<a name="batch-load-using-console"></a>

Following are steps for using batch load with the AWS Management Console. You can download a sample CSV at [sample CSV](samples/batch-load-sample-file.csv.zip).

**Topics**
+ [Access batch load](#console_timestream.access-batch-load.using-console)
+ [Create a batch load task](#console_timestream.create-batch-load.using-console)
+ [Resume a batch load task](#console_timestream.resume-batch-load.using-console)
+ [Using the visual builder](#batch-load-using-visual-builder)

## Access batch load
<a name="console_timestream.access-batch-load.using-console"></a>

Follow these steps to access batch load using the AWS Management Console.

1. Open the [Amazon Timestream console](https://console.aws.amazon.com/timestream).

1. In the navigation pane, choose **Management Tools**, and then choose **Batch load tasks**.

1. From here, you can view the list of batch load tasks and drill into a given task for more details. You can also create and resume tasks.

## Create a batch load task
<a name="console_timestream.create-batch-load.using-console"></a>

Follow these steps to create a batch load task using the AWS Management Console.

1. Open the [Amazon Timestream console](https://console.aws.amazon.com/timestream).

1. In the navigation pane, choose **Management Tools**, and then choose **Batch load tasks**.

1. Choose **Create batch load task**.

1. In **Import destination**, choose the following.
   + **Target database** – Select the name of the database created in [Create a database](console_timestream.md#console_timestream.db.using-console).
   + **Target table** – Select the name of the table created in [Create a table](console_timestream.md#console_timestream.table.using-console).

   If necessary, you can add a table from this panel with the **Create new table** button.

1. From **Data source S3 location** in **Data source**, select the S3 bucket where the source data is stored. Use the **Browse S3** button to view S3 resources the active AWS account has access to, or enter the S3 location URL. The data source must be located in the same region.

1. In **File format settings** (expandable section), you can use the default settings to parse input data. You can also choose **Advanced settings**. From there you can choose **CSV format parameters**, and select parameters to parse input data. For information about these parameters, see [CSV format parameters](batch-load-preparing-data-file.md#batch-load-data-file-options).

1. From **Configure data model mapping**, configure the data model. For additional data model guidance, see [Data model mappings for batch load](batch-load-data-model-mappings.md)
   + From **Data model mapping**, choose **Mapping configuration input**, and choose one of the following.
     + **Visual builder** – To map data visually, choose **TargetMultiMeasureName** or **MeasureNameColumn**. Then from **Visual builder**, map the columns.

       Visual builder automatically detects and loads the source column headers from the data source file when a single CSV file is selected as the data source. Choose the attribute and data type to create your mapping.

       For information about using the visual builder, see [Using the visual builder](#batch-load-using-visual-builder).
     + **JSON editor** – A freeform JSON editor for configuring your data model. Choose this option if you're familiar with Timestream for LiveAnalytics and want to build advanced data model mappings.
     + **JSON file from S3** – Select a JSON model file you have stored in S3. Choose this option if you've already configured a data model and want to reuse it for additional batch loads.

1. From **Error logs S3 location** in **Error log report**, select the S3 location that will be used to report errors. For information about how to use this report, see [Using batch load error reports](batch-load-using-error-reports.md).

1. For **Encryption key type**, choose one of the following.
   + **Amazon S3-managed key (SSE-S3)** – An encryption key that Amazon S3 creates, manages, and uses for you.
   + **AWS KMS key (SSE-KMS)** – An encryption key protected by AWS Key Management Service (AWS KMS).

1. Choose **Next**.

1. On the **Review and create page**, review the settings and edit as necessary.
**Note**  
You can't change batch load task settings after the task has been created. Task completion times will vary based on the amount of data being imported.

1. Choose **Create batch load task**.

## Resume a batch load task
<a name="console_timestream.resume-batch-load.using-console"></a>

When you select a batch load task with a status of "Progress stopped" which is still resumable, you are prompted to resume the task. There is also a banner with a **Resume task** button when you view the details for those tasks. Resumable tasks have a "resume by" date. After that date expires, tasks cannot be resumed.

## Using the visual builder
<a name="batch-load-using-visual-builder"></a>

You can use the visual builder to map source data columns one or more CSV file(s) stored in an S3 bucket to destination columns in a Timestream for LiveAnalytics table.

**Note**  
Your role will need the `SelectObjectContent` permission for the file. Without this, you will need to add and delete columns manually.

### Auto load source columns mode
<a name="batch-load-using-visual-builder-auto-load"></a>

Timestream for LiveAnalytics can automatically scan the source CSV file for column names if you specify one bucket only. When there are no existing mappings, you can choose **Import source columns**.

1. With the **Visual builder** option selected from the **Mapping configuration input settings**, set the Timestamp time input. `Milliseconds` is the default setting.

1. Click the **Load source columns** button to import the column headers found in the source data file. The table will be populated with the source column header names from the data source file.

1. Choose the **Target table column name**, **Timestream attribute type**, and **Data type** for each source column.

   For details about these columns and possible values, see [Mapping fields](#batch-load-using-visual-builder-mapping-fields).

1. Use the drag-to-fill feature to set the value for multiple columns at once.

### Manually add source columns
<a name="batch-load-using-visual-builder-manually-add"></a>

If you're using a bucket or CSV prefix and not a single CSV, you can add and delete column mappings from the visual editor with the **Add column mapping** and **Delete column mapping** buttons. There is also a button to reset mappings.

### Mapping fields
<a name="batch-load-using-visual-builder-mapping-fields"></a>
+ **Source column name** – The name of a column in the source file that represents a measure to import. Timestream for LiveAnalytics can populate this value automatically when you use **Import source columns**.
+ **Target table column name** – Optional input that indicates the column name for the measure in the target table.
+ **Timestream attribute type** – The attribute type of the data in the specified source column such as `DIMENSION`.
  + **TIMESTAMP** – Specifies when a measure was collected.
  + **MULTI** – Multiple measures are represented.
  + **DIMENSION** – Time series metadata.
  + **MEASURE\$1NAME** – For single-measure records, this is the measure name.
+ **Data type** – The type of Timestream column, such as `BOOLEAN`.
  + **BIGINT** – A 64-bit integer.
  + **BOOLEAN** – The two truth values of logic—true and false.
  + **DOUBLE** – 64-bit variable-precision number.
  + **TIMESTAMP** – An instance in time that uses nanosecond precision time in UTC, and tracks the time since the Unix epoch.

# Using batch load with the AWS CLI
<a name="batch-load-using-cli"></a>

**Setup**

To start using batch load, go through the following steps.

1. Install the AWS CLI using the instructions at [Accessing Amazon Timestream for LiveAnalytics using the AWS CLI](Tools.CLI.md).

1. Run the following command to verify that the Timestream CLI commands have been updated. Verify that create-batch-load-task is in the list.

   `aws timestream-write help`

1. Prepare a data source using the instructions at [Preparing a batch load data file](batch-load-preparing-data-file.md).

1. Create a database and table using the instructions at [Accessing Amazon Timestream for LiveAnalytics using the AWS CLI](Tools.CLI.md).

1. Create an S3 bucket for report output. The bucket must be in the same Region. For more information about buckets, see [Creating, configuring, and working with Amazon S3 buckets](https://docs.aws.amazon.com/AmazonS3/latest/userguide/creating-buckets-s3.html).

1. Create a batch load task. For steps, see [Create a batch load task](#batch-load-using-cli-create-task).

1. Confirm the status of the task. For steps, see [Describe batch load task](#batch-load-using-cli-describe-task).

## Create a batch load task
<a name="batch-load-using-cli-create-task"></a>

You can create a batch load task with the `create-batch-load-task` command. When you create a batch load task using the CLI, you can use a JSON parameter, `cli-input-json`, which lets you aggregate the parameters into a single JSON fragment. You can also break those details apart using several other parameters including `data-model-configuration`, `data-source-configuration`, `report-configuration`, `target-database-name`, and `target-table-name`.

For an example, see [Create batch load task example](#batch-load-using-cli-example)

## Describe batch load task
<a name="batch-load-using-cli-describe-task"></a>

You can retrieve a batch load task description as follows.

```
aws timestream-write describe-batch-load-task --task-id <value>
```

Following is an example response.

```
{
    "BatchLoadTaskDescription": {
        "TaskId": "<TaskId>",
        "DataSourceConfiguration": {
            "DataSourceS3Configuration": {
                "BucketName": "test-batch-load-west-2",
                "ObjectKeyPrefix": "sample.csv"
            },
            "CsvConfiguration": {},
            "DataFormat": "CSV"
        },
        "ProgressReport": {
            "RecordsProcessed": 2,
            "RecordsIngested": 0,
            "FileParseFailures": 0,
            "RecordIngestionFailures": 2,
            "FileFailures": 0,
            "BytesIngested": 119
        },
        "ReportConfiguration": {
            "ReportS3Configuration": {
                "BucketName": "test-batch-load-west-2",
                "ObjectKeyPrefix": "<ObjectKeyPrefix>",
                "EncryptionOption": "SSE_S3"
            }
        },
        "DataModelConfiguration": {
            "DataModel": {
                "TimeColumn": "timestamp",
                "TimeUnit": "SECONDS",
                "DimensionMappings": [
                    {
                        "SourceColumn": "vehicle",
                        "DestinationColumn": "vehicle"
                    },
                    {
                        "SourceColumn": "registration",
                        "DestinationColumn": "license"
                    }
                ],
                "MultiMeasureMappings": {
                    "TargetMultiMeasureName": "test",
                    "MultiMeasureAttributeMappings": [
                        {
                            "SourceColumn": "wgt",
                            "TargetMultiMeasureAttributeName": "weight",
                            "MeasureValueType": "DOUBLE"
                        },
                        {
                            "SourceColumn": "spd",
                            "TargetMultiMeasureAttributeName": "speed",
                            "MeasureValueType": "DOUBLE"
                        },
                        {
                            "SourceColumn": "fuel",
                            "TargetMultiMeasureAttributeName": "fuel",
                            "MeasureValueType": "DOUBLE"
                        },
                        {
                            "SourceColumn": "miles",
                            "TargetMultiMeasureAttributeName": "miles",
                            "MeasureValueType": "DOUBLE"
                        }
                    ]
                }
            }
        },
        "TargetDatabaseName": "BatchLoadExampleDatabase",
        "TargetTableName": "BatchLoadExampleTable",
        "TaskStatus": "FAILED",
        "RecordVersion": 1,
        "CreationTime": 1677167593.266,
        "LastUpdatedTime": 1677167602.38
    }
}
```

## List batch load tasks
<a name="batch-load-using-cli-list-tasks"></a>

You can list batch load tasks as follows.

```
aws timestream-write list-batch-load-tasks
```

An output appears as follows.

```
{
    "BatchLoadTasks": [
        {
            "TaskId": "<TaskId>",
            "TaskStatus": "FAILED",
            "DatabaseName": "BatchLoadExampleDatabase",
            "TableName": "BatchLoadExampleTable",
            "CreationTime": 1677167593.266,
            "LastUpdatedTime": 1677167602.38
        }
    ]
}
```

## Resume batch load task
<a name="batch-load-using-cli-resume-task"></a>

You can resume a batch load task as follows.

```
aws timestream-write resume-batch-load-task --task-id <value>
```

A response can indicate success or contain error information.

## Create batch load task example
<a name="batch-load-using-cli-example"></a>

**Example**  

1. Create a Timestream for LiveAnalytics database named `BatchLoad` and a table named `BatchLoadTest`. Verify and, if necessary, adjust the values for `MemoryStoreRetentionPeriodInHours` and `MagneticStoreRetentionPeriodInDays`.

   ```
   aws timestream-write create-database --database-name BatchLoad \
   
   aws timestream-write create-table --database-name BatchLoad \
   --table-name BatchLoadTest \
   --retention-properties "{\"MemoryStoreRetentionPeriodInHours\": 12, \"MagneticStoreRetentionPeriodInDays\": 100}"
   ```

1. Using the console, create an S3 bucket and copy the `sample.csv` file to that location. You can download a sample CSV at [sample CSV](samples/batch-load-sample-file.csv.zip).

1. Using the console create an S3 bucket for Timestream for LiveAnalytics to write a report if the batch load task completes with errors.

1. Create a batch load task. Make sure to replace *\$1INPUT\$1BUCKET* and *\$1REPORT\$1BUCKET* with the buckets that you created in the preceding steps.

   ```
   aws timestream-write create-batch-load-task \
   --data-model-configuration "{\
               \"DataModel\": {\
                 \"TimeColumn\": \"timestamp\",\
                 \"TimeUnit\": \"SECONDS\",\
                 \"DimensionMappings\": [\
                   {\
                     \"SourceColumn\": \"vehicle\"\
                   },\
                   {\
                     \"SourceColumn\": \"registration\",\
                     \"DestinationColumn\": \"license\"\
                   }\
                 ],
                 \"MultiMeasureMappings\": {\
                   \"TargetMultiMeasureName\": \"mva_measure_name\",\
                   \"MultiMeasureAttributeMappings\": [\
                     {\
                       \"SourceColumn\": \"wgt\",\
                       \"TargetMultiMeasureAttributeName\": \"weight\",\
                       \"MeasureValueType\": \"DOUBLE\"\
                     },\
                     {\
                       \"SourceColumn\": \"spd\",\
                       \"TargetMultiMeasureAttributeName\": \"speed\",\
                       \"MeasureValueType\": \"DOUBLE\"\
                     },\
                     {\
                       \"SourceColumn\": \"fuel_consumption\",\
                       \"TargetMultiMeasureAttributeName\": \"fuel\",\
                       \"MeasureValueType\": \"DOUBLE\"\
                     },\
                     {\
                       \"SourceColumn\": \"miles\",\
                       \"MeasureValueType\": \"BIGINT\"\
                     }\
                   ]\
                 }\
               }\
             }" \
   --data-source-configuration "{
               \"DataSourceS3Configuration\": {\
                 \"BucketName\": \"$INPUT_BUCKET\",\
                 \"ObjectKeyPrefix\": \"$INPUT_OBJECT_KEY_PREFIX\"
               },\
               \"DataFormat\": \"CSV\"\
             }" \
   --report-configuration "{\
               \"ReportS3Configuration\": {\
                 \"BucketName\": \"$REPORT_BUCKET\",\
                 \"EncryptionOption\": \"SSE_S3\"\
               }\
             }" \
   --target-database-name BatchLoad \
   --target-table-name BatchLoadTest
   ```

   The preceding command returns the following output.

   ```
   {
       "TaskId": "TaskId "
   }
   ```

1. Check on the progress of the task. Make sure you replace *\$1TASK\$1ID* with the task id that was returned in the preceding step.

   ```
   aws timestream-write describe-batch-load-task --task-id $TASK_ID 
   ```
**Example output**  

```
{
    "BatchLoadTaskDescription": {
        "ProgressReport": {
            "BytesIngested": 1024,
            "RecordsIngested": 2,
            "FileFailures": 0,
            "RecordIngestionFailures": 0,
            "RecordsProcessed": 2,
            "FileParseFailures": 0
        },
        "DataModelConfiguration": {
            "DataModel": {
                "DimensionMappings": [
                    {
                        "SourceColumn": "vehicle",
                        "DestinationColumn": "vehicle"
                    },
                    {
                        "SourceColumn": "registration",
                        "DestinationColumn": "license"
                    }
                ],
                "TimeUnit": "SECONDS",
                "TimeColumn": "timestamp",
                "MultiMeasureMappings": {
                    "MultiMeasureAttributeMappings": [
                        {
                            "TargetMultiMeasureAttributeName": "weight",
                            "SourceColumn": "wgt",
                            "MeasureValueType": "DOUBLE"
                        },
                        {
                            "TargetMultiMeasureAttributeName": "speed",
                            "SourceColumn": "spd",
                            "MeasureValueType": "DOUBLE"
                        },
                        {
                            "TargetMultiMeasureAttributeName": "fuel",
                            "SourceColumn": "fuel_consumption",
                            "MeasureValueType": "DOUBLE"
                        },
                        {
                            "TargetMultiMeasureAttributeName": "miles",
                            "SourceColumn": "miles",
                            "MeasureValueType": "DOUBLE"
                        }
                    ],
                    "TargetMultiMeasureName": "mva_measure_name"
                }
            }
        },
        "TargetDatabaseName": "BatchLoad",
        "CreationTime": 1672960381.735,
        "TaskStatus": "SUCCEEDED",
        "RecordVersion": 1,
        "TaskId": "TaskId ",
        "TargetTableName": "BatchLoadTest",
        "ReportConfiguration": {
            "ReportS3Configuration": {
                "EncryptionOption": "SSE_S3",
                "ObjectKeyPrefix": "ObjectKeyPrefix ",
                "BucketName": "amzn-s3-demo-bucket"
            }
        },
        "DataSourceConfiguration": {
            "DataSourceS3Configuration": {
                "ObjectKeyPrefix": "sample.csv",
                "BucketName": "amzn-s3-demo-source-bucket"
            },
            "DataFormat": "CSV",
            "CsvConfiguration": {}
        },
        "LastUpdatedTime": 1672960387.334
    }
}
```

# Using batch load with the AWS SDKs
<a name="batch-load-using-sdk"></a>

For examples of how to create, describe, and list batch load tasks with the AWS SDKs, see [Create batch load task](code-samples.create-batch-load.md), [Describe batch load task](code-samples.describe-batch-load.md), [List batch load tasks](code-samples.list-batch-load-tasks.md), and [Resume batch load task](code-samples.resume-batch-load-task.md).

# Using batch load error reports
<a name="batch-load-using-error-reports"></a>

Batch load tasks have one of the following status values:
+ `CREATED` (**Created**) – Task is created.
+ `IN_PROGRESS` (**In progress**) – Task is in progress.
+ `FAILED` (**Failed**) – Task has completed. But one or more errors was detected.
+ `SUCCEEDED` (**Completed**) – Task has completed with no errors.
+ `PROGRESS_STOPPED` (**Progress stopped**) – Task has stopped but not completed. You can attempt to resume the task.
+ `PENDING_RESUME` (**Pending resume**) – The task is pending to resume.

When there are errors, an error log report is created in the S3 bucket defined for that. Errors are categorized as taskErrors or fileErrors in separate arrays. Following is an example error report.

```
{
    "taskId": "9367BE28418C5EF902676482220B631C",
    "taskErrors": [],
    "fileErrors": [
        {
            "fileName": "example.csv",
            "errors": [
                {
                    "reason": "The record timestamp is outside the time range of the data ingestion window.",
                    "lineRanges": [
                        [
                            2,
                            3
                        ]
                    ]
                }
            ]
        }
    ]
}
```

# Using scheduled queries in Timestream for LiveAnalytics
<a name="scheduledqueries"></a>

The scheduled query feature in Amazon Timestream for LiveAnalytics is a fully managed, serverless, and scalable solution for calculating and storing aggregates, rollups, and other forms of preprocessed data typically used for operational dashboards, business reports, ad-hoc analytics, and other applications. Scheduled queries make real-time analytics more performant and cost-effective, so you can derive additional insights from your data, and can continue to make better business decisions. 

With scheduled queries, you define the real-time analytics queries that compute aggregates, rollups, and other operations on the data—and Amazon Timestream for LiveAnalytics periodically and automatically runs these queries and reliably writes the query results into a separate table. The data is typically calculated and updated into these tables within a few minutes. 

You can then point your dashboards and reports to query the tables that contain aggregated data instead of querying the considerably larger source tables. This leads to performance and cost gains that can exceed orders of magnitude. This is because the tables with aggregated data contain much less data than the source tables, so they offer faster queries and cheaper data storage. 

Additionally, tables with scheduled queries offer all of the existing functionality of a Timestream for LiveAnalytics table. For example, you can query the tables using SQL. You can visualize the data stored in the tables using Grafana. You can also ingest data into the table using Amazon Kinesis, Amazon MSK, AWS IoT Core, and Telegraf. You can configure data retention policies on these tables for automatic data lifecycle management. 

Because the data retention of the tables that contain aggregated data is fully decoupled from that of source tables, you can also choose to reduce the data retention of the source tables and keep the aggregate data for a much longer duration, at a fraction of the data storage cost. Scheduled queries make real-time analytics faster, cheaper, and therefore more accessible to many more customers, so they can monitor their applications and drive better data-driven business decisions. 

**Topics**
+ [Benefits](#scheduledqueries-benifits)
+ [Use cases](#scheduledqueries-usescases)
+ [Example](#scheduledqueries-example)
+ [Concepts](scheduledqueries-concepts.md)
+ [Schedule expressions](scheduledqueries-schedule.md)
+ [Data model mappings](scheduledqueries-mappings.md)
+ [Notification messages](scheduledqueries-notification.md)
+ [Error reports](scheduledqueries-errorreport.md)
+ [Patterns and examples](scheduledqueries-examplesandpatterns.md)

## Scheduled query benefits
<a name="scheduledqueries-benifits"></a>

The following are the benefits of scheduled queries:
+ **Operational ease** – Scheduled queries are serverless and fully managed. 
+ **Performance and cost** – Because scheduled queries precompute the aggregates, rollups, or other real-time analytics operations for your data and store the results in a table, queries that access tables populated by scheduled queries contain less data than the source tables. Therefore, queries that are run on these tables are faster and cheaper. Tables populated by scheduled computations contain less data than their source tables, and therefore help reduce the storage cost. You can also retain this data for a longer duration in the memory store at a fraction of the cost of retaining the source data in the memory store.
+ **Interoperability** – Tables populated by scheduled queries offer all of the existing functionality of Timestream for LiveAnalytics tables and can be used with all of the services and tools that work with Timestream for LiveAnalytics. See [Working with Other Services](https://docs.aws.amazon.com/timestream/latest/developerguide/OtherServices.html) for details.

## Scheduled query use cases
<a name="scheduledqueries-usescases"></a>

You can use scheduled queries for business reports that summarize the end-user activity from your applications, so you can train machine learning models for personalization. You can also use scheduled queries for alarms that detect anomalies, network intrusions, or fraudulent activity, so you can take immediate remedial actions. 

Additionally, you can use scheduled queries for more effective data governance. You can do this by granting source table access exclusively to the scheduled queries, and providing your developers access to only the tables populated by scheduled queries. This minimizes the impact of unintentional, long-running queries.

## Example: Using real-time analytics to detect fraudulent payments and make better business decisions
<a name="scheduledqueries-example"></a>

Consider a payment system that processes transactions sent from multiple point-of-sale terminals distributed across major metropolitan cities in the United States. You want to use Amazon Timestream for LiveAnalytics to store and analyze the transaction data, so you can detect fraudulent transactions and run real-time analytics queries. These queries can help you answer business questions such as identifying the busiest and least used point-of-sale terminals per hour, the busiest hour of the day for each city, and the city with most transactions per hour. 

The system process \$1100K transactions per minute. Each transaction stored in Amazon Timestream for LiveAnalytics is 100 bytes. You've configured 10 queries that run every minute to detect various kinds of fraudulent payments. You've also created 25 queries that aggregate and slice/dice your data along various dimensions to help answer your business questions. Each of these queries processes the last hour's data. 

You've created a dashboard to display the data generated by these queries. The dashboard contains 25 widgets, it is refreshed every hour, and it is typically accessed by 10 users at any given time. Finally, your memory store is configured with a 2-hour data retention period and the magnetic store is configured to have a 6-month data retention period. 

In this case, you can use real-time analytics queries that recompute the data every time the dashboard is accessed and refreshed, or use derived tables for the dashboard. The query cost for dashboards based on real-time analytics queries will be \$1120.70 per month. In contrast, the cost of dashboarding queries powered by derived tables will be \$112.27 per month (see [Amazon Timestream for LiveAnalytics pricing](https://aws.amazon.com/timestream/pricing/)). In this case, using derived tables reduces the query cost by \$110 times.

# Scheduled query concepts
<a name="scheduledqueries-concepts"></a>

**Query string** - This is the query whose result you are pre-computing and storing in another Timestream for LiveAnalytics table. You can define a scheduled query using the full SQL surface area of Timestream for LiveAnalytics, which provides you the flexibility of writing queries with common table expressions, nested queries, window functions, or any kind of aggregate and scalar functions that are supported by [Timestream for LiveAnalytics query language](https://docs.aws.amazon.com/timestream/latest/developerguide/reference.html).

**Schedule expression** - Allows you to specify when your scheduled query instances are run. You can specify the expressions using a cron expression (such as run at 8 AM UTC every day) or rate expression (such as run every 10 minutes). 

**Target configuration** - Allows you to specify how you map the result of a scheduled query into the destination table where the results of this scheduled query will be stored. 

**Notification configuration** -Timestream for LiveAnalytics automatically runs instances of a scheduled query based on your schedule expression. You receive a notification for every such query run on an SNS topic that you configure when you create a scheduled query. This notification specifies whether the instance was successfully run or encountered any errors. In addition, it provides information such as the bytes metered, data written to the target table, next invocation time, and so on.

The following is an example of this kind of notification message.

```
{
    "type":"AUTO_TRIGGER_SUCCESS",
    "arn":"arn:aws:timestream:us-east-1:123456789012:scheduled-query/ PT1mPerMinutePerRegionMeasureCount-9376096f7309",
    "nextInvocationEpochSecond":1637302500,
    "scheduledQueryRunSummary":
    {
        "invocationEpochSecond":1637302440,
        "triggerTimeMillis":1637302445697,
        "runStatus":"AUTO_TRIGGER_SUCCESS",
        "executionStats":
        {
            "executionTimeInMillis":21669,
            "dataWrites":36864,
            "bytesMetered":13547036820,
            "recordsIngested":1200,
            "queryResultRows":1200
        }
    }
}
```

In this notification message, `bytesMetered` is the bytes that the query scanned on the source table, and dataWrites is the bytes written to the target table. 

**Note**  
 If you are consuming these notifications programmatically, be aware that new fields could be added to the notification message in the future.

**Error report location** - Scheduled queries asynchronously run and store data in the target table. If an instance encounters any errors (for example, invalid data which could not be stored), the records that encountered errors are written to an error report in the error report location you specify at creation of a scheduled query. You specify the S3 bucket and prefix for the location. Timestream for LiveAnalytics appends the scheduled query name and invocation time to this prefix to help you identify the errors associated with a specific instance of a scheduled query.

**Tagging** - You can optionally specify tags that you can associate with a scheduled query. For more details, see [Tagging Timestream for LiveAnalytics Resources](https://docs.aws.amazon.com/timestream/latest/developerguide/tagging-keyspaces.html).

**Example**

In the following example, you compute a simple aggregate using a scheduled query:

```
SELECT region, bin(time, 1m) as minute, 
    SUM(CASE WHEN measure_name = 'metrics' THEN 20 ELSE 5 END) as numDataPoints 
FROM raw_data.devops 
WHERE time BETWEEN @scheduled_runtime - 10m AND @scheduled_runtime + 1m 
GROUP BY bin(time, 1m), region
```

`@scheduled_runtime parameter` - In this example, you will notice the query accepting a special named parameter `@scheduled_runtime`. This is a special parameter (of type Timestamp) that the service sets when invoking a specific instance of a scheduled query so that you can deterministically control the time range for which a specific instance of a scheduled query analyzes the data in the source table. You can use `@scheduled_runtime` in your query in any location where a Timestamp type is expected.

Consider an example where you set a schedule expression: cron(0/5 \$1 \$1 \$1 ? \$1) where the scheduled query will run at minute 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55 of every hour. For the instance that is triggered at 2021-12-01 00:05:00, the @scheduled\$1runtime parameter is initialized to this value, such that the instance at this time operates on data in the range 2021-11-30 23:55:00 to 2021-12-01 00:06:00.

**Instances with overlapping time ranges** - As you will see in this example, two subsequent instances of a scheduled query can overlap in their time ranges. This is something you can control based on your requirements, the time predicates you specify, and the schedule expression. In this case, this overlap allows these computations to update the aggregates based on any data whose arrival was slightly delayed, up to 10 minutes in this example. The query run triggered at 2021-12-01 00:00:00 will cover the time range 2021-11-30 23:50:00 to 2021-12-30 00:01:00 and the query run triggered at 2021-12-01 00:05:00 will cover the range 2021-11-30 23:55:00 to 2021-12-01 00:06:00. 

To ensure correctness and to make sure that the aggregates stored in the target table match the aggregates computed from the source table, Timestream for LiveAnalytics ensures that the computation at 2021-12-01 00:05:00 will be performed only after the computation at 2021-12-01 00:00:00 has completed. The results of the latter computations can update any previously materialized aggregate if a newer value is generated. Internally, Timestream for LiveAnalytics uses record versions where records generated by latter instances of a scheduled query will be assigned a higher version number. Therefore, the aggregates computed by the invocation at 2021-12-01 00:05:00 can update the aggregates computed by the invocation at 2021-12-01 00:00:00, assuming newer data is available on the source table.

**Automatic triggers vs. manual triggers** - After a scheduled query is created, Timestream for LiveAnalytics will automatically run the instances based on the specified schedule. Such automated triggers are managed entirely by the service. 

However, there might be scenarios where you might want to manually initiate some instances of a scheduled query. Examples include if a specific instance failed in a query run, if there was late-arriving data or updates in the source table after the automated schedule run, or if you want to update the target table for time ranges that are not covered by automated query runs (for example, for time ranges before creation of a scheduled query). 

You can use the ExecuteScheduledQuery API to manually initiate a specific instance of a scheduled query by passing the InvocationTime parameter, which is a value used for the @scheduled\$1runtime parameter. The following are a few important considerations when using the ExecuteScheduledQuery API:
+ If you are triggering multiple of these invocations, you need to make sure that these invocations do not generate results in overlapping time ranges. If you cannot ensure non-overlapping time ranges, then make sure that these query runs are initiated sequentially one after the other. If you concurrently initiate multiple query runs that overlap in their time ranges, then you can see trigger failures where you might see version conflicts in the error reports for these query runs.
+ You can initiate the invocations with any timestamp value for @scheduled\$1runtime. So it is your responsibility to appropriately set the values so the appropriate time ranges are updated in the target table corresponding to the ranges where data was updated in the source table.
+ The ExecuteScheduledQuery API operates asynchronously. Upon a successful call, the service sends a 200 response and proceeds to execute the query. However, if there are multiple scheduled query executions concurrently running, anticipate potential delays in executing manually triggered scheduled executions. 

# Schedule expressions for scheduled queries
<a name="scheduledqueries-schedule"></a>

You can create scheduled queries on an automated schedule by using Amazon Timestream for LiveAnalytics scheduled queries that use cron or rate expressions. All scheduled queries use the UTC time zone, and the minimum possible precision for schedules is 1 minute. 

Two ways to specify the schedule expressions are *cron* and *rate*. Cron expressions offer more fine grained schedule control, while rate expressions are simpler to express but lack the fine-grained control. 

For example, with a cron expression, you can define a scheduled query that gets triggered at a specified time on a certain day of each week or month, or a specified minute every hour only on Monday - Friday, and so on. In contrast, rate expressions initiate a scheduled query at a regular rate, such as once every minute, hour, or day, starting from the exact time when the scheduled query is created.

**Cron expression**
+ *Syntax*

  ```
  cron(fields)
  ```

  Cron expressions have six required fields, which are separated by white space.    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/scheduledqueries-schedule.html)

**Wildcard characters**
  + The \$1,\$1 (comma) wildcard includes additional values. In the Month field, JAN,FEB,MAR would include January, February, and March.
  + The \$1-\$1 (dash) wildcard specifies ranges. In the Day field, 1-15 would include days 1 through 15 of the specified month. 
  + The \$1\$1\$1 (asterisk) wildcard includes all values in the field. In the Hours field, \$1\$1\$1 would include every hour. You cannot use \$1\$1\$1 in both the Day-of-month and Day-of-week fields. If you use it in one, you must use \$1?\$1 in the other.
  + The \$1/\$1 (forward slash) wildcard specifies increments. In the Minutes field, you could enter 1/10 to specify every 10th minute, starting from the first minute of the hour (for example, the 11th, 21st, and 31st minute, and so on). 
  + The \$1?\$1 (question mark) wildcard specifies one or another. In the Day-of-month field you could enter \$17\$1 and if you didn't care what day of the week the 7th was, you could enter \$1?\$1 in the Day-of-week field.
  + The \$1L\$1 wildcard in the Day-of-month or Day-of-week fields specifies the last day of the month or week. 
  + The W wildcard in the Day-of-month field specifies a weekday. In the Day-of-month field, 3W specifies the weekday closest to the third day of the month. 
  + The \$1\$1\$1 wildcard in the Day-of-week field specifies a certain instance of the specified day of the week within a month. For example, 3\$12 would be the second Tuesday of the month: the 3 refers to Tuesday because it is the third day of each week, and the 2 refers to the second day of that type within the month. 
**Note**  
If you use a '\$1' character, you can define only one expression in the day-of-week field. For example, "3\$11,6\$13" is not valid because it is interpreted as two expressions. 

**Limitations**
  + You can't specify the Day-of-month and Day-of-week fields in the same cron expression. If you specify a value (or a \$1) in one of the fields, you must use a \$1?\$1 (question mark) in the other.
  + Cron expressions that lead to rates faster than 1 minute are not supported.

  **Examples**    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/scheduledqueries-schedule.html)

**Rate expressions**
+ A rate expression starts when you create the scheduled event rule, and then runs on its defined schedule. Rate expressions have two required fields. Fields are separated by white space. 

  *Syntax*

  ```
  rate(value unit)
  ```
  + `value`: A positive number.
  + `unit`: The unit of time. Different units are required for values of 1 (for example, minute) and values over 1 (for example, minutes). Valid values: minute \$1 minutes \$1 hour \$1 hours \$1 day \$1 days

# Data model mappings for scheduled queries
<a name="scheduledqueries-mappings"></a>

Timestream for LiveAnalytics supports flexible modeling of data in its tables and this same flexibility applies to results of scheduled queries that are materialized into another Timestream for LiveAnalytics table. With scheduled queries, you can query any table, whether it has data in multi-measure records or single-measure records and write the query results using either multi-measure or single-measure records. 

You use the TargetConfiguration in the specification of a scheduled query to map the query results to the appropriate columns in the destination derived table. The following sections describe the different ways of specifying this TargetConfiguration to achieve different data models in the derived table. Specifically, you will see:
+ How to write to multi-measure records when the query result does not have a measure name and you specify the target measure name in the TargetConfiguration.
+ How you use measure name in the query result to write multi-measure records. 
+ How you can define a model to write multiple records with different multi-measure attributes.
+ How you can define a model to write to single-measure records in the derived table.
+ How you can query single-measure records and/or multi-measure records in a scheduled query and have the results materialized to either a single-measure record or a multi-measure record, which allows you to choose the flexibility of data models.

## Example: Target measure name for multi-measure records
<a name="scheduledqueries-mappings-targetmeasurename"></a>

In this example, you will see that the query is reading data from a table with multi-measure data and is writing the results into another table using multi-measure records. The scheduled query result does not have a natural measure name column. Here, you specify the measure name in the derived table using the TargetMultiMeasureName property in the TargetConfiguration.TimestreamConfiguration. 

```
{
    "Name" : "CustomMultiMeasureName",
    "QueryString" : "SELECT region, bin(time, 1h) as hour, AVG(memory_cached) as avg_mem_cached_1h, MIN(memory_free) as min_mem_free_1h, MAX(memory_used) as max_mem_used_1h, SUM(disk_io_writes) as sum_1h, AVG(disk_used) as avg_disk_used_1h, AVG(disk_free) as avg_disk_free_1h, MAX(cpu_user) as max_cpu_user_1h, MIN(cpu_idle) as min_cpu_idle_1h, MAX(cpu_system) as max_cpu_system_1h FROM raw_data.devops_multi WHERE time BETWEEN bin(@scheduled_runtime, 1h) - 14h AND bin(@scheduled_runtime, 1h) - 2h AND measure_name = 'metrics' GROUP BY region, bin(time, 1h)",
    "ScheduleConfiguration" : {
        "ScheduleExpression" : "cron(0 0/1 * * ? *)"
    },
    "NotificationConfiguration" : {
        "SnsConfiguration" : {
            "TopicArn" : "******"
        }
    },
    "ScheduledQueryExecutionRoleArn": "******",
    "TargetConfiguration": {
        "TimestreamConfiguration": {
            "DatabaseName" : "derived",
            "TableName" : "dashboard_metrics_1h_agg_1",
            "TimeColumn" : "hour",
            "DimensionMappings" : [
                {
                    "Name": "region",
                    "DimensionValueType" : "VARCHAR"
                }
            ],
            "MultiMeasureMappings" : {
                "TargetMultiMeasureName": "dashboard-metrics",
                "MultiMeasureAttributeMappings" : [
                    {
                        "SourceColumn" : "avg_mem_cached_1h",
                        "MeasureValueType" : "DOUBLE",
                        "TargetMultiMeasureAttributeName" : "avgMemCached"
                    },
                    {
                        "SourceColumn" : "min_mem_free_1h",
                        "MeasureValueType" : "DOUBLE"
                    },
                    {
                        "SourceColumn" : "max_mem_used_1h",
                        "MeasureValueType" : "DOUBLE"
                    },
                    {
                        "SourceColumn" : "sum_1h",
                        "MeasureValueType" : "DOUBLE",
                        "TargetMultiMeasureAttributeName" : "totalDiskWrites"
                    },
                    {
                        "SourceColumn" : "avg_disk_used_1h",
                        "MeasureValueType" : "DOUBLE"
                    },
                    {
                        "SourceColumn" : "avg_disk_free_1h",
                        "MeasureValueType" : "DOUBLE"
                    },
                    {
                        "SourceColumn" : "max_cpu_user_1h",
                        "MeasureValueType" : "DOUBLE",
                        "TargetMultiMeasureAttributeName" : "CpuUserP100"
                    },
                    {
                        "SourceColumn" : "min_cpu_idle_1h",
                        "MeasureValueType" : "DOUBLE"
                    },
                    {
                        "SourceColumn" : "max_cpu_system_1h",
                        "MeasureValueType" : "DOUBLE",
                        "TargetMultiMeasureAttributeName" : "CpuSystemP100"
                    }  
                ]
            }
        }
    },
    "ErrorReportConfiguration": {
        "S3Configuration" : {
            "BucketName" : "******",
            "ObjectKeyPrefix": "errors",
            "EncryptionOption": "SSE_S3"
        }
    }
}
```

The mapping in this example creates one multi-measure record with measure name dashboard-metrics and attribute names avgMemCached, min\$1mem\$1free\$11h, max\$1mem\$1used\$11h, totalDiskWrites, avg\$1disk\$1used\$11h, avg\$1disk\$1free\$11h, CpuUserP100, min\$1cpu\$1idle\$11h, CpuSystemP100. Notice the optional use of TargetMultiMeasureAttributeName to rename the query output columns to a different attribute name used for result materialization.

The following is the schema for the destination table once this scheduled query is materialized. As you can see from the Timestream for LiveAnalytics attribute type in the following result, the results are materialized into a multi-measure record with a single-measure name `dashboard-metrics`, as shown in the measure schema.


| Column | Type | Timestream for LiveAnalytics attribute type | 
| --- | --- | --- | 
|  region  |  varchar  |  DIMENSION  | 
|  measure\$1name  |  varchar  |  MEASURE\$1NAME  | 
|  time  |  timestamp  |  TIMESTAMP  | 
|  CpuSystemP100  |  double  |  MULTI  | 
|  avgMemCached  |  double  |  MULTI  | 
|  min\$1cpu\$1idle\$11h  |  double  |  MULTI  | 
|  avg\$1disk\$1free\$11h  |  double  |  MULTI  | 
|  avg\$1disk\$1used\$11h  |  double  |  MULTI  | 
|  totalDiskWrites  |  double  |  MULTI  | 
|  max\$1mem\$1used\$11h  |  double  |  MULTI  | 
|  min\$1mem\$1free\$11h  |  double  |  MULTI  | 
|  CpuUserP100  |  double  |  MULTI  | 

The following are the corresponding measures obtained with a SHOW MEASURES query.


| measure\$1name | data\$1type | Dimensions | 
| --- | --- | --- | 
|  dashboard-metrics  |  multi  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 

## Example: Using measure name from scheduled query in multi-measure records
<a name="scheduledqueries-mappings-usingmeasurename"></a>

In this example, you will see a query reading from a table with single-measure records and materializing the results into multi-measure records. In this case, the scheduled query result has a column whose values can be used as measure names in the target table where the results of the scheduled query is materialized. Then you can specify the measure name for the multi-measure record in the derived table using the MeasureNameColumn property in TargetConfiguration.TimestreamConfiguration. 

```
{
    "Name" : "UsingMeasureNameFromQueryResult",
    "QueryString" : "SELECT region, bin(time, 1h) as hour, measure_name, AVG(CASE WHEN measure_name IN ('memory_cached', 'disk_used', 'disk_free') THEN measure_value::double ELSE NULL END) as avg_1h, MIN(CASE WHEN measure_name IN ('memory_free', 'cpu_idle') THEN measure_value::double ELSE NULL END) as min_1h, SUM(CASE WHEN measure_name IN ('disk_io_writes') THEN measure_value::double ELSE NULL END) as sum_1h, MAX(CASE WHEN measure_name IN ('memory_used', 'cpu_user', 'cpu_system') THEN measure_value::double ELSE NULL END) as max_1h FROM raw_data.devops WHERE time BETWEEN bin(@scheduled_runtime, 1h) - 14h AND bin(@scheduled_runtime, 1h) - 2h AND measure_name IN ('memory_free', 'memory_used', 'memory_cached', 'disk_io_writes', 'disk_used', 'disk_free', 'cpu_user', 'cpu_system', 'cpu_idle') GROUP BY region, measure_name, bin(time, 1h)",
    "ScheduleConfiguration" : {
        "ScheduleExpression" : "cron(0 0/1 * * ? *)"
    },
    "NotificationConfiguration" : {
        "SnsConfiguration" : {
            "TopicArn" : "******"
        }
    },
    "ScheduledQueryExecutionRoleArn": "******",
    "TargetConfiguration": {
        "TimestreamConfiguration": {
            "DatabaseName" : "derived",
            "TableName" : "dashboard_metrics_1h_agg_2",
            "TimeColumn" : "hour",
            "DimensionMappings" : [
                {
                    "Name": "region",
                    "DimensionValueType" : "VARCHAR"
                }
            ],
            "MeasureNameColumn" : "measure_name",
            "MultiMeasureMappings" : {
                "MultiMeasureAttributeMappings" : [
                    {
                        "SourceColumn" : "avg_1h",
                        "MeasureValueType" : "DOUBLE"
                    },
                    {
                        "SourceColumn" : "min_1h",
                        "MeasureValueType" : "DOUBLE",
                        "TargetMultiMeasureAttributeName": "p0_1h"
                    },
                    {
                        "SourceColumn" : "sum_1h",
                        "MeasureValueType" : "DOUBLE"
                    },
                    {
                        "SourceColumn" : "max_1h",
                        "MeasureValueType" : "DOUBLE",
                        "TargetMultiMeasureAttributeName": "p100_1h"
                    } 
                ]
            }
        }
    },
    "ErrorReportConfiguration": {
        "S3Configuration" : {
            "BucketName" : "******",
            "ObjectKeyPrefix": "errors",
            "EncryptionOption": "SSE_S3"
        }
    }
}
```

The mapping in this example will create multi-measure records with attributes avg\$11h, p0\$11h, sum\$11h, p100\$11h and will use the values of the measure\$1name column in the query result as the measure name for the multi-measure records in the destination table. Additionally note that the previous examples optionally use the TargetMultiMeasureAttributeName with a subset of the mappings to rename the attributes. For instance, min\$11h was renamed to p0\$11h and max\$11h is renamed to p100\$11h.

The following is the schema for the destination table once this scheduled query is materialized. As you can see from the Timestream for LiveAnalytics attribute type in the following result, the results are materialized into a multi-measure record. If you look at the measure schema, there were nine different measure names that were ingested which correspond to the values seen in the query results.


| Column | Type | Timestream for LiveAnalytics attribute type | 
| --- | --- | --- | 
|  region  |  varchar  |  DIMENSION  | 
|  measure\$1name  |  varchar  |  MEASURE\$1NAME  | 
|  time  |  timestamp  |  TIMESTAMP  | 
|  sum\$11h  |  double  |  MULTI  | 
|  p100\$11h  |  double  |  MULTI  | 
|  p0\$11h  |  double  |  MULTI  | 
|  avg\$11h  |  double  |  MULTI  | 

The following are corresponding measures obtained with a SHOW MEASURES query.


| measure\$1name | data\$1type | Dimensions | 
| --- | --- | --- | 
|  cpu\$1idle  |  multi  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  cpu\$1system  |  multi  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  cpu\$1user  |  multi  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  disk\$1free  |  multi  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  disk\$1io\$1writes  |  multi  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  disk\$1used  |  multi  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  memory\$1cached  |  multi  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  memory\$1free  |  multi  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  memory\$1free  |  multi  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 

## Example: Mapping results to different multi-measure records with different attributes
<a name="scheduledqueries-mappings-mappintresultstodiffrentmultimeasure"></a>

The following example shows how you can map different columns in your query result into different multi-measure records with different measure names. If you see the following scheduled query definition, the result of the query has the following columns: region, hour, avg\$1mem\$1cached\$11h, min\$1mem\$1free\$11h, max\$1mem\$1used\$11h, total\$1disk\$1io\$1writes\$11h, avg\$1disk\$1used\$11h, avg\$1disk\$1free\$11h, max\$1cpu\$1user\$11h, max\$1cpu\$1system\$11h, min\$1cpu\$1system\$11h. `region` is mapped to dimension, and `hour` is mapped to the time column. 

The MixedMeasureMappings property in TargetConfiguration.TimestreamConfiguration specifies how to map the measures to multi-measure records in the derived table. 

In this specific example, avg\$1mem\$1cached\$11h, min\$1mem\$1free\$11h, max\$1mem\$1used\$11h are used in one multi-measure record with measure name of mem\$1aggregates, total\$1disk\$1io\$1writes\$11h, avg\$1disk\$1used\$11h, avg\$1disk\$1free\$11h are used in another multi-measure record with measure name of disk\$1aggregates, and finally max\$1cpu\$1user\$11h, max\$1cpu\$1system\$11h, min\$1cpu\$1system\$11h are used in another multi-measure record with measure name cpu\$1aggregates. 

In these mappings, you can also optionally use TargetMultiMeasureAttributeName to rename the query result column to have a different attribute name in the destination table. For instance, the result column avg\$1mem\$1cached\$11h gets renamed to avgMemCached, total\$1disk\$1io\$1writes\$11h gets renamed to totalIOWrites, etc. 

When you're defining the mappings for multi-measure records, Timestream for LiveAnalytics inspects every row in the query results and automatically ignores the column values that have NULL values. As a result, in the case of mappings with multiple measures names, if all the column values for that group in the mapping are NULL for a given row, then no value for that measure name is ingested for that row. 

For example, in the following mapping, avg\$1mem\$1cached\$11h, min\$1mem\$1free\$11h, and max\$1mem\$1used\$11h are mapped to measure name mem\$1aggregates. If for a given row of the query result, all these of the column values are NULL, Timestream for LiveAnalytics won't ingest the measure mem\$1aggregates for that row. If all nine columns for a given row are NULL, then you will see an user error reported in your error report. 

```
{
    "Name" : "AggsInDifferentMultiMeasureRecords",
    "QueryString" : "SELECT region, bin(time, 1h) as hour, AVG(CASE WHEN measure_name = 'memory_cached' THEN measure_value::double ELSE NULL END) as avg_mem_cached_1h, MIN(CASE WHEN measure_name = 'memory_free' THEN measure_value::double ELSE NULL END) as min_mem_free_1h, MAX(CASE WHEN measure_name = 'memory_used' THEN measure_value::double ELSE NULL END) as max_mem_used_1h, SUM(CASE WHEN measure_name = 'disk_io_writes' THEN measure_value::double ELSE NULL END) as total_disk_io_writes_1h, AVG(CASE WHEN measure_name = 'disk_used' THEN measure_value::double ELSE NULL END) as avg_disk_used_1h, AVG(CASE WHEN measure_name = 'disk_free' THEN measure_value::double ELSE NULL END) as avg_disk_free_1h, MAX(CASE WHEN measure_name = 'cpu_user' THEN measure_value::double ELSE NULL END) as max_cpu_user_1h, MAX(CASE WHEN measure_name = 'cpu_system' THEN measure_value::double ELSE NULL END) as max_cpu_system_1h, MIN(CASE WHEN measure_name = 'cpu_idle' THEN measure_value::double ELSE NULL END) as min_cpu_system_1h FROM raw_data.devops WHERE time BETWEEN bin(@scheduled_runtime, 1h) - 14h AND bin(@scheduled_runtime, 1h) - 2h AND measure_name IN ('memory_cached', 'memory_free', 'memory_used', 'disk_io_writes', 'disk_used', 'disk_free', 'cpu_user', 'cpu_system', 'cpu_idle') GROUP BY region, bin(time, 1h)",
    "ScheduleConfiguration" : {
        "ScheduleExpression" : "cron(0 0/1 * * ? *)"
    },
    "NotificationConfiguration" : {
        "SnsConfiguration" : {
            "TopicArn" : "******"
        }
    },
    "ScheduledQueryExecutionRoleArn": "******",
    "TargetConfiguration": {
        "TimestreamConfiguration": {
            "DatabaseName" : "derived",
            "TableName" : "dashboard_metrics_1h_agg_3",
            "TimeColumn" : "hour",
            "DimensionMappings" : [
                {
                    "Name": "region",
                    "DimensionValueType" : "VARCHAR"
                }
            ],
            "MixedMeasureMappings" : [
                {
                    "MeasureValueType" : "MULTI",
                    "TargetMeasureName" : "mem_aggregates",
                    "MultiMeasureAttributeMappings" : [
                        {
                            "SourceColumn" : "avg_mem_cached_1h",
                            "MeasureValueType" : "DOUBLE",
                            "TargetMultiMeasureAttributeName": "avgMemCached"
                        },
                        {
                            "SourceColumn" : "min_mem_free_1h",
                            "MeasureValueType" : "DOUBLE"
                        },
                        {
                            "SourceColumn" : "max_mem_used_1h",
                            "MeasureValueType" : "DOUBLE",
                            "TargetMultiMeasureAttributeName": "maxMemUsed"
                        }
                    ]
                },
                {
                    "MeasureValueType" : "MULTI",
                    "TargetMeasureName" : "disk_aggregates",
                    "MultiMeasureAttributeMappings" : [
                        {
                            "SourceColumn" : "total_disk_io_writes_1h",
                            "MeasureValueType" : "DOUBLE",
                            "TargetMultiMeasureAttributeName": "totalIOWrites"
                        },
                        {
                            "SourceColumn" : "avg_disk_used_1h",
                            "MeasureValueType" : "DOUBLE"
                        },
                        {
                            "SourceColumn" : "avg_disk_free_1h",
                            "MeasureValueType" : "DOUBLE"
                        }
                    ]
                },
                {
                    "MeasureValueType" : "MULTI",
                    "TargetMeasureName" : "cpu_aggregates",
                    "MultiMeasureAttributeMappings" : [
                        {
                            "SourceColumn" : "max_cpu_user_1h",
                            "MeasureValueType" : "DOUBLE"
                        },
                        {
                            "SourceColumn" : "max_cpu_system_1h",
                            "MeasureValueType" : "DOUBLE"
                        },
                        {
                            "SourceColumn" : "min_cpu_idle_1h",
                            "MeasureValueType" : "DOUBLE",
                            "TargetMultiMeasureAttributeName": "minCpuIdle"
                        }
                    ]
                }
            ]
        }
    },
    "ErrorReportConfiguration": {
        "S3Configuration" : {
            "BucketName" : "******",
            "ObjectKeyPrefix": "errors",
            "EncryptionOption": "SSE_S3"
        }
    }
}
```

The following is the schema for the destination table once this scheduled query is materialized.


| Column | Type | Timestream for LiveAnalytics attribute type | 
| --- | --- | --- | 
|  region  |  varchar  |  DIMENSION  | 
|  measure\$1name  |  varchar  |  MEASURE\$1NAME  | 
|  time  |  timestamp  |  TIMESTAMP  | 
|  minCpuIdle  |  double  |  MULTI  | 
|  max\$1cpu\$1system\$11h  |  double  |  MULTI  | 
|  max\$1cpu\$1user\$11h  |  double  |  MULTI  | 
|  avgMemCached  |  double  |  MULTI  | 
|  maxMemUsed  |  double  |  MULTI  | 
|  min\$1mem\$1free\$11h  |  double  |  MULTI  | 
|  avg\$1disk\$1free\$11h  |  double  |  MULTI  | 
|  avg\$1disk\$1used\$11h  |  double  |  MULTI  | 
|  totalIOWrites  |  double  |  MULTI  | 

The following are the corresponding measures obtained with a SHOW MEASURES query.


| measure\$1name | data\$1type | Dimensions | 
| --- | --- | --- | 
|  cpu\$1aggregates  |  multi  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  disk\$1aggregates  |  multi  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  mem\$1aggregates  |  multi  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 

## Example: Mapping results to single-measure records with measure name from query results
<a name="scheduledqueries-mappings-mappintresultstosinglemeasurerecords"></a>

The following is an example of a scheduled query whose results are materialized into single-measure records. In this example, the query result has the measure\$1name column whose values will be used as measure names in the target table. You use the MixedMeasureMappings attribute in the TargetConfiguration.TimestreamConfiguration to specify the mapping of the query result column to the scalar measure in the target table. 

In the following example definition, the query result is expected to nine distinct measure\$1name values. You list out all these measure names in the mapping and specify which column to use for the single-measure value for that measure name. For example, in this mapping, if measure name of memory\$1cached is seen for a given result row, then the value in the avg\$11h column is used as the value for the measure when the data is written to the target table. You can optionally use TargetMeasureName to provide a new measure name for this value. 

```
{
    "Name" : "UsingMeasureNameColumnForSingleMeasureMapping",
    "QueryString" : "SELECT region, bin(time, 1h) as hour, measure_name, AVG(CASE WHEN measure_name IN ('memory_cached', 'disk_used', 'disk_free') THEN measure_value::double ELSE NULL END) as avg_1h, MIN(CASE WHEN measure_name IN ('memory_free', 'cpu_idle') THEN measure_value::double ELSE NULL END) as min_1h, SUM(CASE WHEN measure_name IN ('disk_io_writes') THEN measure_value::double ELSE NULL END) as sum_1h, MAX(CASE WHEN measure_name IN ('memory_used', 'cpu_user', 'cpu_system') THEN measure_value::double ELSE NULL END) as max_1h FROM raw_data.devops WHERE time BETWEEN bin(@scheduled_runtime, 1h) - 14h AND bin(@scheduled_runtime, 1h) - 2h AND measure_name IN ('memory_free', 'memory_used', 'memory_cached', 'disk_io_writes', 'disk_used', 'disk_free', 'cpu_user', 'cpu_system', 'cpu_idle') GROUP BY region, bin(time, 1h), measure_name",
    "ScheduleConfiguration" : {
        "ScheduleExpression" : "cron(0 0/1 * * ? *)"
    },
    "NotificationConfiguration" : {
        "SnsConfiguration" : {
            "TopicArn" : "******"
        }
    },
    "ScheduledQueryExecutionRoleArn": "******",
    "TargetConfiguration": {
        "TimestreamConfiguration": {
            "DatabaseName" : "derived",
            "TableName" : "dashboard_metrics_1h_agg_4",
            "TimeColumn" : "hour",
            "DimensionMappings" : [
                {
                    "Name": "region",
                    "DimensionValueType" : "VARCHAR"
                }
            ],
            "MeasureNameColumn" : "measure_name",
            "MixedMeasureMappings" : [
                {
                    "MeasureName" : "memory_cached",
                    "MeasureValueType" : "DOUBLE",
                    "SourceColumn" : "avg_1h",
                    "TargetMeasureName" : "AvgMemCached"
                },
                {
                    "MeasureName" : "disk_used",
                    "MeasureValueType" : "DOUBLE",
                    "SourceColumn" : "avg_1h"
                },
                {
                    "MeasureName" : "disk_free",
                    "MeasureValueType" : "DOUBLE",
                    "SourceColumn" : "avg_1h"
                },
                {
                    "MeasureName" : "memory_free",
                    "MeasureValueType" : "DOUBLE",
                    "SourceColumn" : "min_1h",
                    "TargetMeasureName" : "MinMemFree"
                },
                {
                    "MeasureName" : "cpu_idle",
                    "MeasureValueType" : "DOUBLE",
                    "SourceColumn" : "min_1h"
                },
                {
                    "MeasureName" : "disk_io_writes",
                    "MeasureValueType" : "DOUBLE",
                    "SourceColumn" : "sum_1h",
                    "TargetMeasureName" : "total-disk-io-writes"
                },
                {
                    "MeasureName" : "memory_used",
                    "MeasureValueType" : "DOUBLE",
                    "SourceColumn" : "max_1h",
                    "TargetMeasureName" : "maxMemUsed"
                },
                {
                    "MeasureName" : "cpu_user",
                    "MeasureValueType" : "DOUBLE",
                    "SourceColumn" : "max_1h"
                },
                {
                    "MeasureName" : "cpu_system",
                    "MeasureValueType" : "DOUBLE",
                    "SourceColumn" : "max_1h"
                }
            ]
        }
    },
    "ErrorReportConfiguration": {
        "S3Configuration" : {
            "BucketName" : "******",
            "ObjectKeyPrefix": "errors",
            "EncryptionOption": "SSE_S3"
        }
    }
}
```

The following is the schema for the destination table once this scheduled query is materialized. As you can see from the schema, the table is using single-measure records. If you list the measure schema for the table, you will see the nine measures written to based on the mapping provided in the specification.


| Column | Type | Timestream for LiveAnalytics attribute type | 
| --- | --- | --- | 
|  region  |  varchar  |  DIMENSION  | 
|  measure\$1name  |  varchar  |  MEASURE\$1NAME  | 
|  time  |  timestamp  |  TIMESTAMP  | 
|  measure\$1value::double  |  double  |  MEASURE\$1VALUE  | 

The following are the corresponding measures obtained with a SHOW MEASURES query.


| measure\$1name | data\$1type | Dimensions | 
| --- | --- | --- | 
|  AvgMemCached  |  double  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  MinMemFree  |  double  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  cpu\$1idle  |  double  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  cpu\$1system  |  double  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  cpu\$1user  |  double  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  disk\$1free  |  double  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  disk\$1used  |  double  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  maxMemUsed  |  double  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  total-disk-io-writes  |  double  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 

## Example: Mapping results to single-measure records with query result columns as measure names
<a name="scheduledqueries-mappings-mappintresultstsolumnsasmeasurename"></a>

In this example, you have a query whose results do not have a measure name column. Instead, you want the query result column name as the measure name when mapping the output to single-measure records. Earlier there was an example where a similar result was written to a multi-measure record. In this example, you will see how to map it to single-measure records if that fits your application scenario. 

Again, you specify this mapping using the MixedMeasureMappings property in TargetConfiguration.TimestreamConfiguration. In the following example, you see that the query result has nine columns. You use the result columns as measure names and the values as the single-measure values. 

For example, for a given row in the query result, the column name avg\$1mem\$1cached\$11h is used as the column name and value associated with column, and avg\$1mem\$1cached\$11h is used as the measure value for the single-measure record. You can also use TargetMeasureName to use a different measure name in the target table. For instance, for values in column sum\$11h, the mapping specifies to use total\$1disk\$1io\$1writes\$11h as the measure name in the target table. If any column's value is NULL, then the corresponding measure is ignored. 

```
{
    "Name" : "SingleMeasureMappingWithoutMeasureNameColumnInQueryResult",
    "QueryString" : "SELECT region, bin(time, 1h) as hour, AVG(CASE WHEN measure_name = 'memory_cached' THEN measure_value::double ELSE NULL END) as avg_mem_cached_1h, AVG(CASE WHEN measure_name = 'disk_used' THEN measure_value::double ELSE NULL END) as avg_disk_used_1h, AVG(CASE WHEN measure_name = 'disk_free' THEN measure_value::double ELSE NULL END) as avg_disk_free_1h, MIN(CASE WHEN measure_name = 'memory_free' THEN measure_value::double ELSE NULL END) as min_mem_free_1h, MIN(CASE WHEN measure_name = 'cpu_idle' THEN measure_value::double ELSE NULL END) as min_cpu_idle_1h, SUM(CASE WHEN measure_name = 'disk_io_writes' THEN measure_value::double ELSE NULL END) as sum_1h, MAX(CASE WHEN measure_name = 'memory_used' THEN measure_value::double ELSE NULL END) as max_mem_used_1h, MAX(CASE WHEN measure_name = 'cpu_user' THEN measure_value::double ELSE NULL END) as max_cpu_user_1h, MAX(CASE WHEN measure_name = 'cpu_system' THEN measure_value::double ELSE NULL END) as max_cpu_system_1h FROM raw_data.devops WHERE time BETWEEN bin(@scheduled_runtime, 1h) - 14h AND bin(@scheduled_runtime, 1h) - 2h AND measure_name IN ('memory_free', 'memory_used', 'memory_cached', 'disk_io_writes', 'disk_used', 'disk_free', 'cpu_user', 'cpu_system', 'cpu_idle') GROUP BY region, bin(time, 1h)",
    "ScheduleConfiguration" : {
        "ScheduleExpression" : "cron(0 0/1 * * ? *)"
    },
    "NotificationConfiguration" : {
        "SnsConfiguration" : {
            "TopicArn" : "******"
        }
    },
    "ScheduledQueryExecutionRoleArn": "******",
    "TargetConfiguration": {
        "TimestreamConfiguration": {
            "DatabaseName" : "derived",
            "TableName" : "dashboard_metrics_1h_agg_5",
            "TimeColumn" : "hour",
            "DimensionMappings" : [
                {
                    "Name": "region",
                    "DimensionValueType" : "VARCHAR"
                }
            ],
            "MixedMeasureMappings" : [
                {
                    "MeasureValueType" : "DOUBLE",
                    "SourceColumn" : "avg_mem_cached_1h"
                },
                {
                    "MeasureValueType" : "DOUBLE",
                    "SourceColumn" : "avg_disk_used_1h"
                },
                {
                    "MeasureValueType" : "DOUBLE",
                    "SourceColumn" : "avg_disk_free_1h"
                },
                {
                    "MeasureValueType" : "DOUBLE",
                    "SourceColumn" : "min_mem_free_1h"
                },
                {
                    "MeasureValueType" : "DOUBLE",
                    "SourceColumn" : "min_cpu_idle_1h"
                },
                {
                    "MeasureValueType" : "DOUBLE",
                    "SourceColumn" : "sum_1h",
                    "TargetMeasureName" : "total_disk_io_writes_1h"
                },
                {
                    "MeasureValueType" : "DOUBLE",
                    "SourceColumn" : "max_mem_used_1h"
                },
                {
                    "MeasureValueType" : "DOUBLE",
                    "SourceColumn" : "max_cpu_user_1h"
                },
                {
                    "MeasureValueType" : "DOUBLE",
                    "SourceColumn" : "max_cpu_system_1h"
                }
            ]
        }
    },
    "ErrorReportConfiguration": {
        "S3Configuration" : {
            "BucketName" : "******",
            "ObjectKeyPrefix": "errors",
            "EncryptionOption": "SSE_S3"
        }
    }
}
```

The following is the schema for the destination table once this scheduled query is materialized. As you can see that the target table is storing records with single-measure values of type double. Similarly, the measure schema for the table shows the nine measure names. Also notice that the measure name total\$1disk\$1io\$1writes\$11h is present since the mapping renamed sum\$11h to total\$1disk\$1io\$1writes\$11h.


| Column | Type | Timestream for LiveAnalytics attribute type | 
| --- | --- | --- | 
|  region  |  varchar  |  DIMENSION  | 
|  measure\$1name  |  varchar  |  MEASURE\$1NAME  | 
|  time  |  timestamp  |  TIMESTAMP  | 
|  measure\$1value::double  |  double  |  MEASURE\$1VALUE  | 

The following are the corresponding measures obtained with a SHOW MEASURES query.


| measure\$1name | data\$1type | Dimensions | 
| --- | --- | --- | 
|  avg\$1disk\$1free\$11h  |  double  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  avg\$1disk\$1used\$11h  |  double  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  avg\$1mem\$1cached\$11h  |  double  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  max\$1cpu\$1system\$11h  |  double  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  max\$1cpu\$1user\$11h  |  double  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  max\$1mem\$1used\$11h  |  double  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  min\$1cpu\$1idle\$11h  |  double  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  min\$1mem\$1free\$11h  |  double  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 
|  total-disk-io-writes  |  double  |  [\$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1]  | 

# Scheduled query notification messages
<a name="scheduledqueries-notification"></a>

This section describes the messages sent by Timestream for LiveAnalytics when creating, deleting, running, or updating the state of a scheduled query. 


| Notification message name | Structure | Description | 
| --- | --- | --- | 
|  CreatingNotificationMessage  |  <pre>CreatingNotificationMessage {<br />    String arn;<br />    NotificationType type;<br />}</pre>  |  This notification message is sent before sending the response for `CreateScheduledQuery`. The scheduled query is enabled after sending this notification.  *arn* - The ARN of the scheduled query that is being created. *type* - SCHEDULED\$1QUERY\$1CREATING  | 
|  UpdateNotificationMessage  |  <pre> UpdateNotificationMessage {<br />    String arn;<br />    NotificationType type;<br />    QueryState state;<br />}</pre>  |  This notification message is sent when a scheduled query is updated. Timestream for LiveAnalytics can disable the scheduled query, automatically, in case non-recoverable error is encountered, such as: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/scheduledqueries-notification.html) *arn* - The ARN of the scheduled query that is being updated. *type* - SCHEDULED\$1QUERY\$1UPDATE *state* - ENABLED or DISABLED  | 
|  DeleteNotificationMessage  |  <pre>DeletionNotificationMessage {<br />    String arn;<br />    NotificationType type;<br />}</pre>  |  This notification message is sent when a scheduled query has been deleted.  *arn* - The ARN of the scheduled query that is being created. *type* - SCHEDULED\$1QUERY\$1DELETED  | 
|  SuccessNotificationMessage  |  <pre>SuccessNotificationMessage {<br />    NotificationType type;<br />    String arn;<br />    Date nextInvocationEpochSecond;<br />    ScheduledQueryRunSummary runSummary;<br />}<br /><br />ScheduledQueryRunSummary {<br />    Date invocationTime;<br />    Date triggerTime;<br />    String runStatus;<br />    ExecutionStats executionstats;<br />    ErrorReportLocation errorReportLocation;<br />    String failureReason;<br />}<br /><br /><br />ExecutionStats {<br />    Long bytesMetered;<br />    Long dataWrites;<br />    Long queryResultRows;<br />    Long recordsIngested;<br />    Long executionTimeInMillis;<br />}<br /><br /><br />ErrorReportLocation {<br />    S3ReportLocation s3ReportLocation;<br />}<br /><br /><br />S3ReportLocation {<br />    String bucketName;<br />    String objectKey;<br />}</pre>  |  This notification message is sent after the scheduled query is run and the results are successfully ingested.  *ARN* - The ARN of the scheduled query that is being deleted. *NotificationType* - AUTO\$1TRIGGER\$1SUCCESS or MANUAL\$1TRIGGER\$1SUCCESS. *nextInvocationEpochSecond* - The next time Timestream for LiveAnalytics will run the scheduled query. *runSummary* - Information about the scheduled query run.  | 
|  FailureNotificationMessage  |  <pre>FailureNotificationMessage {<br />    NotificationType type;<br />    String arn;<br />    ScheduledQueryRunSummary runSummary;<br />}<br /><br />ScheduledQueryRunSummary {<br />    Date invocationTime;<br />    Date triggerTime;<br />    String runStatus;<br />    ExecutionStats executionstats;<br />    ErrorReportLocation errorReportLocation;<br />    String failureReason;<br />}<br /><br /><br />ExecutionStats {<br />    Long bytesMetered;<br />    Long dataWrites;<br />    Long queryResultRows;<br />    Long recordsIngested;<br />    Long executionTimeInMillis;<br />}<br /><br /><br />ErrorReportLocation {<br />    S3ReportLocation s3ReportLocation;<br />}<br /><br /><br />S3ReportLocation {<br />    String bucketName;<br />    String objectKey;<br />}</pre>  |  This notification message is sent when a failure is encountered during a scheduled query run or when ingesting the query results.  *arn* - The ARN of the scheduled query that is being run. *type* - AUTO\$1TRIGGER\$1FAILURE or MANUAL\$1TRIGGER\$1FAILURE. *runSummary* - Information about the scheduled query run.  | 

# Scheduled query error reports
<a name="scheduledqueries-errorreport"></a>

This section describes the location, format, and reasons for error reports generated by Timestream for LiveAnalytics when errors are encountered by running scheduled queries.

**Topics**
+ [Reasons](#scheduled-queries-error-report-reasons)
+ [Location](#scheduled-queries-error-report-location)
+ [Format](#scheduled-queries-error-report-format)
+ [Error types](#scheduled-queries-error-report-error-types)
+ [Example](#scheduled-queries-error-report-example)

## Scheduled query error reports reasons
<a name="scheduled-queries-error-report-reasons"></a>

Error reports are generated for recoverable errors. Error reports are not generated for non-recoverable errors. Timestream for LiveAnalytics can disable the scheduled queries automatically when non-recoverable errors are encountered. These include:
+ `AssumeRole` failure
+ Any 4xx errors encountered when communicating with KMS when a customer-managed KMS key is specified
+ Any 4xx errors encountered when a scheduled query runs
+ Any 4xx errors encountered during ingestion of query results

For non-recoverable errors, Timestream for LiveAnalytics sends a failure notification with a non-recoverable error message. An update notification is also sent which indicates that the scheduled query is disabled.

## Scheduled query error reports location
<a name="scheduled-queries-error-report-location"></a>

A scheduled query error report location has the following naming convention:

```
s3://customer-bucket/customer-prefix/
```

Following is an example scheduled query ARN:

```
arn:aws:timestream:us-east-1:000000000000:scheduled-query/test-query-hd734tegrgfd
```

```
s3://customer-bucket/customer-prefix/test-query-hd734tegrgfd/<InvocationTime>/<Auto or Manual>/<Actual Trigger Time>
```

*Auto* indicates scheduled queries automatically scheduled by Timestream for LiveAnalytics and *Manual* indicates scheduled queries manually triggered by a user via `ExecuteScheduledQuery` API action in Amazon Timestream for LiveAnalytics Query. For more information about `ExecuteScheduledQuery`, see [ExecuteScheduledQuery](https://docs.aws.amazon.com/timestream/latest/developerguide/API_query_ExecuteScheduledQuery.html).

## Scheduled query error reports format
<a name="scheduled-queries-error-report-format"></a>

 The error reports have the following JSON format:

```
{
    "reportId": <String>,            // A unique string ID for all error reports belonging to a particular scheduled query run
    "errors": [ <Error>, ... ],      // One or more errors
}
```

## Scheduled query error types
<a name="scheduled-queries-error-report-error-types"></a>

The `Error` object can be one of three types: 
+ Records Ingestion Errors

  ```
  {
      "reason": <String>,              // The error message String
      "records": [ <Record>, ... ],    // One or more rejected records )
  }
  ```
+ Row Parse and Validation Errors

  ```
  {
      "reason": <String>,        // The error message String
      "rawLine": <String>,       // [Optional] The raw line String that is being parsed into record(s) to be ingested. This line has encountered the above-mentioned parse error.
  }
  ```
+ General Errors

  ```
  {
      "reason": <String>,        // The error message
  }
  ```

## Scheduled query error reports example
<a name="scheduled-queries-error-report-example"></a>

The following is an example of an error report that was produced due to ingestion errors. 

```
{
    "reportId": "C9494AABE012D1FBC162A67EA2C18255",
    "errors": [
        {
            "reason": "The record timestamp is outside the time range [2021-11-12T14:18:13.354Z, 2021-11-12T16:58:13.354Z) of the memory store.",
            "records": [
                {
                    "dimensions": [
                        {
                            "name": "dim0",
                            "value": "d0_1",
                            "dimensionValueType": null
                        },
                        {
                            "name": "dim1",
                            "value": "d1_1",
                            "dimensionValueType": null
                        }
                    ],
                    "measureName": "random_measure_value",
                    "measureValue": "3.141592653589793",
                    "measureValues": null,
                    "measureValueType": "DOUBLE",
                    "time": "1637166175635000000",
                    "timeUnit": "NANOSECONDS",
                    "version": null
                },
                {
                    "dimensions": [
                        {
                            "name": "dim0",
                            "value": "d0_2",
                            "dimensionValueType": null
                        },
                        {
                            "name": "dim1",
                            "value": "d1_2",
                            "dimensionValueType": null
                        }
                    ],
                    "measureName": "random_measure_value",
                    "measureValue": "6.283185307179586",
                    "measureValues": null,
                    "measureValueType": "DOUBLE",
                    "time": "1637166175636000000",
                    "timeUnit": "NANOSECONDS",
                    "version": null
                },
                {
                    "dimensions": [
                        {
                            "name": "dim0",
                            "value": "d0_3",
                            "dimensionValueType": null
                        },
                        {
                            "name": "dim1",
                            "value": "d1_3",
                            "dimensionValueType": null
                        }
                    ],
                    "measureName": "random_measure_value",
                    "measureValue": "9.42477796076938",
                    "measureValues": null,
                    "measureValueType": "DOUBLE",
                    "time": "1637166175637000000",
                    "timeUnit": "NANOSECONDS",
                    "version": null
                },
                {
                    "dimensions": [
                        {
                            "name": "dim0",
                            "value": "d0_4",
                            "dimensionValueType": null
                        },
                        {
                            "name": "dim1",
                            "value": "d1_4",
                            "dimensionValueType": null
                        }
                    ],
                    "measureName": "random_measure_value",
                    "measureValue": "12.566370614359172",
                    "measureValues": null,
                    "measureValueType": "DOUBLE",
                    "time": "1637166175638000000",
                    "timeUnit": "NANOSECONDS",
                    "version": null
                }
            ]
        }
    ]
}
```

# Scheduled query patterns and examples
<a name="scheduledqueries-examplesandpatterns"></a>

This section describes the usage patterns for scheduled queries as well as end-to-end examples.

**Topics**
+ [Sample schema](scheduledqueries-common-schema-example.md)
+ [Patterns](scheduledqueries-patterns.md)
+ [Examples](scheduledqueries-examples.md)

# Scheduled queries sample schema
<a name="scheduledqueries-common-schema-example"></a>

In this example we will use a sample application mimicking a DevOps scenario monitoring metrics from a large fleet of servers. Users want to alert on anomalous resource usage, create dashboards on aggregate fleet behavior and utilization, and perform sophisticated analysis on recent and historical data to find correlations. The following diagram provides an illustration of the setup where a set of monitored instances emit metrics to Timestream for LiveAnalytics. Another set of concurrent users issues queries for alerts, dashboards, or ad-hoc analysis, where queries and ingestion run in parallel. 

![\[Diagram showing data flow from servers to Timestream database, with users querying for analytics.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/schedquery_common_schema_example.png)


The application being monitored is modeled as a highly scaled-out service that is deployed in several regions across the globe. Each region is further subdivided into a number of scaling units called cells that have a level of isolation in terms of infrastructure within the region. Each cell is further subdivided into silos, which represent a level of software isolation. Each silo has five microservices that comprise one isolated instance of the service. Each microservice has several servers with different instance types and OS versions, which are deployed across three availability zones. These attributes that identify the servers emitting the metrics are modeled as [dimensions](https://docs.aws.amazon.com/timestream/latest/developerguide/concepts.html) in Timestream for LiveAnalytics. In this architecture, we have a hierarchy of dimensions (such as region, cell, silo, and microservice\$1name) and other dimensions that cut across the hierarchy (such as instance\$1type and availability\$1zone). 

The application emits a variety of metrics (such as cpu\$1user and memory\$1free) and events (such as task\$1completed and gc\$1reclaimed). Each metric or event is associated with eight dimensions (such as region or cell) that uniquely identify the server emitting it. Data is written with the 20 metrics stored together in a multi-measure record with measure name metrics and all the 5 events are stored together in another multi-measure record with measure name events. The data model, schema, and data generation can be found in the [open-sourced data generator](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/tools/python/perf-scale-workload). In addition to the schema and data distributions, the data generator provides an example of using multiple writers to ingest data in parallel, using the ingestion scaling of Timestream for LiveAnalytics to ingest millions of measurements per second. Below we show the schema (table and measure schema) and some sample data from the data set.

**Topics**
+ [Multi-measure records](#scheduledqueries-common-schema-example-mmr)
+ [Single-measure records](#scheduledqueries-common-schema-example-smr)

## Multi-measure records
<a name="scheduledqueries-common-schema-example-mmr"></a>

**Table Schema**

Below is the table schema once the data is ingested using multi-measure records. It is the output of DESCRIBE query. Assuming the data is ingested into a database raw\$1data and table devops, below is the query.

```
DESCRIBE "raw_data"."devops"
```


| Column | Type | Timestream for LiveAnalytics attribute type | 
| --- | --- | --- | 
| availability\$1zone | varchar | DIMENSION | 
| microservice\$1name | varchar | DIMENSION | 
| instance\$1name | varchar | DIMENSION | 
| process\$1name | varchar | DIMENSION | 
| os\$1version | varchar | DIMENSION | 
| jdk\$1version | varchar | DIMENSION | 
| cell | varchar | DIMENSION | 
| region | varchar | DIMENSION | 
| silo | varchar | DIMENSION | 
| instance\$1type | varchar | DIMENSION | 
| measure\$1name | varchar | MEASURE\$1NAME | 
| time | timestamp | TIMESTAMP | 
| memory\$1free | double | MULTI | 
| cpu\$1steal | double | MULTI | 
| cpu\$1iowait | double | MULTI | 
| cpu\$1user | double | MULTI | 
| memory\$1cached | double | MULTI | 
| disk\$1io\$1reads | double | MULTI | 
| cpu\$1hi | double | MULTI | 
| latency\$1per\$1read | double | MULTI | 
| network\$1bytes\$1out | double | MULTI | 
| cpu\$1idle | double | MULTI | 
| disk\$1free | double | MULTI | 
| memory\$1used | double | MULTI | 
| cpu\$1system | double | MULTI | 
| file\$1descriptors\$1in\$1use | double | MULTI | 
| disk\$1used | double | MULTI | 
| cpu\$1nice | double | MULTI | 
| disk\$1io\$1writes | double | MULTI | 
| cpu\$1si | double | MULTI | 
| latency\$1per\$1write | double | MULTI | 
| network\$1bytes\$1in | double | MULTI | 
| task\$1end\$1state | varchar | MULTI | 
| gc\$1pause | double | MULTI | 
| task\$1completed | bigint | MULTI | 
| gc\$1reclaimed | double | MULTI | 

**Measure Schema**

Below is the measure schema returned by the SHOW MEASURES query.

```
SHOW MEASURES FROM "raw_data"."devops"
```


| measure\$1name | data\$1type | Dimensions | 
| --- | --- | --- | 
| events | multi | [\$1"data\$1type":"varchar","dimension\$1name":"availability\$1zone"\$1,\$1"data\$1type":"varchar","dimension\$1name":"microservice\$1name"\$1,\$1"data\$1type":"varchar","dimension\$1name":"instance\$1name"\$1,\$1"data\$1type":"varchar","dimension\$1name":"process\$1name"\$1,\$1"data\$1type":"varchar","dimension\$1name":"jdk\$1version"\$1,\$1"data\$1type":"varchar","dimension\$1name":"cell"\$1,\$1"data\$1type":"varchar","dimension\$1name":"region"\$1,\$1"data\$1type":"varchar","dimension\$1name":"silo"\$1] | 
| metrics | multi | [\$1"data\$1type":"varchar","dimension\$1name":"availability\$1zone"\$1,\$1"data\$1type":"varchar","dimension\$1name":"microservice\$1name"\$1,\$1"data\$1type":"varchar","dimension\$1name":"instance\$1name"\$1,\$1"data\$1type":"varchar","dimension\$1name":"os\$1version"\$1,\$1"data\$1type":"varchar","dimension\$1name":"cell"\$1,\$1"data\$1type":"varchar","dimension\$1name":"region"\$1,\$1"data\$1type":"varchar","dimension\$1name":"silo"\$1,\$1"data\$1type":"varchar","dimension\$1name":"instance\$1type"\$1] | 

**Example Data**


| region | Cell | Silo | availability\$1zone | microservice\$1name | instance\$1name | instance\$1type | os\$1version | process\$1name | jdk\$1version | measure\$1name | Time | cpu\$1user | cpu\$1system | cpu\$1idle | cpu\$1steal | cpu\$1iowait | cpu\$1nice | cpu\$1hi | cpu\$1si | memory\$1used | memory\$1cached | disk\$1io\$1reads | latency\$1per\$1read | disk\$1io\$1writes | latency\$1per\$1write | disk\$1used | disk\$1free | network\$1bytes\$1in | network\$1bytes\$1out | file\$1descriptors\$1in\$1use | memory\$1free | task\$1end\$1state | gc\$1pause | task\$1completed | gc\$1reclaimed | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 
| us-east-2 | us-east-2-cell-1 | us-east-2-cell-1-silo-2 | us-east-2-1 | athena | i-zaZswmJk-athena-us-east-2-cell-1-silo-2-00000216.amazonaws.com | m5.8xlarge | AL2012 |  |  | metrics | 11/12/2021 12:43 | 62.8 | 0.408 | 34.2 | 0.972 | 0.0877 | 0.103 | 0.567 | 0.844 | 57.6 | 88.9 | 52.6 | 91.9 | 31.7 | 2.25 | 63.5 | 29.2 | 85.3 | 49.8 | 32.3 | 57.6 |  |  |  |  | 
| us-east-2 | us-east-2-cell-1 | us-east-2-cell-1-silo-2 | us-east-2-1 | athena | i-zaZswmJk-athena-us-east-2-cell-1-silo-2-00000216.amazonaws.com | m5.8xlarge | AL2012 |  |  | metrics | 11/12/2021 12:41 | 56 | 0.923 | 39.9 | 0.799 | 0.532 | 0.655 | 0.851 | 0.317 | 90.5 | 31.9 | 56.6 | 37.1 | 25 | 93.3 | 52.2 | 33.1 | 7.14 | 53.7 | 65.9 | 20.4 |  |  |  |  | 
| us-east-2 | us-east-2-cell-1 | us-east-2-cell-1-silo-2 | us-east-2-1 | athena | i-zaZswmJk-athena-us-east-2-cell-1-silo-2-00000216.amazonaws.com | m5.8xlarge | AL2012 |  |  | metrics | 11/12/2021 12:39 | 48.5 | 0.801 | 48.2 | 0.18 | 0.943 | 0.0316 | 0.844 | 0.54 | 97.4 | 41.4 | 55.1 | 32.7 | 86.2 | 33.7 | 72.7 | 61.5 | 80.8 | 5.15 | 44.3 | 8.5 |  |  |  |  | 
| us-east-2 | us-east-2-cell-1 | us-east-2-cell-1-silo-2 | us-east-2-1 | athena | i-zaZswmJk-athena-us-east-2-cell-1-silo-2-00000216.amazonaws.com | m5.8xlarge | AL2012 |  |  | metrics | 11/12/2021 12:38 | 37.5 | 0.723 | 58.8 | 0.317 | 0.608 | 0.859 | 0.791 | 0.393 | 4.84 | 78.9 | 20.3 | 41.4 | 46.8 | 3.87 | 84.6 | 60.6 | 21.1 | 11.8 | 2.76 | 10 |  |  |  |  | 
| us-east-2 | us-east-2-cell-1 | us-east-2-cell-1-silo-2 | us-east-2-1 | athena | i-zaZswmJk-athena-us-east-2-cell-1-silo-2-00000216.amazonaws.com | m5.8xlarge | AL2012 |  |  | metrics | 11/12/2021 12:36 | 58 | 0.786 | 38.7 | 0.219 | 0.436 | 0.829 | 0.331 | 0.734 | 51 | 36.8 | 81.8 | 50.5 | 77.9 | 17.8 | 82.3 | 64 | 7.69 | 66.5 | 56.2 | 31.3 |  |  |  |  | 
| us-east-2 | us-east-2-cell-1 | us-east-2-cell-1-silo-2 | us-east-2-1 | athena | i-zaZswmJk-athena-us-east-2-cell-1-silo-2-00000216.amazonaws.com |  |  | host\$1manager | JDK\$18 | events | 11/12/2021 12:43 |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  | 75.8 | SUCCESS\$1WITH\$1NO\$1RESULT | 85.5 | 348 | 64.8 | 
| us-east-2 | us-east-2-cell-1 | us-east-2-cell-1-silo-2 | us-east-2-1 | athena | i-zaZswmJk-athena-us-east-2-cell-1-silo-2-00000216.amazonaws.com |  |  | host\$1manager | JDK\$18 | events | 11/12/2021 12:41 |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  | 7.47 | SUCCESS\$1WITH\$1RESULT | 22.8 | 42 | 7.45 | 
| us-east-2 | us-east-2-cell-1 | us-east-2-cell-1-silo-2 | us-east-2-1 | athena | i-zaZswmJk-athena-us-east-2-cell-1-silo-2-00000216.amazonaws.com |  |  | host\$1manager | JDK\$18 | events | 11/12/2021 12:39 |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  | 64.1 | SUCCESS\$1WITH\$1RESULT | 6.77 | 249 | 72.3 | 
| us-east-2 | us-east-2-cell-1 | us-east-2-cell-1-silo-2 | us-east-2-1 | athena | i-zaZswmJk-athena-us-east-2-cell-1-silo-2-00000216.amazonaws.com |  |  | host\$1manager | JDK\$18 | events | 11/12/2021 12:38 |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  | 23 | SUCCESS\$1WITH\$1RESULT | 53.3 | 138 | 99 | 
| us-east-2 | us-east-2-cell-1 | us-east-2-cell-1-silo-2 | us-east-2-1 | athena | i-zaZswmJk-athena-us-east-2-cell-1-silo-2-00000216.amazonaws.com |  |  | host\$1manager | JDK\$18 | events | 11/12/2021 12:36 |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  | 39.4 | SUCCESS\$1WITH\$1NO\$1RESULT | 79.6 | 254 | 82.9 | 

## Single-measure records
<a name="scheduledqueries-common-schema-example-smr"></a>

Timestream for LiveAnalytics also allows you to ingest the data with one measure per time series record. Below are the schema details when ingested using single measure records.

**Table Schema**

Below is the table schema once the data is ingested using multi-measure records. It is the output of DESCRIBE query. Assuming the data is ingested into a database raw\$1data and table devops, below is the query.

```
DESCRIBE "raw_data"."devops_single"
```


| Column | Type | Timestream for LiveAnalytics attribute type | 
| --- | --- | --- | 
| availability\$1zone | varchar | DIMENSION | 
| microservice\$1name | varchar | DIMENSION | 
| instance\$1name | varchar | DIMENSION | 
| process\$1name | varchar | DIMENSION | 
| os\$1version | varchar | DIMENSION | 
| jdk\$1version | varchar | DIMENSION | 
| cell | varchar | DIMENSION | 
| region | varchar | DIMENSION | 
| silo | varchar | DIMENSION | 
| instance\$1type | varchar | DIMENSION | 
| measure\$1name | varchar | MEASURE\$1NAME | 
| time | timestamp | TIMESTAMP | 
| measure\$1value::double | double | MEASURE\$1VALUE | 
| measure\$1value::bigint | bigint | MEASURE\$1VALUE | 
| measure\$1value::varchar | varchar | MEASURE\$1VALUE | 

**Measure Schema**

Below is the measure schema returned by the SHOW MEASURES query.

```
SHOW MEASURES FROM "raw_data"."devops_single"
```


| measure\$1name | data\$1type | Dimensions | 
| --- | --- | --- | 
| cpu\$1hi | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| cpu\$1idle | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| cpu\$1iowait | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| cpu\$1nice | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| cpu\$1si | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| cpu\$1steal | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| cpu\$1system | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| cpu\$1user | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| disk\$1free | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| disk\$1io\$1reads | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| disk\$1io\$1writes | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| disk\$1used | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| file\$1descriptors\$1in\$1use | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| gc\$1pause | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'process\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'jdk\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1] | 
| gc\$1reclaimed | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'process\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'jdk\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1] | 
| latency\$1per\$1read | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| latency\$1per\$1write | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| memory\$1cached | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| memory\$1free | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'process\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'jdk\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| memory\$1used | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| network\$1bytes\$1in | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| network\$1bytes\$1out | double | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'os\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1type', 'data\$1type': 'varchar'\$1] | 
| task\$1completed | bigint | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'process\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'jdk\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1] | 
| task\$1end\$1state | varchar | [\$1'dimension\$1name': 'availability\$1zone', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'microservice\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'instance\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'process\$1name', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'jdk\$1version', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'cell', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'region', 'data\$1type': 'varchar'\$1, \$1'dimension\$1name': 'silo', 'data\$1type': 'varchar'\$1] | 

**Example Data**


| availability\$1zone | microservice\$1name | instance\$1name | process\$1name | os\$1version | jdk\$1version | Cell | region | Silo | instance\$1type | measure\$1name | Time | measure\$1value::double | measure\$1value::bigint | measure\$1value::varchar | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | cpu\$1hi | 34:57.2 | 0.87169 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | cpu\$1idle | 34:57.2 | 3.46266 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | cpu\$1iowait | 34:57.2 | 0.10226 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | cpu\$1nice | 34:57.2 | 0.63013 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | cpu\$1si | 34:57.2 | 0.16441 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | cpu\$1steal | 34:57.2 | 0.10729 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | cpu\$1system | 34:57.2 | 0.45709 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | cpu\$1user | 34:57.2 | 94.20448 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | disk\$1free | 34:57.2 | 72.51895 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | disk\$1io\$1reads | 34:57.2 | 81.73383 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | disk\$1io\$1writes | 34:57.2 | 77.11665 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | disk\$1used | 34:57.2 | 89.42235 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | file\$1descriptors\$1in\$1use | 34:57.2 | 30.08254 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com | server |  | JDK\$18 | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 |  | gc\$1pause | 34:57.2 | 60.28679 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com | server |  | JDK\$18 | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 |  | gc\$1reclaimed | 34:57.2 | 75.28839 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | latency\$1per\$1read | 34:57.2 | 8.07605 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | latency\$1per\$1write | 34:57.2 | 58.11223 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | memory\$1cached | 34:57.2 | 87.56481 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com | server |  | JDK\$18 | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 |  | memory\$1free | 34:57.2 | 18.95768 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | memory\$1free | 34:57.2 | 97.20523 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | memory\$1used | 34:57.2 | 12.37723 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | network\$1bytes\$1in | 34:57.2 | 31.02065 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com |  | AL2012 |  | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 | r5.4xlarge | network\$1bytes\$1out | 34:57.2 | 0.51424 |  |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com | server |  | JDK\$18 | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 |  | task\$1completed | 34:57.2 |  | 69 |  | 
| eu-west-1-1 | hercules | i-zaZswmJk-hercules-eu-west-1-cell-9-silo-2-00000027.amazonaws.com | server |  | JDK\$18 | eu-west-1-cell-9 | eu-west-1 | eu-west-1-cell-9-silo-2 |  | task\$1end\$1state | 34:57.2 |  |  | SUCCESS\$1WITH\$1RESULT | 

# Scheduled query patterns
<a name="scheduledqueries-patterns"></a>

In this section you will find some common patterns of how you can use Amazon Timestream for LiveAnalytics Scheduled Queries to optimize your dashboards to load faster and at reduced costs. The examples below use a DevOps application scenario to illustrate the key concepts which apply to scheduled queries in general, irrespective of the application scenario.

Scheduled Queries in Timestream for LiveAnalytics allow you to express your queries using the full SQL surface area of Timestream for LiveAnalytics. Your query can include one or more source tables, perform aggregations or any other query allowed by Timestream for LiveAnalytics's SQL language, and then materialize the results of the query in another destination table in Timestream for LiveAnalytics. For ease of exposition, this section refers to this target table of a scheduled query as a *derived table*.

The following are the key points that are covered in this section.
+ Using a simple fleet-level aggregate to explain how you can define a scheduled query and understand some basic concepts. 
+ How you can combine results from the target of a scheduled query (the derived table) with the results from the source table to get the cost and performance benefits of scheduled query. 
+ What are your trade-offs when configuring the refresh period of the scheduled queries. 
+ Using scheduled queries for some common scenarios.
  + Tracking the last data point from every instance before a specific date.
  + Distinct values for a dimension to use for populating variables in a dashboard.
+ How you handle late arriving data in the context of scheduled queries.
+ How you can use one-off manual executions to handle a variety of scenarios not directly covered by automated triggers for scheduled queries.

**Topics**
+ [Scenario](scheduledqueries-patterns-scenario.md)
+ [Simple fleet-level aggregates](scheduledqueries-patterns-simplefleet.md)
+ [Last point from each device](scheduledqueries-patterns-lastpointfromdevice.md)
+ [Unique dimension values](scheduledqueries-patterns-uniquedimvalues.md)
+ [Handling late-arriving data](scheduledqueries-patterns-latearrive.md)
+ [Back-filling historical pre-computations](scheduledqueries-patterns-backfilling.md)

# Scenario
<a name="scheduledqueries-patterns-scenario"></a>

The following examples use a DevOps monitoring scenario which is outlined in [Scheduled queries sample schema](scheduledqueries-common-schema-example.md).

The examples provide the scheduled query definition where you can plug in the appropriate configurations for where to receive execution status notifications for scheduled queries, where to receive reports for errors encountered during execution of a scheduled query, and the IAM role the scheduled query uses to perform its operations.

You can create these scheduled queries after filling in the preceding options, [creating the target ](https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.create-table.html) (or derived) table, and executing the through the AWS CLI. For example, assume that a scheduled query definition is stored in a file, `scheduled_query_example.json`. You can create the query using the CLI command.

```
aws timestream-query create-scheduled-query --cli-input-json  file://scheduled_query_example.json --profile aws_profile --region us-east-1
```

In the preceding command, the profile passed using the --profile option must have the appropriate permissions to create scheduled queries. See [Identity-based policies for Scheduled Queries](https://docs.aws.amazon.com/timestream/latest/developerguide/security_iam_id-based-policy-examples.html#security_iam_id-based-policy-examples-sheduledqueries) for detailed instructions for the policies and permissions.

# Simple fleet-level aggregates
<a name="scheduledqueries-patterns-simplefleet"></a>

This first example walks you through some of the basic concepts when working with scheduled queries using a simple example computing fleet-level aggregates. Using this example, you will learn the following.
+ How to take your dashboard query that is used to obtain aggregate statistics and map it to a scheduled query.
+ How Timestream for LiveAnalytics manages the execution of the different instances of your scheduled query.
+ How you can have different instances of scheduled queries overlap in time ranges and how the correctness of data is maintained on the target table to ensure that your dashboard using the results of the scheduled query gives you results that match with the same aggregate computed on the raw data. 
+ How to set the time range and refresh cadence for your scheduled query.
+ How you can self-serve track the results of the scheduled queries to tune them so that the execution latency for the query instances are within the acceptable delays of refreshing your dashboards. 

**Topics**
+ [Aggregate from source tables](#scheduledqueries-patterns-simplefleet-aggrfromsourcetable)
+ [Scheduled query to pre-compute aggregates](#scheduledqueries-patterns-simplefleet-schedtoprecomputeaggr)
+ [Aggregate from derived table](#scheduledqueries-patterns-simplefleet-aggrfromderived)
+ [Aggregate combining source and derived tables](#scheduledqueries-patterns-simplefleet-aggrcombsourceandderived)
+ [Aggregate from frequently refreshed scheduled computation](#scheduledqueries-patterns-simplefleet-aggregatefromrequently)

## Aggregate from source tables
<a name="scheduledqueries-patterns-simplefleet-aggrfromsourcetable"></a>

In this example, you are tracking the number of metrics emitted by the servers within a given region in every minute. The graph below is an example plotting this time series for the region us-east-1.

![\[Time series graph showing fluctuating number of metrics emitted by servers in us-east-1 region.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/schedquery_aggrfromsourcetable.png)


Below is an example query to compute this aggregate from the raw data. It filters the rows for the region us-east-1 and then computes the per minute sum by accounting for the 20 metrics (if measure\$1name is metrics) or 5 events (if measure\$1name is events). In this example, the graph illustration shows that the number of metrics emitted vary between 1.5 Million to 6 Million per minute. When plotting this time series for several hours (past 12 hours in this figure), this query over the raw data analyzes hundreds of millions of rows.

```
WITH grouped_data AS (
    SELECT region, bin(time, 1m) as minute, SUM(CASE WHEN measure_name = 'metrics' THEN 20 ELSE 5 END) as numDataPoints 
    FROM "raw_data"."devops"
    WHERE time BETWEEN from_milliseconds(1636699996445) AND from_milliseconds(1636743196445)
        AND region = 'us-east-1'
    GROUP BY region, measure_name, bin(time, 1m)
)
SELECT minute, SUM(numDataPoints) AS numDataPoints
FROM grouped_data
GROUP BY minute
ORDER BY 1 desc, 2 desc
```

## Scheduled query to pre-compute aggregates
<a name="scheduledqueries-patterns-simplefleet-schedtoprecomputeaggr"></a>

If you would like to optimize your dashboards to load faster and lower your costs by scanning less data, you can use a scheduled query to pre-compute these aggregates. Scheduled queries in Timestream for LiveAnalytics allows you to materialize these pre-computations in another Timestream for LiveAnalytics table, which you can subsequently use for your dashboards.

The first step in creating a scheduled query is to identify the query you want to pre-compute. Note that the preceding dashboard was drawn for region us-east-1. However, a different user may want the same aggregate for a different region, say us-west-2 or eu-west-1. To avoid creating a scheduled query for each such query, you can pre-compute the aggregate for each region and materialize the per-region aggregates in another Timestream for LiveAnalytics table.

The query below provides an example of the corresponding pre-computation. As you can see, it is similar to the common table expression grouped\$1data used in the query on the raw data, except for two differences: 1) it does not use a region predicate, so that we can use one query to pre-compute for all regions; and 2) it uses a parameterized time predicate with a special parameter @scheduled\$1runtime which is explained in details below.

```
SELECT region, bin(time, 1m) as minute, 
    SUM(CASE WHEN measure_name = 'metrics' THEN 20 ELSE 5 END) as numDataPoints 
FROM raw_data.devops 
WHERE time BETWEEN @scheduled_runtime - 10m AND @scheduled_runtime + 1m 
GROUP BY bin(time, 1m), region
```

The preceding query can be converted into a scheduled query using the following specification. The scheduled query is assigned a Name, which is a user-friendly mnemonic. It then includes the QueryString, a ScheduleConfiguration, which is a [cron expression](https://docs.aws.amazon.com/timestream/latest/developerguide/scheduledqueries-schedule.html). It specifies the TargetConfiguration which maps the query results to the destination table in Timestream for LiveAnalytics. Finally, it specifies a number of other configurations, such as the NotificationConfiguration, where notifications are sent for individual executions of the query, ErrorReportConfiguration where a report is written in case the query encounters any errors, and the ScheduledQueryExecutionRoleArn, which is the role used to perform operations for the scheduled query.

```
{
    "Name": "MultiPT5mPerMinutePerRegionMeasureCount",
    "QueryString": "SELECT region, bin(time, 1m) as minute, SUM(CASE WHEN measure_name = 'metrics' THEN 20 ELSE 5 END) as numDataPoints FROM raw_data.devops WHERE time BETWEEN @scheduled_runtime - 10m AND @scheduled_runtime + 1m GROUP BY bin(time, 1m), region",
    "ScheduleConfiguration": {
        "ScheduleExpression": "cron(0/5 * * * ? *)"
    },
    "NotificationConfiguration": {
        "SnsConfiguration": {
            "TopicArn": "******"
        }
    },
    "TargetConfiguration": {
        "TimestreamConfiguration": {
            "DatabaseName": "derived",
            "TableName": "per_minute_aggs_pt5m",
            "TimeColumn": "minute",
            "DimensionMappings": [
                {
                    "Name": "region",
                    "DimensionValueType": "VARCHAR"
                }
            ],
            "MultiMeasureMappings": {
                "TargetMultiMeasureName": "numDataPoints",
                "MultiMeasureAttributeMappings": [
                    {
                        "SourceColumn": "numDataPoints",
                        "MeasureValueType": "BIGINT"
                    }
                ]
            }
        }
    },
    "ErrorReportConfiguration": {
        "S3Configuration" : {
            "BucketName" : "******",
            "ObjectKeyPrefix": "errors",
            "EncryptionOption": "SSE_S3"
        }
    },
    "ScheduledQueryExecutionRoleArn": "******"
}
```

In the example, the ScheduleExpression cron(0/5 \$1 \$1 \$1 ? \$1) implies that the query is executed once every 5 minutes at the 5th, 10th, 15th, .. minutes of every hour of every day. These timestamps when a specific instance of this query is triggered is what translates to the @scheduled\$1runtime parameter used in the query. For instance, consider the instance of this scheduled query executing on 2021-12-01 00:00:00. For this instance, the @scheduled\$1runtime parameter is initialized to the timestamp 2021-12-01 00:00:00 when invoking the query. Therefore, this specific instance will execute at timestamp 2021-12-01 00:00:00 and will compute the per-minute aggregates from time range 2021-11-30 23:50:00 to 2021-12-01 00:01:00. Similarly, the next instance of this query is triggered at timestamp 2021-12-01 00:05:00 and in that case, the query will compute per-minute aggregates from the time range 2021-11-30 23:55:00 to 2021-12-01 00:06:00. Hence, the @scheduled\$1runtime parameter provides a scheduled query to pre-compute the aggregates for the configured time ranges using the invocation time for the queries.

Note that two subsequent instances of the query overlap in their time ranges. This is something you can control based on your requirements. In this case, this overlap allows these queries to update the aggregates based on any data whose arrival was slightly delayed, up to 5 minutes in this example. To ensure correctness of the materialized queries, Timestream for LiveAnalytics ensures that the query at 2021-12-01 00:05:00 will be performed only after the query at 2021-12-01 00:00:00 has completed and the results of the latter queries can update any previously materialized aggregate using if a newer value is generated. For example, if some data at timestamp 2021-11-30 23:59:00 arrived after the query for 2021-12-01 00:00:00 executed but before the query for 2021-12-01 00:05:00, then the execution at 2021-12-01 00:05:00 will recompute the aggregates for the minute 2021-11-30 23:59:00 and this will result in the previous aggregate being updated with the newly-computed value. You can rely on these semantics of the scheduled queries to strike a trade-off between how quickly you update your pre-computations versus how you can gracefully handle some data with delayed arrival. Additional considerations are discussed below on how you trade-off this refresh cadence with freshness of the data and how you address updating the aggregates for data that arrives even more delayed or if your source of the scheduled computation has updated values which would require the aggregates to be recomputed. 

Every scheduled computation has a notification configuration where Timestream for LiveAnalytics sends notification of every execution of a scheduled configuration. You can configure an SNS topic for to receive notifications for each invocation. In addition to the success or failure status of a specific instance, it also has several statistics such as the time this computation took to execute, the number of bytes the computation scanned, and the number of bytes the computation wrote to its destination table. You can use these statistics to further tune your query, schedule configuration, or track the spend for your scheduled queries. One aspect worth noting is the execution time for an instance. In this example, the scheduled computation is configured to execute the every 5 minutes. The execution time will determine the delay with which the pre-computation will be available, which will also define the lag in your dashboard when you're using the pre-computed data in your dashboards. Furthermore, if this delay is consistently higher than the refresh interval, for example, if the execution time is more than 5 minutes for a computation configured to refresh every 5 minutes, it is important to tune your computation to run faster to avoid further lag in your dashboards.

## Aggregate from derived table
<a name="scheduledqueries-patterns-simplefleet-aggrfromderived"></a>

Now that you have set up the scheduled queries and the aggregates are pre-computed and materialized to another Timestream for LiveAnalytics table specified in the target configuration of the scheduled computation, you can use the data in that table to write SQL queries to power your dashboards. Below is an equivalent of the query that uses the materialized pre-aggregates to generate the per minute data point count aggregate for us-east-1.

```
SELECT bin(time, 1m) as minute, SUM(numDataPoints) as numDatapoints
FROM "derived"."per_minute_aggs_pt5m"
WHERE time BETWEEN from_milliseconds(1636699996445) AND from_milliseconds(1636743196445)
    AND region = 'us-east-1'
GROUP BY bin(time, 1m)
ORDER BY 1 desc
```

![\[Graph showing data points fluctuating between 0 and 6 million over time from 23:00 to 10:00.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/schedquery_aggrfromderived.png)


The previous figure plots the aggregate computed from the aggregate table. Comparing this panel with the panel computed from the raw source data, you will notice that they match up exactly, albeit these aggregates are delayed by a few minute, controlled by the refresh interval you configured for the scheduled computation plus the time to execute it.

This query over the pre-computed data scans several orders of magnitude lesser data compared to the aggregates computed over the raw source data. Depending on the granularity of aggregations, this reduction can easily result in 100X lower cost and query latency. There is a cost to executing this scheduled computation. However, depending on how frequently these dashboards are refreshed and how many concurrent users load these dashboards, you end up significantly reducing your overall costs by using these pre-computations. And this is on top of 10-100X faster load times for the dashboards.

## Aggregate combining source and derived tables
<a name="scheduledqueries-patterns-simplefleet-aggrcombsourceandderived"></a>

Dashboards created using the derived tables can have a lag. If your application scenario requires the dashboards to have the most recent data, then you can use the power and flexibility of Timestream for LiveAnalytics's SQL support to combine the latest data from the source table with the historical aggregates from the derived table to form a merged view. This merged view uses the union semantics of SQL and non-overlapping time ranges from the source and the derived table. In the example below, we are using the "derived"."per\$1minute\$1aggs\$1pt5m" derived table. Since the scheduled computation for that derived table refreshes once every 5 minutes (per the schedule expression specification), this query below uses the most recent 15 minutes of data from the source table, and any data older than 15 minutes from the derived table and then unions the results to create the merged view that has the best of both worlds: the economics and low latency by reading older pre-computed aggregates from the derived table and the freshness of the aggregates from the source table to power your real time analytics use cases.

Note that this union approach will have slightly higher query latency compared to only querying the derived table and also have slightly higher data scanned, since it is aggregating the raw data in real time to fill in the most recent time interval. However, this merged view will still be significantly faster and cheaper compared to aggregating on the fly from the source table, especially for dashboards rendering days or weeks of data. You can tune the time ranges for this example to suite your application's refresh needs and delay tolerance.

```
WITH aggregated_source_data AS (
    SELECT bin(time, 1m) as minute, SUM(CASE WHEN measure_name = 'metrics' THEN 20 ELSE 5 END) as numDatapoints 
    FROM "raw_data"."devops"
    WHERE time BETWEEN bin(from_milliseconds(1636743196439), 1m) - 15m AND from_milliseconds(1636743196439)
        AND region = 'us-east-1'
    GROUP BY bin(time, 1m)
), aggregated_derived_data AS (
    SELECT bin(time, 1m) as minute, SUM(numDataPoints) as numDatapoints
    FROM "derived"."per_minute_aggs_pt5m"
    WHERE time BETWEEN from_milliseconds(1636699996439) AND bin(from_milliseconds(1636743196439), 1m) - 15m
        AND region = 'us-east-1'
    GROUP BY bin(time, 1m)
)
SELECT minute, numDatapoints
FROM (
    (
    SELECT *
    FROM aggregated_derived_data
    )
    UNION
    (
    SELECT *
    FROM aggregated_source_data
    )
)
ORDER BY 1 desc
```

Below is the dashboard panel with this unified merged view. As you can see, the dashboard looks almost identical to the view computed from the derived table, except for that it will have the most up-to-date aggregate at the rightmost tip.

![\[Time-series graph showing fluctuating data points over 11 hours, with peaks around 6 million.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/schedquery_aggrcombsourceandderived.png)


## Aggregate from frequently refreshed scheduled computation
<a name="scheduledqueries-patterns-simplefleet-aggregatefromrequently"></a>

Depending on how frequently your dashboards are loaded and how much latency you want for your dashboard, there is another approach to obtaining fresher results in your dashboard: having the scheduled computation refresh the aggregates more frequently. For instance, below is configuration of the same scheduled computation, except that it refreshes once every minute (note the schedule express cron(0/1 \$1 \$1 \$1 ? \$1)). With this setup, the derived table per\$1minute\$1aggs\$1pt1m will have much more recent aggregates compared to the scenario where the computation specified a refresh schedule of once every 5 minutes.

```
{
    "Name": "MultiPT1mPerMinutePerRegionMeasureCount",
    "QueryString": "SELECT region, bin(time, 1m) as minute, SUM(CASE WHEN measure_name = 'metrics' THEN 20 ELSE 5 END) as numDataPoints FROM raw_data.devops WHERE time BETWEEN @scheduled_runtime - 10m AND @scheduled_runtime + 1m GROUP BY bin(time, 1m), region",
    "ScheduleConfiguration": {
        "ScheduleExpression": "cron(0/1 * * * ? *)"
    },
    "NotificationConfiguration": {
        "SnsConfiguration": {
            "TopicArn": "******"
        }
    },
    "TargetConfiguration": {
        "TimestreamConfiguration": {
            "DatabaseName": "derived",
            "TableName": "per_minute_aggs_pt1m",
            "TimeColumn": "minute",
            "DimensionMappings": [
                {
                    "Name": "region",
                    "DimensionValueType": "VARCHAR"
                }
            ],
            "MultiMeasureMappings": {
                "TargetMultiMeasureName": "numDataPoints",
                "MultiMeasureAttributeMappings": [
                    {
                        "SourceColumn": "numDataPoints",
                        "MeasureValueType": "BIGINT"
                    }
                ]
            }
        }
    },
    "ErrorReportConfiguration": {
        "S3Configuration" : {
            "BucketName" : "******",
            "ObjectKeyPrefix": "errors",
            "EncryptionOption": "SSE_S3"
        }
    },
    "ScheduledQueryExecutionRoleArn": "******"
}
```

```
SELECT bin(time, 1m) as minute, SUM(numDataPoints) as numDatapoints
FROM "derived"."per_minute_aggs_pt1m"
WHERE time BETWEEN from_milliseconds(1636699996446) AND from_milliseconds(1636743196446)
    AND region = 'us-east-1'
GROUP BY bin(time, 1m), region
ORDER BY 1 desc
```

Since the derived table has more recent aggregates, you can now directly query the derived table per\$1minute\$1aggs\$1pt1m to get fresher aggregates, as can be seen from the previous query and the dashboard snapshot below.

![\[Graph showing fluctuating data points over time, with peaks reaching 6 million and valleys near 1 million.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/schedquery_aggregatefromrequently.png)


Note that refreshing the scheduled computation at a faster schedule (say 1 minute compared to 5 minutes) will increase the maintenance costs for the scheduled computation. The notification message for every computation's execution provides statistics for how much data was scanned and how much was written to the derived table. Similarly, if you use the merged view to union the derived table, you query costs on the merged view and the dashboard load latency will be higher compared to only querying the derived table. Therefore, the approach you pick will depend on how frequently your dashboards are refreshed and the maintenance costs for the scheduled queries. If you have tens of users refreshing the dashboards once every minute or so, having a more frequent refresh of your derived table will likely result in overall lower costs.

# Last point from each device
<a name="scheduledqueries-patterns-lastpointfromdevice"></a>

Your application may require you to read the last measurement emitted by a device. There can be more general use cases to obtain the last measurement for a device before a given date/time or the first measurement for a device after a given date/time. When you have millions of devices and years of data, this search might require scanning large amounts of data.

Below you will see an example of how you can use scheduled queries to optimize searching for the last point emitted by a device. You can use the same pattern to optimize the first point query as well if your application needs them.

**Topics**
+ [Computed from source table](#scheduledqueries-patterns-lastpointfromdevice-computedfromsrctable)
+ [Derived table to precompute at daily granularity](#scheduledqueries-patterns-lastpointfromdevice-derivedttabletoprecompute)
+ [Computed from derived table](#scheduledqueries-patterns-lastpointfromdevice-computedfromderivedtable)
+ [Combining from source and derived table](#scheduledqueries-patterns-lastpointfromdevice-combinesourceandderived)

## Computed from source table
<a name="scheduledqueries-patterns-lastpointfromdevice-computedfromsrctable"></a>

Below is an example query to find the last measurement emitted by the services in a specific deployment (for example, servers for a given micro-service within a given region, cell, silo, and availability\$1zone). In the example application, this query will return the last measurement for hundreds of servers. Also note that this query has an unbounded time predicate and looks for any data older than a given timestamp.

**Note**  
For information about the `max` and `max_by` functions, see [Aggregate functions](aggregate-functions.md).

```
SELECT instance_name, MAX(time) AS time, MAX_BY(gc_pause, time) AS last_measure
FROM "raw_data"."devops"
WHERE time < from_milliseconds(1636685271872)
    AND measure_name = 'events'
    AND region = 'us-east-1'
    AND cell = 'us-east-1-cell-10'
    AND silo = 'us-east-1-cell-10-silo-3'
    AND availability_zone = 'us-east-1-1'
    AND microservice_name = 'hercules'
GROUP BY region, cell, silo, availability_zone, microservice_name,
    instance_name, process_name, jdk_version
ORDER BY instance_name, time DESC
```

## Derived table to precompute at daily granularity
<a name="scheduledqueries-patterns-lastpointfromdevice-derivedttabletoprecompute"></a>

You can convert the preceding use case into a scheduled computation. If your application requirements are such that you may need to obtain these values for your entire fleet across multiple regions, cells, silos, availability zones and microservices, you can use one schedule computation to pre-compute the values for your entire fleet. That is the power of Timestream for LiveAnalytics's serverless scheduled queries that allows these queries to scale with your application's scaling requirements.

Below is a query to pre-compute the last point across all the servers for a given day. Note that the query only has a time predicate and not a predicate on the dimensions. The time predicate limits the query to the past day from the time when the computation is triggered based on the specified schedule expression.

```
SELECT region, cell, silo, availability_zone, microservice_name, 
    instance_name, process_name, jdk_version, 
    MAX(time) AS time, MAX_BY(gc_pause, time) AS last_measure 
FROM raw_data.devops 
WHERE time BETWEEN bin(@scheduled_runtime, 1d) - 1d AND bin(@scheduled_runtime, 1d) 
    AND measure_name = 'events' 
GROUP BY region, cell, silo, availability_zone, microservice_name, 
    instance_name, process_name, jdk_version
```

Below is a configuration for the scheduled computation using the preceding query which executes that query at 01:00 hrs UTC every day to compute the aggregate for the past day. The schedule expression cron(0 1 \$1 \$1 ? \$1) controls this behavior and runs an hour after the day has ended to consider any data arriving up to a day late.

```
{
    "Name": "PT1DPerInstanceLastpoint",
    "QueryString": "SELECT region, cell, silo, availability_zone, microservice_name, instance_name, process_name, jdk_version, MAX(time) AS time, MAX_BY(gc_pause, time) AS last_measure FROM raw_data.devops WHERE time BETWEEN bin(@scheduled_runtime, 1d) - 1d AND bin(@scheduled_runtime, 1d) AND measure_name = 'events' GROUP BY region, cell, silo, availability_zone, microservice_name, instance_name, process_name, jdk_version",
    "ScheduleConfiguration": {
        "ScheduleExpression": "cron(0 1 * * ? *)"
    },
    "NotificationConfiguration": {
        "SnsConfiguration": {
            "TopicArn": "******"
        }
    },
    "TargetConfiguration": {
        "TimestreamConfiguration": {
            "DatabaseName": "derived",
            "TableName": "per_timeseries_lastpoint_pt1d",
            "TimeColumn": "time",
            "DimensionMappings": [
                {
                    "Name": "region",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "cell",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "silo",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "availability_zone",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "microservice_name",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "instance_name",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "process_name",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "jdk_version",
                    "DimensionValueType": "VARCHAR"
                }
            ],
            "MultiMeasureMappings": {
                "TargetMultiMeasureName": "last_measure",
                "MultiMeasureAttributeMappings": [
                    {
                        "SourceColumn": "last_measure",
                        "MeasureValueType": "DOUBLE"
                    }
                ]
            }
        }
    },
    "ErrorReportConfiguration": {
        "S3Configuration" : {
            "BucketName" : "******",
            "ObjectKeyPrefix": "errors",
            "EncryptionOption": "SSE_S3"
        }
    },
    "ScheduledQueryExecutionRoleArn": "******"
}
```

## Computed from derived table
<a name="scheduledqueries-patterns-lastpointfromdevice-computedfromderivedtable"></a>

Once you define the derived table using the preceding configuration and at least one instance of the scheduled query has materialized data into the derived table, you can now query the derived table to get the latest measurement. Below is an example query on the derived table.

```
SELECT instance_name, MAX(time) AS time, MAX_BY(last_measure, time) AS last_measure
FROM "derived"."per_timeseries_lastpoint_pt1d"
WHERE time < from_milliseconds(1636746715649)
    AND measure_name = 'last_measure'
    AND region = 'us-east-1'
    AND cell = 'us-east-1-cell-10'
    AND silo = 'us-east-1-cell-10-silo-3'
    AND availability_zone = 'us-east-1-1'
    AND microservice_name = 'hercules'
GROUP BY region, cell, silo, availability_zone, microservice_name,
    instance_name, process_name, jdk_version
ORDER BY instance_name, time DESC
```

## Combining from source and derived table
<a name="scheduledqueries-patterns-lastpointfromdevice-combinesourceandderived"></a>

Similar to the previous example, any data from the derived table will not have the most recent writes. Therefore, you can again use a similar pattern as earlier to merge the data from the derived table for the older data and use the source data for the remaining tip. Below is an example of such a query using the similar UNION approach. Since the application requirement is to find the latest measurement before a time period, and this start time can be in past, the way you write this query is to use the provided time, use the source data for up to a day old from the specified time, and then use the derived table on the older data. As you can see from the query example below, the time predicate on the source data is bounded. That ensures efficient processing on the source table which has significantly higher volume of data, and then the unbounded time predicate is on the derived table.

```
WITH last_point_derived AS (
    SELECT instance_name, MAX(time) AS time, MAX_BY(last_measure, time) AS last_measure
    FROM "derived"."per_timeseries_lastpoint_pt1d"
    WHERE time < from_milliseconds(1636746715649)
        AND measure_name = 'last_measure'
        AND region = 'us-east-1'
        AND cell = 'us-east-1-cell-10'
        AND silo = 'us-east-1-cell-10-silo-3'
        AND availability_zone = 'us-east-1-1'
        AND microservice_name = 'hercules'
    GROUP BY region, cell, silo, availability_zone, microservice_name,
        instance_name, process_name, jdk_version
), last_point_source AS (
    SELECT instance_name, MAX(time) AS time, MAX_BY(gc_pause, time) AS last_measure
    FROM "raw_data"."devops"
    WHERE time < from_milliseconds(1636746715649) AND time > from_milliseconds(1636746715649) - 26h
        AND measure_name = 'events'
        AND region = 'us-east-1'
        AND cell = 'us-east-1-cell-10'
        AND silo = 'us-east-1-cell-10-silo-3'
        AND availability_zone = 'us-east-1-1'
        AND microservice_name = 'hercules'
    GROUP BY region, cell, silo, availability_zone, microservice_name,
        instance_name, process_name, jdk_version
)
SELECT instance_name, MAX(time) AS time, MAX_BY(last_measure, time) AS last_measure
FROM (
    SELECT * FROM last_point_derived
    UNION
    SELECT * FROM last_point_source
)
GROUP BY instance_name
ORDER BY instance_name, time DESC
```

The previous is just one illustration of how you can structure the derived tables. If you have years of data, you can use more levels of aggregations. For instance, you can have monthly aggregates on top of daily aggregates, and you can have hourly aggregates before the daily. So you can merge together the most recent to fill in the last hour, the hourly to fill in the last day, the daily to fill in the last month, and monthly to fill in the older. The number of levels you set up vs. the refresh schedule will be depending on your requirements of how frequently these queries are issues and how many users are concurrently issuing these queries.

# Unique dimension values
<a name="scheduledqueries-patterns-uniquedimvalues"></a>

You may have a use case where you have dashboards which you want to use the unique values of dimensions as variables to drill down on the metrics corresponding to a specific slice of data. The snapshot below is an example where the dashboard pre-populates the unique values of several dimensions such as region, cell, silo, microservice, and availability\$1zone. Here we show an example of how you can use scheduled queries to significantly speed up computing these distinct values of these variables from the metrics you are tracking.

**Topics**
+ [On raw data](#scheduledqueries-patterns-uniquedimvalues-onraw)
+ [Pre-compute unique dimension values](#scheduledqueries-patterns-uniquedimvalues-precompute)
+ [Computing the variables from derived table](#scheduledqueries-patterns-uniquedimvalues-fromderived)

## On raw data
<a name="scheduledqueries-patterns-uniquedimvalues-onraw"></a>

You can use SELECT DISTINCT to compute the distinct values seen from your data. For instance, if you want to obtain the distinct values of region, you can use the query of this form.

```
SELECT DISTINCT region
FROM "raw_data"."devops"
WHERE time > ago(1h)
ORDER BY 1
```

You may be tracking millions of devices and billions of time series. However, in most cases, these interesting variables are for lower cardinality dimensions, where you have a few to tens of values. Computing DISTINCT from raw data can require scanning large volumes of data. 

## Pre-compute unique dimension values
<a name="scheduledqueries-patterns-uniquedimvalues-precompute"></a>

You want these variables to load fast so that your dashboards are interactive. Moreover, these variables are often computed on every dashboard load, so you want them to be cost-effective as well. You can optimize finding these variables using scheduled queries and materializing them in a derived table.

First, you need to identify the dimensions for which you need to compute the DISTINCT values or columns which you will use in the predicates when computing the DISTINCT value.

In this example, you can see that the dashboard is populating distinct values for the dimensions region, cell, silo, availability\$1zone and microservice. So you can use the query below to pre-compute these unique values.

```
SELECT region, cell, silo, availability_zone, microservice_name, 
    min(@scheduled_runtime) AS time, COUNT(*) as numDataPoints 
FROM raw_data.devops 
WHERE time BETWEEN @scheduled_runtime - 15m AND @scheduled_runtime 
GROUP BY region, cell, silo, availability_zone, microservice_name
```

There are a few important things to note here.
+ You can use one scheduled computation to pre-compute values for many different queries. For instance, you are using the preceding query to pre-compute values for five different variables. So you don't need one for each variable. You can use this same pattern to identify shared computation across multiple panels to optimize the number of scheduled queries you need to maintain.
+ The unique values of the dimensions isn't inherently time series data. So you convert this to time series using the @scheduled\$1runtime. By associating this data with the @scheduled\$1runtime parameter, you can also track which unique values appeared at a given point in time, thus creating time series data out of it.
+ In the previous example, you will see a metric value being tracked. This example uses COUNT(\$1). You can compute other meaningful aggregates if you want to track them for your dashboards.

Below is a configuration for a scheduled computation using the previous query. In this example, it is configured to refresh once every 15 mins using the schedule expression cron(0/15 \$1 \$1 \$1 ? \$1). 

```
{
    "Name": "PT15mHighCardPerUniqueDimensions",
    "QueryString": "SELECT region, cell, silo, availability_zone, microservice_name, min(@scheduled_runtime) AS time, COUNT(*) as numDataPoints FROM raw_data.devops WHERE time BETWEEN @scheduled_runtime - 15m AND @scheduled_runtime GROUP BY region, cell, silo, availability_zone, microservice_name",
    "ScheduleConfiguration": {
        "ScheduleExpression": "cron(0/15 * * * ? *)"
    },
    "NotificationConfiguration": {
        "SnsConfiguration": {
            "TopicArn": "******"
        }
    },
    "TargetConfiguration": {
        "TimestreamConfiguration": {
            "DatabaseName": "derived",
            "TableName": "hc_unique_dimensions_pt15m",
            "TimeColumn": "time",
            "DimensionMappings": [
                {
                    "Name": "region",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "cell",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "silo",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "availability_zone",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "microservice_name",
                    "DimensionValueType": "VARCHAR"
                }
            ],
            "MultiMeasureMappings": {
                "TargetMultiMeasureName": "count_multi",
                "MultiMeasureAttributeMappings": [
                    {
                        "SourceColumn": "numDataPoints",
                        "MeasureValueType": "BIGINT"
                    }
                ]
            }
        }
    },
    "ErrorReportConfiguration": {
        "S3Configuration" : {
            "BucketName" : "******",
            "ObjectKeyPrefix": "errors",
            "EncryptionOption": "SSE_S3"
        }
    },
    "ScheduledQueryExecutionRoleArn": "******"
}
```

## Computing the variables from derived table
<a name="scheduledqueries-patterns-uniquedimvalues-fromderived"></a>

Once the scheduled computation pre-materializes the unique values in the derived table hc\$1unique\$1dimensions\$1pt15m, you can use the derived table to efficiently compute the unique values of the dimensions. Below are example queries for how to compute the unique values, and how you can use other variables as predicates in these unique value queries.

**Region**

```
SELECT DISTINCT region
FROM "derived"."hc_unique_dimensions_pt15m"
WHERE time > ago(1h)
ORDER BY 1
```

**Cell**

```
SELECT DISTINCT cell
FROM "derived"."hc_unique_dimensions_pt15m"
WHERE time > ago(1h)
  AND region = '${region}'
ORDER BY 1
```

**Silo**

```
SELECT DISTINCT silo
FROM "derived"."hc_unique_dimensions_pt15m"
WHERE time > ago(1h)
   AND region = '${region}' AND cell = '${cell}'
ORDER BY 1
```

**Microservice**

```
SELECT DISTINCT microservice_name
FROM "derived"."hc_unique_dimensions_pt15m"
WHERE time > ago(1h)
   AND region = '${region}' AND cell = '${cell}'
ORDER BY 1
```

**Availability Zone**

```
SELECT DISTINCT availability_zone
FROM "derived"."hc_unique_dimensions_pt15m"
WHERE time > ago(1h)
   AND region = '${region}' AND cell = '${cell}' AND silo = '${silo}'
ORDER BY 1
```

# Handling late-arriving data
<a name="scheduledqueries-patterns-latearrive"></a>

You may have scenarios where you can have data that arrives significantly late, for example, the time when the data was ingested into Timestream for LiveAnalytics is significantly delayed compared to the timestamp associated to the rows that are ingested. In the previous examples, you have seen how you can use the time ranges defined by the @scheduled\$1runtime parameter to account for some late arriving data. However, if you have use cases where data can be delayed by hours or days, you may need a different pattern to make sure your pre-computations in the derived table are appropriately updated to reflect such late-arriving data. For general information about late-arriving data, see [Writing data (inserts and upserts)](writes.md#writes.writing-data-inserts-upserts).

In the following you will see two different ways to address this late arriving data.
+ If you have predictable delays in your data arrival, then you can use another "catch-up" scheduled computation to update your aggregates for late arriving data.
+ If you have un-predictable delays or occasional late-arrival data, you can use manual executions to update the derived tables.

This discussion covers scenarios for late data arrival. However, the same principles apply for data corrections, where you have modified the data in your source table and you want to update the aggregates in your derived tables.

**Topics**
+ [Scheduled catch-up queries](#scheduledqueries-patterns-latearrive-schedcatchup)
+ [Manual executions for unpredictable late arriving data](#scheduledqueries-patterns-latearrive-manual)

## Scheduled catch-up queries
<a name="scheduledqueries-patterns-latearrive-schedcatchup"></a>

### Query aggregating data that arrived in time
<a name="scheduledqueries-patterns-latearrive-schedcatchup-1"></a>

Below is a pattern you will see how you can use an automated way to update your aggregates if you have predictable delays in your data arrival. Consider one of the previous examples of a scheduled computation on real-time data below. This scheduled computation refreshes the derived table once every 30 minutes and already accounts for data up to an hour delayed.

```
{
    "Name": "MultiPT30mPerHrPerTimeseriesDPCount",
    "QueryString": "SELECT region, cell, silo, availability_zone, microservice_name, instance_type, os_version, instance_name, process_name, jdk_version, bin(time, 1h) as hour, SUM(CASE WHEN measure_name = 'metrics' THEN 20 ELSE 5 END) as numDataPoints FROM raw_data.devops WHERE time BETWEEN bin(@scheduled_runtime, 1h) - 1h AND @scheduled_runtime + 1h GROUP BY region, cell, silo, availability_zone, microservice_name, instance_type, os_version, instance_name, process_name, jdk_version, bin(time, 1h)",
    "ScheduleConfiguration": {
        "ScheduleExpression": "cron(0/30 * * * ? *)"
    },
    "NotificationConfiguration": {
        "SnsConfiguration": {
            "TopicArn": "******"
        }
    },
    "TargetConfiguration": {
        "TimestreamConfiguration": {
            "DatabaseName": "derived",
            "TableName": "dp_per_timeseries_per_hr",
            "TimeColumn": "hour",
            "DimensionMappings": [
                {
                    "Name": "region",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "cell",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "silo",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "availability_zone",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "microservice_name",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "instance_type",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "os_version",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "instance_name",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "process_name",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "jdk_version",
                    "DimensionValueType": "VARCHAR"
                }
            ],
            "MultiMeasureMappings": {
                "TargetMultiMeasureName": "numDataPoints",
                "MultiMeasureAttributeMappings": [
                    {
                        "SourceColumn": "numDataPoints",
                        "MeasureValueType": "BIGINT"
                    }
                ]
            }
        }
    },
    "ErrorReportConfiguration": {
        "S3Configuration" : {
            "BucketName" : "******",
            "ObjectKeyPrefix": "errors",
            "EncryptionOption": "SSE_S3"
        }
    },
    "ScheduledQueryExecutionRoleArn": "******"
}
```

### Catch-up query updating the aggregates for late arriving data
<a name="scheduledqueries-patterns-latearrive-schedcatchup-2"></a>

Now if you consider the case that your data can be delayed by about 12 hours. Below is a variant of the same query. However, the difference is that it computes the aggregates on data that is delayed by up to 12 hours compared to when the scheduled computation is being triggered. For instance, you see the query in the example below, the time range this query is targeting is between 2h to 14h before when the query is triggered. Moreover, if you notice the schedule expression cron(0 0,12 \$1 \$1 ? \$1), it will trigger the computation at 00:00 UTC and 12:00 UTC every day. Therefore, when the query is triggered on 2021-12-01 00:00:00, then the query updates aggregates in the time range 2021-11-30 10:00:00 to 2021-11-30 22:00:00. Scheduled queries use upsert semantics similar to Timestream for LiveAnalytics's writes where this catch-up query will update the aggregate values with newer values if there is late arriving data in the window or if newer aggregates are found (e.g., a new grouping shows up in this aggregate which was not present when the original scheduled computation was triggered), then the new aggregate will be inserted into the derived table. Similarly, when the next instance is triggered on 2021-12-01 12:00:00, then that instance will update aggregates in the range 2021-11-30 22:00:00 to 2021-12-01 10:00:00.

```
       {
    "Name": "MultiPT12HPerHrPerTimeseriesDPCountCatchUp",
    "QueryString": "SELECT region, cell, silo, availability_zone, microservice_name, instance_type, os_version, instance_name, process_name, jdk_version, bin(time, 1h) as hour, SUM(CASE WHEN measure_name = 'metrics' THEN 20 ELSE 5 END) as numDataPoints FROM raw_data.devops WHERE time BETWEEN bin(@scheduled_runtime, 1h) - 14h AND bin(@scheduled_runtime, 1h) - 2h GROUP BY region, cell, silo, availability_zone, microservice_name, instance_type, os_version, instance_name, process_name, jdk_version, bin(time, 1h)",
    "ScheduleConfiguration": {
        "ScheduleExpression": "cron(0 0,12 * * ? *)"
    },
    "NotificationConfiguration": {
        "SnsConfiguration": {
            "TopicArn": "******"
        }
    },
    "TargetConfiguration": {
        "TimestreamConfiguration": {
            "DatabaseName": "derived",
            "TableName": "dp_per_timeseries_per_hr",
            "TimeColumn": "hour",
            "DimensionMappings": [
                {
                    "Name": "region",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "cell",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "silo",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "availability_zone",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "microservice_name",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "instance_type",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "os_version",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "instance_name",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "process_name",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "jdk_version",
                    "DimensionValueType": "VARCHAR"
                }
            ],
            "MultiMeasureMappings": {
                "TargetMultiMeasureName": "numDataPoints",
                "MultiMeasureAttributeMappings": [
                    {
                        "SourceColumn": "numDataPoints",
                        "MeasureValueType": "BIGINT"
                    }
                ]
            }
        }
    },
    "ErrorReportConfiguration": {
        "S3Configuration" : {
            "BucketName" : "******",
            "ObjectKeyPrefix": "errors",
            "EncryptionOption": "SSE_S3"
        }
    },
    "ScheduledQueryExecutionRoleArn": "******"
}
```

This preceding example is an illustration assuming your late arrival is bounded to 12 hours and it is okay to update the derived table once every 12 hours for data arriving later than the real time window. You can adapt this pattern to update your derived table once every hour so your derived table reflects the late arriving data sooner. Similarly, you can adapt the time range to be older than 12 hours, e.g., a day or even a week or more, to handle predictable late-arriving data.

## Manual executions for unpredictable late arriving data
<a name="scheduledqueries-patterns-latearrive-manual"></a>

There can be instances where you have unpredictable late arriving data or you made changes to the source data and updated some values after the fact. In all such cases, you can manually trigger scheduled queries to update the derived table. Below is an example on how you can achieve this.

Assume that you have the use case where you have the computation written to the derived table dp\$1per\$1timeseries\$1per\$1hr. Your base data in the table devops was updated in the time range 2021-11-30 23:00:00 - 2021-12-01 00:00:00. There are two different scheduled queries that can be used to update this derived table: MultiPT30mPerHrPerTimeseriesDPCount and MultiPT12HPerHrPerTimeseriesDPCountCatchUp. Each scheduled computation you create in Timestream for LiveAnalytics has a unique ARN which you obtain when you create the computation or when you perform a list operation. You can use the ARN for the computation and a value for the parameter @scheduled\$1runtime taken by the query to perform this operation. 

Assume that the computation for MultiPT30mPerHrPerTimeseriesDPCount has an ARN arn\$11 and you want to use this computation to update the derived table. Since the preceding scheduled computation updates the aggregates 1h before and 1hr after the @scheduled\$1runtime value, you can cover the time range for the update (2021-11-30 23:00:00 - 2021-12-01 00:00:00) using a value of 2021-12-01 00:00:00 for the @scheduled\$1runtime parameter. You can use the ExecuteScheduledQuery API to pass the ARN of this computation and the time parameter value in epoch seconds (in UTC) to achieve this. Below is an example using the AWS CLI and you can follow the same pattern using any of the SDKs supported by Timestream for LiveAnalytics.

```
aws timestream-query execute-scheduled-query --scheduled-query-arn arn_1 --invocation-time 1638316800 --profile profile --region us-east-1
```

In the previous example, profile is the AWS profile which has the appropriate privileges to make this API call and 1638316800 corresponds to the epoch second for 2021-12-01 00:00:00. This manual trigger behaves almost like the automated trigger assuming the system triggered this invocation at the desired time period.

If you had an update in a longer time period, say the base data was updated for 2021-11-30 23:00:00 - 2021-12-01 11:00:00, then you can trigger the preceding queries multiple times to cover this entire time range. For instance, you could do six different execution as follows.

```
aws timestream-query execute-scheduled-query --scheduled-query-arn arn_1 --invocation-time 1638316800 --profile profile --region us-east-1

aws timestream-query execute-scheduled-query --scheduled-query-arn arn_1 --invocation-time 1638324000 --profile profile --region us-east-1

aws timestream-query execute-scheduled-query --scheduled-query-arn arn_1 --invocation-time 1638331200 --profile profile --region us-east-1

aws timestream-query execute-scheduled-query --scheduled-query-arn arn_1 --invocation-time 1638338400 --profile profile --region us-east-1

aws timestream-query execute-scheduled-query --scheduled-query-arn arn_1 --invocation-time 1638345600 --profile profile --region us-east-1

aws timestream-query execute-scheduled-query --scheduled-query-arn arn_1 --invocation-time 1638352800 --profile profile --region us-east-1
```

The previous six commands correspond to the scheduled computation invoked at 2021-12-01 00:00:00, 2021-12-01 02:00:00, 2021-12-01 04:0:00, 2021-12-01 06:00:00, 2021-12-01 08:00:00, and 2021-12-01 10:00:

Alternatively, you can use the computation MultiPT12HPerHrPerTimeseriesDPCountCatchUp triggered at 2021-12-01 13:00:00 for one execution to update the aggregates for the entire 12 hour time range. For instance, if arn\$12 is the ARN for that computation, you can execute the following command from CLI.

```
aws timestream-query execute-scheduled-query --scheduled-query-arn arn_2 --invocation-time 1638363600 --profile profile --region us-east-1
```

It is worth noting that for a manual trigger, you can use a timestamp for the invocation-time parameter that does not need to be aligned with that automated trigger timestamps. For instance, in the previous example, you triggered the computation at time 2021-12-01 13:00:00 even though the automated schedule only triggers at timestamps 2021-12-01 10:00:00, 2021-12-01 12:00:00, and 2021-12-02 00:00:00. Timestream for LiveAnalytics provides you with the flexibility to trigger it with appropriate values as needed for your manual operations.

Following are a few important considerations when using the ExecuteScheduledQuery API.
+ If you are triggering multiple of these invocations, you need to make sure that these invocations do not generate results in overlapping time ranges. For instance, in the previous examples, there were six invocations. Each invocation covers 2 hours of time range, and hence the invocation timestamps were spread out by two hours each to avoid any overlap in the updates. This ensures that the data in the derived table ends up in a state that matches are aggregates from the source table. If you cannot ensure non-overlapping time ranges, then make sure these the executions are triggered sequentially one after the other. If you trigger multiple executions concurrently which overlap in their time ranges, then you can see trigger failures where you might see version conflicts in the error reports for these executions. Results generated by a scheduled query invocation are assigned a version based on when the invocation was triggered. Therefore, rows generated by newer invocations have higher versions. A higher version record can overwrite a lower version record. For automatically-triggered scheduled queries, Timestream for LiveAnalytics automatically manages the schedules so that you don't see these issues even if the subsequent invocations have overlapping time ranges.
+ noted earlier, you can trigger the invocations with any timestamp value for @scheduled\$1runtime. So it is your responsibility to appropriately set the values so the appropriate time ranges are updated in the derived table corresponding to the ranges where data was updated in the source table.
+ You can also use these manual trigger for scheduled queries that are in the DISABLED state. This allows you to define special queries that are not executed in an automated schedule, since they are in the DISABLED state. Rather, you can use the manual triggers on them to manage data corrections or late arrival use cases.

# Back-filling historical pre-computations
<a name="scheduledqueries-patterns-backfilling"></a>

When you create a scheduled computation, Timestream for LiveAnalytics manages executions of the queries moving forward where the refresh is governed by the schedule expression you provide. Depending of how much historical data your source table, you may want to update your derived table with aggregates corresponding to the historical data. You can use the preceding logic for manual triggers to back-fill the historical aggregates.

For instance, if we consider the derived table per\$1timeseries\$1lastpoint\$1pt1d, then the scheduled computation is updated once a day for the past day. If your source table has a year of data, you can use the ARN for this scheduled computation and trigger it manually for every day up to a year old so that the derived table has all the historical queries populated. Notes that all the caveats for manual triggers apply here. Moreover, if the derived table is set up in a way that the historical ingestion will write to magnetic store on the derived table, be aware of the [best practices](https://docs.aws.amazon.com/timestream/latest/developerguide/best-practices.html) and [limits for writes](https://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html) to the magnetic store.

# Scheduled query examples
<a name="scheduledqueries-examples"></a>

This section contains examples of how you can use Timestream for LiveAnalytics's Scheduled Queries to optimize the costs and dashboard load times when visualizing fleet-wide statistics effectively monitor your fleet of devices. Scheduled Queries in Timestream for LiveAnalytics allow you to express your queries using the full SQL surface area of Timestream for LiveAnalytics. Your query can include one or more source tables, perform aggregations or any other query allowed by Timestream for LiveAnalytics's SQL language, and then store the results of the query in another destination table in Timestream for LiveAnalytics.

This section refers to the target table of a scheduled query as a *derived table*.

As an example, we will use a DevOps application where you are monitoring a large fleet of servers that are deployed across multiple deployments (such as regions, cells, and silos), multiple microservices, and you're tracking the fleet-wide statistics using Timestream for LiveAnalytics. The example schema we will use is described in [Scheduled Queries Sample Schema](https://docs.aws.amazon.com/timestream/latest/developerguide/scheduledqueries-common-schema-example.html). 

The following scenarios will be described.
+ How to convert a dashboard, plotting aggregated statistics from the raw data you ingest into Timestream for LiveAnalytics into a scheduled query and then how to use your pre-computed aggregates to create a new dashboard showing aggregate statistics.
+ How to combine scheduled queries to get an aggregate view and the raw granular data, to drill down into details. This allows you to store and analyze the raw data while optimizing your common fleet-wide operations using scheduled queries.
+ How to optimize costs using scheduled queries by finding which aggregates are used in multiple dashboards and have the same scheduled query populate multiple panels in the same or multiple dashboards.

**Topics**
+ [Converting an aggregate dashboard to scheduled query](scheduledqueries-example1.md)
+ [Using scheduled queries and raw data for drill downs](scheduledqueries-example2.md)
+ [Optimizing costs by sharing scheduled query across dashboards](scheduledqueries-example3.md)
+ [Comparing a query on a base table with a query of scheduled query results](scheduledqueries-example4-clickstream.md)

# Converting an aggregate dashboard to scheduled query
<a name="scheduledqueries-example1"></a>

Assume you are computing the fleet-wide statistics such as host counts in the fleet by the five microservices and by the six regions where your service is deployed. From the snapshot below, you can see there are 500K servers emitting metrics, and some of the bigger regions (e.g., us-east-1) have >200K servers.

Computing these aggregates, where you are computing distinct instance names over hundreds of gigabytes of data can result in query latency of tens of seconds, in addition to the cost of scanning the data.

![\[Instance counts for microservices: apollo and zeus 150k, hercules 100k, athena and demeter 50k each.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/sched_query_ex1_img1.png)


**Original dashboard query**

The aggregate shown in the dasboard panel is computed, from raw data, using the query below. The query uses multiple SQL constructs, such as distinct counts and multiple aggregation functions.

```
SELECT CASE WHEN microservice_name = 'apollo' THEN num_instances ELSE NULL END AS apollo,
    CASE WHEN microservice_name = 'athena' THEN num_instances ELSE NULL END AS athena,
    CASE WHEN microservice_name = 'demeter' THEN num_instances ELSE NULL END AS demeter,
    CASE WHEN microservice_name = 'hercules' THEN num_instances ELSE NULL END AS hercules,
    CASE WHEN microservice_name = 'zeus' THEN num_instances ELSE NULL END AS zeus
FROM (
    SELECT microservice_name, SUM(num_instances) AS num_instances
    FROM (
        SELECT microservice_name, COUNT(DISTINCT instance_name) as num_instances
        FROM "raw_data"."devops"
        WHERE time BETWEEN from_milliseconds(1636526171043) AND from_milliseconds(1636612571043)
            AND measure_name = 'metrics'
        GROUP BY region, cell, silo, availability_zone, microservice_name
    )
    GROUP BY microservice_name
)
```

**Converting to a scheduled query**

The previous query can be converted into a scheduled query as follows. You first compute the distinct host names within a given deployment in a region, cell, silo, availability zone and microservice. Then you add up the hosts to compute a per hour per microservice host count. By using the `@scheduled_runtime` parameter supported by the scheduled queries, you can recompute it for the past hour when the query is invoked. The `bin(@scheduled_runtime, 1h)` in the `WHERE` clause of the inner query ensures that even if the query is scheduled at a time in the middle of the hour, you still get the data for the full hour.

Even though the query computes hourly aggregates, as you will see in the scheduled computation configuration, it is set up to refresh every half hour so that you get updates in your derived table sooner. You can tune that based on your freshness requirements, e.g., recompute the aggregates every 15 minutes or recompute it at the hour boundaries.

```
SELECT microservice_name, hour, SUM(num_instances) AS num_instances    
FROM (
        SELECT microservice_name, bin(time, 1h) AS hour, 
            COUNT(DISTINCT instance_name) as num_instances
       FROM raw_data.devops        
       WHERE time BETWEEN bin(@scheduled_runtime, 1h) - 1h AND @scheduled_runtime        
           AND measure_name = 'metrics'        
       GROUP BY region, cell, silo, availability_zone, microservice_name, bin(time, 1h)    
     )    
GROUP BY microservice_name, hour
```

```
{
    "Name": "MultiPT30mHostCountMicroservicePerHr",
    "QueryString": "SELECT microservice_name, hour, SUM(num_instances) AS num_instances    FROM (        SELECT microservice_name, bin(time, 1h) AS hour, COUNT(DISTINCT instance_name) as num_instances        FROM raw_data.devops        WHERE time BETWEEN bin(@scheduled_runtime, 1h) - 1h AND @scheduled_runtime            AND measure_name = 'metrics'        GROUP BY region, cell, silo, availability_zone, microservice_name, bin(time, 1h)    )    GROUP BY microservice_name, hour",
    "ScheduleConfiguration": {
        "ScheduleExpression": "cron(0/30 * * * ? *)"
    },
    "NotificationConfiguration": {
        "SnsConfiguration": {
            "TopicArn": "******"
        }
    },
    "TargetConfiguration": {
        "TimestreamConfiguration": {
            "DatabaseName": "derived",
            "TableName": "host_count_pt1h",
            "TimeColumn": "hour",
            "DimensionMappings": [
                {
                    "Name": "microservice_name",
                    "DimensionValueType": "VARCHAR"
                }
            ],
            "MultiMeasureMappings": {
                "TargetMultiMeasureName": "num_instances",
                "MultiMeasureAttributeMappings": [
                    {
                        "SourceColumn": "num_instances",
                        "MeasureValueType": "BIGINT"
                    }
                ]
            }
        }
    },
    "ErrorReportConfiguration": {
        "S3Configuration" : {
            "BucketName" : "******",
            "ObjectKeyPrefix": "errors",
            "EncryptionOption": "SSE_S3"
        }
    },
    "ScheduledQueryExecutionRoleArn": "******"
}
```

**Using the pre-computed results in a new dashboard**

You will now see how to create your aggregate view dashboard using the derived table from the scheduled query you created. From the dashboard snapshot, you will also be able to validate that the aggregates computed from the derived table and the base table also match. Once you create the dashboards using the derived tables, you will notice the significantly faster load time and lower costs of using the derived tables compared to computing these aggregates from the raw data. Below is a snapshot of the dashboard using pre-computed data, and the query used to render this panel using pre-computed data stored in the table "derived"."host\$1count\$1pt1h". Note that the structure of the query is very similar to the query that was used in the dashboard on raw data, except that is it using the derived table which already computes the distinct counts which this query is aggregating. 

![\[Instance count by microservice showing values for apollo, athena, demeter, hercules, and zeus.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/sched_query_ex1_img2.png)


```
SELECT CASE WHEN microservice_name = 'apollo' THEN num_instances ELSE NULL END AS apollo,
    CASE WHEN microservice_name = 'athena' THEN num_instances ELSE NULL END AS athena,
    CASE WHEN microservice_name = 'demeter' THEN num_instances ELSE NULL END AS demeter,
    CASE WHEN microservice_name = 'hercules' THEN num_instances ELSE NULL END AS hercules,
    CASE WHEN microservice_name = 'zeus' THEN num_instances ELSE NULL END AS zeus
FROM (
    SELECT microservice_name, AVG(num_instances) AS num_instances
    FROM (
        SELECT microservice_name, bin(time, 1h), SUM(num_instances) as num_instances
        FROM "derived"."host_count_pt1h"
        WHERE time BETWEEN from_milliseconds(1636567785421) AND from_milliseconds(1636654185421)
            AND measure_name = 'num_instances'
        GROUP BY microservice_name, bin(time, 1h)
    )
    GROUP BY microservice_name
)
```

# Using scheduled queries and raw data for drill downs
<a name="scheduledqueries-example2"></a>

You can use the aggregated statistics across your fleet to identify areas that need drill downs and then use the raw data to drill down into granular data to get deeper insights.

In this example, you will see how you can use aggregate dashboard to identify any deployment (a deployment is for a given microservice within a given region, cell, silo, and availability zone) which seems to have higher CPU utilization compared to other deployments. You can then drill down to get a better understanding using the raw data. Since these drill downs might be infrequent and only access data relevant to the deployment, you can use the raw data for this analysis and do not need to use scheduled queries. 

**Per deployment drill down**

The dashboard below provides drill down into more granular and server-level statistics within a given deployment. To help you drill down into the different parts of your fleet, this dashboard uses variables such as region, cell, silo, microservice, and availability\$1zone. It then shows some aggregate statistics for that deployment.

![\[Dashboard showing deployment statistics with filters for region, cell, silo, and other parameters.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/sched_query_ex2_img1.png)


![\[CPU distribution graph showing consistent patterns for avg, p90, p95, and p99 values over 24 hours.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/sched_query_ex2_img2.png)


In the query below, you can see that the values chosen in the drop down of the variables are used as predicates in the `WHERE` clause of the query, which allows you to only focus on the data for the deployment. And then the panel plots the aggregated CPU metrics for instances in that deployment. You can use the raw data to perform this drill down with interactive query latency to derive deeper insights.

```
SELECT bin(time, 5m) as minute,
    ROUND(AVG(cpu_user), 2) AS avg_value,
    ROUND(APPROX_PERCENTILE(cpu_user, 0.9), 2) AS p90_value,
    ROUND(APPROX_PERCENTILE(cpu_user, 0.95), 2) AS p95_value,
    ROUND(APPROX_PERCENTILE(cpu_user, 0.99), 2) AS p99_value
FROM "raw_data"."devops"
WHERE time BETWEEN from_milliseconds(1636527099476) AND from_milliseconds(1636613499476)
    AND region = 'eu-west-1'
    AND cell = 'eu-west-1-cell-10'
    AND silo = 'eu-west-1-cell-10-silo-1'
    AND microservice_name = 'demeter'
    AND availability_zone = 'eu-west-1-3'
    AND measure_name = 'metrics'
GROUP BY bin(time, 5m)
ORDER BY 1
```

**Instance-level statistics**

This dashboard further computes another variable that also lists the servers/instances with high CPU utilization, sorted in descending order of utilization. The query used to compute this variable is displayed below.

```
WITH microservice_cell_avg AS (
    SELECT AVG(cpu_user) AS microservice_avg_metric
    FROM "raw_data"."devops"
    WHERE $__timeFilter
        AND measure_name = 'metrics'
        AND region = '${region}'
        AND cell = '${cell}'
        AND silo = '${silo}'
        AND availability_zone = '${availability_zone}'
        AND microservice_name = '${microservice}'
), instance_avg AS (
    SELECT instance_name,
        AVG(cpu_user) AS instance_avg_metric
    FROM "raw_data"."devops"
    WHERE $__timeFilter
        AND measure_name = 'metrics'
        AND region = '${region}'
        AND cell = '${cell}'
        AND silo = '${silo}'
        AND microservice_name = '${microservice}'
        AND availability_zone = '${availability_zone}'
    GROUP BY availability_zone, instance_name
) 
SELECT i.instance_name
FROM instance_avg i CROSS JOIN microservice_cell_avg m 
WHERE i.instance_avg_metric > (1 + ${utilization_threshold}) * m.microservice_avg_metric
ORDER BY i.instance_avg_metric DESC
```

In the preceding query, the variable is dynamically recalculated depending on the values chosen for the other variables. Once the variable is populated for a deployment, you can pick individual instances from the list to further visualize the metrics from that instance. You can pick the different instances from the drop down of the instance names as seen from the snapshot below.

![\[List of Amazon Web Services (AWS) resource identifiers for Demeter instances in eu-west-1 region.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/sched_query_ex2_img3.png)


![\[Dashboard showing CPU utilization, memory usage, GC pause events, and disk I/O metrics for an AWS instance.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/sched_query_ex2_img4.png)


Preceding panels show the statistics for the instance that is selected and below are the queries used to fetch these statistics.

```
SELECT BIN(time, 30m) AS time_bin, 
    AVG(cpu_user) AS avg_cpu,
    ROUND(APPROX_PERCENTILE(cpu_user, 0.99), 2) as p99_cpu
FROM "raw_data"."devops"
WHERE time BETWEEN from_milliseconds(1636527099477) AND from_milliseconds(1636613499477)
    AND measure_name = 'metrics'
    AND region = 'eu-west-1' AND cell = 'eu-west-1-cell-10' AND silo = 'eu-west-1-cell-10-silo-1' 
    AND availability_zone = 'eu-west-1-3' AND microservice_name = 'demeter' 
    AND instance_name = 'i-zaZswmJk-demeter-eu-west-1-cell-10-silo-1-00000272.amazonaws.com'
GROUP BY BIN(time, 30m)
ORDER BY time_bin desc
```

```
SELECT BIN(time, 30m) AS time_bin, 
    AVG(memory_used) AS avg_memory,
    ROUND(APPROX_PERCENTILE(memory_used, 0.99), 2) as p99_memory
FROM "raw_data"."devops"
WHERE time BETWEEN from_milliseconds(1636527099477) AND from_milliseconds(1636613499477)
    AND measure_name = 'metrics'
    AND region = 'eu-west-1' AND cell = 'eu-west-1-cell-10' AND silo = 'eu-west-1-cell-10-silo-1' 
    AND availability_zone = 'eu-west-1-3' AND microservice_name = 'demeter' 
    AND instance_name = 'i-zaZswmJk-demeter-eu-west-1-cell-10-silo-1-00000272.amazonaws.com'
GROUP BY BIN(time, 30m)
ORDER BY time_bin desc
```

```
SELECT COUNT(gc_pause)
FROM "raw_data"."devops"
WHERE time BETWEEN from_milliseconds(1636527099477) AND from_milliseconds(1636613499478)
    AND measure_name = 'events'
    AND region = 'eu-west-1' AND cell = 'eu-west-1-cell-10' AND silo = 'eu-west-1-cell-10-silo-1' 
    AND availability_zone = 'eu-west-1-3' AND microservice_name = 'demeter' 
    AND instance_name = 'i-zaZswmJk-demeter-eu-west-1-cell-10-silo-1-00000272.amazonaws.com'
```

```
SELECT avg(gc_pause) as avg, round(approx_percentile(gc_pause, 0.99), 2) as p99
FROM "raw_data"."devops"
WHERE time BETWEEN from_milliseconds(1636527099478) AND from_milliseconds(1636613499478)
    AND measure_name = 'events'
    AND region = 'eu-west-1' AND cell = 'eu-west-1-cell-10' AND silo = 'eu-west-1-cell-10-silo-1' 
    AND availability_zone = 'eu-west-1-3' AND microservice_name = 'demeter' 
    AND instance_name = 'i-zaZswmJk-demeter-eu-west-1-cell-10-silo-1-00000272.amazonaws.com'
```

```
SELECT BIN(time, 30m) AS time_bin, 
    AVG(disk_io_reads) AS avg,
    ROUND(APPROX_PERCENTILE(disk_io_reads, 0.99), 2) as p99
FROM "raw_data"."devops"
WHERE time BETWEEN from_milliseconds(1636527099478) AND from_milliseconds(1636613499478)
    AND measure_name = 'metrics'
    AND region = 'eu-west-1' AND cell = 'eu-west-1-cell-10' AND silo = 'eu-west-1-cell-10-silo-1' 
    AND availability_zone = 'eu-west-1-3' AND microservice_name = 'demeter' 
    AND instance_name = 'i-zaZswmJk-demeter-eu-west-1-cell-10-silo-1-00000272.amazonaws.com'
GROUP BY BIN(time, 30m)
ORDER BY time_bin desc
```

# Optimizing costs by sharing scheduled query across dashboards
<a name="scheduledqueries-example3"></a>

In this example, we will see a scenario where multiple dashboard panels display variations of similar information (finding high CPU hosts and fraction of fleet with high CPU utilization) and how you can use the same scheduled query to pre-compute results which are then used to populate multiple panels. This reuse further optimizes your costs where instead of using different scheduled queries, one for each panel, you use only owner. 

## Dashboard panels with raw data
<a name="scheduledqueries-example3-dashboard-raw"></a>

**CPU utilization per region per microservice**

The first panel computes the instances whose avg CPU utilization is a threshold below or above the above CPU utilization for given deployment within a region, cell, silo, availability zone, and microservice. It then sorts the region and microservice which has the highest percentage of hosts with high utilization. It helps identify how hot the servers of a specific deployment are running, and then subsequently drill down to better understand the issues. 

The query for the panel demonstrates the flexibility of Timestream for LiveAnalytics's SQL support to perform complex analytical tasks with common table expressions, window functions, joins, and so on. 

![\[Table showing CPU utilization data for microservices across different regions.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/sched_query_ex3_img1.png)


*Query*:

```
WITH microservice_cell_avg AS (
    SELECT region, cell, silo, availability_zone, microservice_name, AVG(cpu_user) AS microservice_avg_metric
    FROM "raw_data"."devops"
    WHERE time BETWEEN from_milliseconds(1636526593876) AND from_milliseconds(1636612993876)
        AND measure_name = 'metrics'
    GROUP BY region, cell, silo, availability_zone, microservice_name
), instance_avg AS (
    SELECT region, cell, silo, availability_zone, microservice_name, instance_name,
        AVG(cpu_user) AS instance_avg_metric
    FROM "raw_data"."devops"
    WHERE time BETWEEN from_milliseconds(1636526593876) AND from_milliseconds(1636612993876)
        AND measure_name = 'metrics'
    GROUP BY region, cell, silo, availability_zone, microservice_name, instance_name
), instances_above_threshold AS (
  SELECT i.*,
    CASE WHEN i.instance_avg_metric > (1 + 0.2) * m.microservice_avg_metric THEN 1 ELSE 0 END AS high_utilization,
    CASE WHEN i.instance_avg_metric < (1 - 0.2) * m.microservice_avg_metric THEN 1 ELSE 0 END AS low_utilization
  FROM instance_avg i INNER JOIN microservice_cell_avg m 
    ON i.region = m.region AND i.cell = m.cell AND i.silo = m.silo AND i.availability_zone = m.availability_zone
      AND m.microservice_name = i.microservice_name
), per_deployment_high AS (
SELECT region, microservice_name, COUNT(*) AS num_hosts, SUM(high_utilization) AS high_utilization_hosts, SUM(low_utilization) AS low_utilization_hosts,
    ROUND(SUM(high_utilization) * 100.0 / COUNT(*), 0) AS percent_high_utilization_hosts,
    ROUND(SUM(low_utilization) * 100.0 / COUNT(*), 0) AS percent_low_utilization_hosts
FROM instances_above_threshold
GROUP BY region, microservice_name
), per_region_ranked AS (
    SELECT *,
        DENSE_RANK() OVER (PARTITION BY region ORDER BY percent_high_utilization_hosts DESC, high_utilization_hosts DESC) AS rank
    FROM per_deployment_high
)
SELECT *
FROM per_region_ranked
WHERE rank <= 2
ORDER BY percent_high_utilization_hosts desc, rank asc
```

**Drill down into a microservice to find hot spots**

The next dashboard allows you to drill deeper into one of the microservices to find out the specific region, cell, and silo for that microservice is running what fraction of fraction of its fleet at higher CPU utilization. For instance, in the fleet wide dashboard you saw the microservice demeter show up in the top few ranked positions, so in this dashboard, you want to drill deeper into that microservice. 

This dashboard uses a variable to pick microservice to drill down into, and the values of the variable is populated using unique values of the dimension. Once you pick the microservice, the rest of the dashboard refreshes. 

As you see below, the first panel plots the percentage of hosts in a deployment (a region, cell, and silo for a microservice) over time, and the corresponding query which is used to plot the dashboard. This plot itself identifies a specific deployment having higher percentage of hosts with high CPU.

![\[Dropdown menu showing "microservice", "demeter", "topk", and "2" options.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/sched_query_ex3_img2.png)


![\[Graph showing deployments with high CPU utilization over time, with multiple flat lines.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/sched_query_ex3_img3.png)


*Query*:

```
WITH microservice_cell_avg AS (
    SELECT region, cell, silo, availability_zone, microservice_name, bin(time, 1h) as hour, AVG(cpu_user) AS microservice_avg_metric
    FROM "raw_data"."devops"
    WHERE time BETWEEN from_milliseconds(1636526898831) AND from_milliseconds(1636613298831)
        AND measure_name = 'metrics'
        AND microservice_name = 'demeter'
    GROUP BY region, cell, silo, availability_zone, microservice_name, bin(time, 1h)
), instance_avg AS (
    SELECT region, cell, silo, availability_zone, microservice_name, instance_name, bin(time, 1h) as hour,
        AVG(cpu_user) AS instance_avg_metric
    FROM "raw_data"."devops"
    WHERE time BETWEEN from_milliseconds(1636526898831) AND from_milliseconds(1636613298831)
        AND measure_name = 'metrics'
        AND microservice_name = 'demeter'
    GROUP BY region, cell, silo, availability_zone, microservice_name, instance_name, bin(time, 1h)
), instances_above_threshold AS (
  SELECT i.*,
    CASE WHEN i.instance_avg_metric > (1 + 0.2) * m.microservice_avg_metric THEN 1 ELSE 0 END AS high_utilization
  FROM instance_avg i INNER JOIN microservice_cell_avg m 
    ON i.region = m.region AND i.cell = m.cell AND i.silo = m.silo AND i.availability_zone = m.availability_zone
      AND m.microservice_name = i.microservice_name AND m.hour = i.hour
), high_utilization_percent AS (
    SELECT region, cell, silo, microservice_name, hour, COUNT(*) AS num_hosts, SUM(high_utilization) AS high_utilization_hosts,
        ROUND(SUM(high_utilization) * 100.0 / COUNT(*), 0) AS percent_high_utilization_hosts
    FROM instances_above_threshold
    GROUP BY region, cell, silo, microservice_name, hour
), high_utilization_ranked AS (
    SELECT region, cell, silo, microservice_name, 
        DENSE_RANK() OVER (PARTITION BY region ORDER BY AVG(percent_high_utilization_hosts) desc, AVG(high_utilization_hosts) desc) AS rank
    FROM high_utilization_percent 
    GROUP BY region, cell, silo, microservice_name
)
SELECT hup.silo, CREATE_TIME_SERIES(hour, hup.percent_high_utilization_hosts) AS percent_high_utilization_hosts
FROM high_utilization_percent hup INNER JOIN high_utilization_ranked hur
    ON hup.region = hur.region AND hup.cell = hur.cell AND hup.silo = hur.silo AND hup.microservice_name = hur.microservice_name
WHERE rank <= 2
GROUP BY hup.region, hup.cell, hup.silo
ORDER BY hup.silo
```

## Converting into a single scheduled query enabling reuse
<a name="scheduledqueries-example3-query-reuse"></a>

It is important to note that a similar computation is done across the different panels across the two dashboards. You can define a separate scheduled query for each panel. Here you will see how you can further optimize your costs by defining one scheduled query who results can be used to render all the three panels. 

Following is the query that captures the aggregates that are computed and used for all the different panels. You will observe several important aspects in the definition of this scheduled query.
+ The flexibility and the power of the SQL surface area supported by scheduled queries, where you can use common table expressions, joins, case statements, etc. 
+ You can using one scheduled query to compute the statistics at a finer granularity than a specific dashboard might need, and for all values that a dashboard might use for different variables. For instance, you will see the aggregates are computed across a region, cell, silo, and microservice. Therefore, you can combine these to create region-level, or region, and microservice-level aggregates. Similarly, the same query computes the aggregates for all regions, cells, silos, and microservices. It allows you to apply filters on these columns to obtain the aggregates for a subset of the values. For instance, you can compute the aggregates for any one region, say us-east-1, or any one microservice say demeter or drill down into a specific deployment within a region, cell, silo, and microservice. This approach further optimizes your costs of maintaining the pre-computed aggregates. 

```
WITH microservice_cell_avg AS (
    SELECT region, cell, silo, availability_zone, microservice_name, bin(time, 1h) as hour, AVG(cpu_user) AS microservice_avg_metric    
    FROM raw_data.devops    
    WHERE time BETWEEN bin(@scheduled_runtime, 1h) - 1h AND bin(@scheduled_runtime, 1h) + 1h
        AND measure_name = 'metrics'    
    GROUP BY region, cell, silo, availability_zone, microservice_name, bin(time, 1h)    
), instance_avg AS (
    SELECT region, cell, silo, availability_zone, microservice_name, instance_name, bin(time, 1h) as hour,
        AVG(cpu_user) AS instance_avg_metric    
   FROM raw_data.devops    
   WHERE time BETWEEN bin(@scheduled_runtime, 1h) - 1h AND bin(@scheduled_runtime, 1h) + 1h
       AND measure_name = 'metrics'    
   GROUP BY region, cell, silo, availability_zone, microservice_name, instance_name, bin(time, 1h)    
), instances_above_threshold AS (
    SELECT i.*,
        CASE WHEN i.instance_avg_metric > (1 + 0.2) * m.microservice_avg_metric THEN 1 ELSE 0 END AS high_utilization,    
        CASE WHEN i.instance_avg_metric < (1 - 0.2) * m.microservice_avg_metric THEN 1 ELSE 0 END AS low_utilization    
   FROM instance_avg i INNER JOIN microservice_cell_avg m
       ON i.region = m.region AND i.cell = m.cell AND i.silo = m.silo AND i.availability_zone = m.availability_zone
           AND m.microservice_name = i.microservice_name AND m.hour = i.hour    
)     
SELECT region, cell, silo, microservice_name, hour,
     COUNT(*) AS num_hosts, SUM(high_utilization) AS high_utilization_hosts, SUM(low_utilization) AS low_utilization_hosts    
FROM instances_above_threshold GROUP BY region, cell, silo, microservice_name, hour
```

The following is a scheduled query definition for the previous query. The schedule expression, it is configured to refresh every 30 mins, and refreshes the data for up to an hour back, again using the bin(@scheduled\$1runtime, 1h) construct to get the full hour's events. Depending on your application's freshness requirements, you can configure it to refresh more or less frequently. By using WHERE time BETWEEN bin(@scheduled\$1runtime, 1h) - 1h AND bin(@scheduled\$1runtime, 1h) \$1 1h, we can ensure that even if you are refreshing once every 15 minutes, you will get the full hour's data for the current hour and the previous hour. 

Later on, you will see how the three panels use these aggregates written to table deployment\$1cpu\$1stats\$1per\$1hr to visualize the metrics that are relevant to the panel.

```
{
    "Name": "MultiPT30mHighCpuDeploymentsPerHr",
    "QueryString": "WITH microservice_cell_avg AS (    SELECT region, cell, silo, availability_zone, microservice_name, bin(time, 1h) as hour, AVG(cpu_user) AS microservice_avg_metric    FROM raw_data.devops    WHERE time BETWEEN bin(@scheduled_runtime, 1h) - 1h AND bin(@scheduled_runtime, 1h) + 1h    AND measure_name = 'metrics'    GROUP BY region, cell, silo, availability_zone, microservice_name, bin(time, 1h)    ), instance_avg AS (    SELECT region, cell, silo, availability_zone, microservice_name, instance_name, bin(time, 1h) as hour,    AVG(cpu_user) AS instance_avg_metric    FROM raw_data.devops    WHERE time BETWEEN bin(@scheduled_runtime, 1h) - 1h AND bin(@scheduled_runtime, 1h) + 1h    AND measure_name = 'metrics'    GROUP BY region, cell, silo, availability_zone, microservice_name, instance_name, bin(time, 1h)    ), instances_above_threshold AS (    SELECT i.*,    CASE WHEN i.instance_avg_metric > (1 + 0.2) * m.microservice_avg_metric THEN 1 ELSE 0 END AS high_utilization,    CASE WHEN i.instance_avg_metric < (1 - 0.2) * m.microservice_avg_metric THEN 1 ELSE 0 END AS low_utilization    FROM instance_avg i INNER JOIN microservice_cell_avg m    ON i.region = m.region AND i.cell = m.cell AND i.silo = m.silo AND i.availability_zone = m.availability_zone    AND m.microservice_name = i.microservice_name AND m.hour = i.hour    )     SELECT region, cell, silo, microservice_name, hour,         COUNT(*) AS num_hosts, SUM(high_utilization) AS high_utilization_hosts, SUM(low_utilization) AS low_utilization_hosts    FROM instances_above_threshold GROUP BY region, cell, silo, microservice_name, hour",
    "ScheduleConfiguration": {
        "ScheduleExpression": "cron(0/30 * * * ? *)"
    },
    "NotificationConfiguration": {
        "SnsConfiguration": {
            "TopicArn": "******"
        }
    },
    "TargetConfiguration": {
        "TimestreamConfiguration": {
            "DatabaseName": "derived",
            "TableName": "deployment_cpu_stats_per_hr",
            "TimeColumn": "hour",
            "DimensionMappings": [
                {
                    "Name": "region",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "cell",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "silo",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "Name": "microservice_name",
                    "DimensionValueType": "VARCHAR"
                }
            ],
            "MultiMeasureMappings": {
                "TargetMultiMeasureName": "cpu_user",
                "MultiMeasureAttributeMappings": [
                    {
                        "SourceColumn": "num_hosts",
                        "MeasureValueType": "BIGINT"
                    },
                    {
                        "SourceColumn": "high_utilization_hosts",
                        "MeasureValueType": "BIGINT"
                    },
                    {
                        "SourceColumn": "low_utilization_hosts",
                        "MeasureValueType": "BIGINT"
                    }
                ]
            }
        }
    },
    "ErrorReportConfiguration": {
        "S3Configuration" : {
            "BucketName" : "******",
            "ObjectKeyPrefix": "errors",
            "EncryptionOption": "SSE_S3"
        }
    },
    "ScheduledQueryExecutionRoleArn": "******"
}
```

## Dashboard from pre-computed results
<a name="scheduledqueries-example3-dashboard-precompute"></a>

**High CPU utilization hosts**

For the high utilization hosts, you will see how the different panels use the data from deployment\$1cpu\$1stats\$1per\$1hr to compute different aggregates necessary for the panels. For instance, this panels provides region-level information, so it reports aggregates grouped by region and microservice, without filtering any region or microservice. 

![\[Table showing microservice utilization stats across regions, with high and low host percentages.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/sched_query_ex3_img4.png)


```
WITH per_deployment_hosts AS (
    SELECT region, cell, silo, microservice_name, 
        AVG(num_hosts) AS num_hosts, 
        AVG(high_utilization_hosts) AS high_utilization_hosts, 
        AVG(low_utilization_hosts) AS low_utilization_hosts
    FROM "derived"."deployment_cpu_stats_per_hr"
    WHERE time BETWEEN from_milliseconds(1636567785437) AND from_milliseconds(1636654185437)
        AND measure_name = 'cpu_user'
    GROUP BY region, cell, silo, microservice_name
), per_deployment_high AS (
    SELECT region, microservice_name,
        SUM(num_hosts) AS num_hosts, 
        ROUND(SUM(high_utilization_hosts), 0) AS high_utilization_hosts,
        ROUND(SUM(low_utilization_hosts),0) AS low_utilization_hosts,
        ROUND(SUM(high_utilization_hosts) * 100.0 / SUM(num_hosts)) AS percent_high_utilization_hosts,
        ROUND(SUM(low_utilization_hosts) * 100.0 / SUM(num_hosts)) AS percent_low_utilization_hosts
    FROM per_deployment_hosts
    GROUP BY region, microservice_name
), 
per_region_ranked AS (
    SELECT *,
        DENSE_RANK() OVER (PARTITION BY region ORDER BY percent_high_utilization_hosts DESC, high_utilization_hosts DESC) AS rank
    FROM per_deployment_high
)
SELECT *
FROM per_region_ranked
WHERE rank <= 2
ORDER BY percent_high_utilization_hosts desc, rank asc
```

**Drill down into a microservice to find high CPU usage deploymentss**

This next example again uses the deployment\$1cpu\$1stats\$1per\$1hr derived table, but now applies a filter for a specific microservice (demeter in this example, since it reported high utilization hosts in the aggregate dashboard). This panel tracks the percentage of high CPU utilization hosts over time.

![\[Graph showing consistent high CPU utilization percentages for multiple deployments over 24 hours.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/sched_query_ex3_img5.png)


```
WITH high_utilization_percent AS (
    SELECT region, cell, silo, microservice_name, bin(time, 1h) AS hour, MAX(num_hosts) AS num_hosts, 
        MAX(high_utilization_hosts) AS high_utilization_hosts,
        ROUND(MAX(high_utilization_hosts) * 100.0 / MAX(num_hosts)) AS percent_high_utilization_hosts
    FROM "derived"."deployment_cpu_stats_per_hr"
    WHERE time BETWEEN from_milliseconds(1636525800000) AND from_milliseconds(1636612200000)
        AND measure_name = 'cpu_user'
        AND microservice_name = 'demeter'
    GROUP BY region, cell, silo, microservice_name, bin(time, 1h)
), high_utilization_ranked AS (
    SELECT region, cell, silo, microservice_name, 
        DENSE_RANK() OVER (PARTITION BY region ORDER BY AVG(percent_high_utilization_hosts) desc, AVG(high_utilization_hosts) desc) AS rank
    FROM high_utilization_percent 
    GROUP BY region, cell, silo, microservice_name
)
SELECT hup.silo, CREATE_TIME_SERIES(hour, hup.percent_high_utilization_hosts) AS percent_high_utilization_hosts
FROM high_utilization_percent hup INNER JOIN high_utilization_ranked hur
    ON hup.region = hur.region AND hup.cell = hur.cell AND hup.silo = hur.silo AND hup.microservice_name = hur.microservice_name
WHERE rank <= 2
GROUP BY hup.region, hup.cell, hup.silo
ORDER BY hup.silo
```

# Comparing a query on a base table with a query of scheduled query results
<a name="scheduledqueries-example4-clickstream"></a>

In this Timestream query example, we use the following schema, example queries, and outputs to compare a query on a base table with a query on a derived table of scheduled query results. With a well-planned scheduled query, you can get a derived table with fewer rows and other characteristics that can lead to faster queries than would be possible on the original base table. 

For a video that describes this scenario, see [Improve query performance and reduce cost using scheduled queries in Amazon Timestream for LiveAnalytics](https://youtu.be/x8AgLhAydzY).

For this example, we use the following scenario:
+ **Region** – us-east-1
+ **Base table** – `"clickstream"."shopping"`
+ **Derived table** – `"clickstream"."aggregate"`

## Base table
<a name="scheduledqueries-example4-clickstream-base-table"></a>

The following describes the schema for the base table.


| Column | Type | Timestream for LiveAnalytics attribute type | 
| --- | --- | --- | 
|  channel  |  varchar  |  MULTI  | 
|  description  |  varchar  |  MULTI  | 
|  event  |  varchar  |  DIMENSION  | 
|  ip\$1address  |  varchar  |  DIMENSION  | 
|  measure\$1name  |  varchar  |  MEASURE\$1NAME  | 
|  product  |  varchar  |  MULTI  | 
|  product\$1id  |  varchar  |  MULTI  | 
|  quantity  |  double  |  MULTI  | 
|  query  |  varchar  |  MULTI  | 
|  session\$1id  |  varchar  |  DIMENSION  | 
|  user\$1group  |  varchar  |  DIMENSION  | 
|  user\$1id  |  varchar  |  DIMENSION  | 

The following describes the measures for the base table. A *base table* refers to a table in Timestream that scheduled query is run on.
+ **measure\$1name** – `metrics`
+ **data** – multi
+ **dimensions**:

  ```
  [ ( user_group, varchar ),( user_id, varchar ),( session_id, varchar ),( ip_address, varchar ),( event, varchar ) ]
  ```

## Query on a base table
<a name="scheduledqueries-example4-clickstream-base-table-query"></a>

The following is an ad-hoc query that gathers counts by a 5-minute aggregate in a given time range.

```
SELECT BIN(time, 5m) as time, 
channel, 
product_id,
SUM(quantity) as product_quantity 
FROM "clickstream"."shopping" 
WHERE BIN(time, 5m) BETWEEN '2023-05-11 10:10:00.000000000' AND '2023-05-11 10:30:00.000000000'
AND channel = 'Social media'
and product_id = '431412'
GROUP BY BIN(time, 5m),channel,product_id
```

Output:

```
duration:1.745 sec
Bytes scanned: 29.89 MB
Query Id: AEBQEANMHG7MHHBHCKJ3BSOE3QUGIDBGWCCP5I6J6YUW5CVJZ2M3JCJ27QRMM7A
Row count:5
```

## Scheduled query
<a name="scheduledqueries-example4-clickstream-scheduled-query"></a>

The following is a scheduled query that runs every 5 minutes.

```
SELECT BIN(time, 5m) as time, channel as measure_name, product_id, product, 
SUM(quantity) as product_quantity 
FROM "clickstream"."shopping" 
WHERE time BETWEEN BIN(@scheduled_runtime, 5m) - 10m AND BIN(@scheduled_runtime, 5m) - 5m 
AND channel = 'Social media' 
GROUP BY BIN(time, 5m), channel, product_id, product
```

## Query on a derived table
<a name="scheduledqueries-example4-clickstream-derived-table"></a>

The following is an ad-hoc query on a derived table. A *derived table* refers to a Timestream table that contains the results of a scheduled query.

```
SELECT time, measure_name, product_id,product_quantity 
FROM "clickstream"."aggregate"
WHERE time BETWEEN '2023-05-11 10:10:00.000000000' AND '2023-05-11 10:30:00.000000000'
AND measure_name = 'Social media'
and product_id = '431412'
```

Output:

```
duration: 0.2960 sec
Bytes scanned: 235.00 B
QueryID: AEBQEANMHHAAQU4FFTT6CFM6UYXTL4SMLZV22MFP4KV2Z7IRVOPLOMLDD6BR33Q
Row count: 5
```

## Comparison
<a name="scheduledqueries-example4-clickstream-comparison"></a>

The following is a comparison of the results of a query on a base table with a query on a derived table. The same query on a derived table that has aggregated results done through a scheduled query completes faster with fewer scanned bytes. 

These results show the value of using scheduled queries to aggregate data for faster queries.


|  | Query on base table | Query on derived table | 
| --- | --- | --- | 
|  Duration  |  1.745 sec  |  0.2960 sec  | 
|  Bytes scanned  |  29.89 MB  |  235 bytes  | 
|  Row count  |  5  |  5  | 

# Using UNLOAD to export query results to S3 from Timestream for LiveAnalytics
<a name="export-unload"></a>

Amazon Timestream for LiveAnalytics now enables you to export your query results to Amazon S3 in a cost-effective and secure way using the `UNLOAD` statement. Using the `UNLOAD` statement, you can now export time series data to selected S3 buckets in either Apache Parquet or Comma Separated Values (CSV) format, which provides flexibility to store, combine, and analyze your time series data with other services. The `UNLOAD` statement allows you to export the data in a compressed manner, which reduces the data transferred and storage space required. `UNLOAD` also supports partitioning based on selected attributes when exporting the data, improving performance and reducing the processing time of downstream services accessing the data. In addition, you can use Amazon S3 managed keys (SSE-S3) or AWS Key Management Service (AWS KMS) managed keys (SSE-KMS) to encrypt your exported data.

## Benefits of UNLOAD from Timestream for LiveAnalytics
<a name="export-unload-benefits"></a>

The key benefits of using the `UNLOAD` statement are as follows.
+ **Operational ease** – With the `UNLOAD` statement, you can export gigabytes of data in a single query request in either Apache Parquet or CSV format, providing flexibility to select the best suited format for your downstream processing needs and making it easier to build data lakes.
+ **Secure and Cost effective** – `UNLOAD` statement provides the capability to export your data to an S3 bucket in a compressed manner and to encrypt (SSE-KMS or SSE\$1S3) your data using customer managed keys, reducing the data storage costs and protecting against unauthorized access.
+ **Performance** – Using the `UNLOAD` statement, you can partition the data when exporting to an S3 bucket. Partitioning the data enables downstream services to process the data in parallel, reducing their processing time. In addition, downstream services can process only the data they need, reducing the processing resources required and thereby costs associated.

## Use cases for UNLOAD from Timestream for LiveAnalytics
<a name="export-unload-use-cases"></a>

You can use the `UNLOAD` statement to write data to your S3 bucket to the following.
+ **Build Data Warehouse** – You can export gigabytes of query results into S3 bucket and more easily add time series data into your data lake. You can use services such as Amazon Athena and Amazon Redshift to combine your time series data with other relevant data to derive complex business insights. 
+ **Build AI and ML data pipelines** – The `UNLOAD` statement enables you to easily build data pipelines for your machine learning models that access time series data, making it easier to use time series data with services such as Amazon SageMaker and Amazon EMR.
+ **Simplify ETL Processing** – Exporting data into S3 buckets can simplify the process of performing Extract, Transform, Load (ETL) operations on the data, enabling you to seamlessly use third-party tools or AWS services such as AWS Glue to process and transform the data.

# UNLOAD Concepts
<a name="export-unload-concepts"></a>

## Syntax
<a name="export-unload-concepts-syntax"></a>

```
UNLOAD (SELECT statement)
 TO 's3://bucket-name/folder'
 WITH ( option = expression [, ...] )
```

where `option` is

```
{ partitioned_by = ARRAY[ col_name[,…] ] 
 | format = [ '{ CSV | PARQUET }' ] 
 | compression = [ '{ GZIP | NONE }' ]
 | encryption = [ '{ SSE_KMS | SSE_S3 }' ]
 | kms_key = '<string>'
 | field_delimiter ='<character>'
 | escaped_by = '<character>'
 | include_header = ['{true, false}']
 | max_file_size = '<value>'
 | }
```

## Parameters
<a name="export-unload-concepts-parameters"></a>

SELECT statement  
The query statement used to select and retrieve data from one or more Timestream for LiveAnalytics tables.   

```
(SELECT column 1, column 2, column 3 from database.table
      where measure_name = "ABC" and timestamp between ago (1d) and now() )
```

TO clause  

```
TO 's3://bucket-name/folder'
```
or  

```
TO 's3://access-point-alias/folder'
```
The `TO` clause in the `UNLOAD` statement specifies the destination for the output of the query results. You need to provide the full path, including either Amazon S3 bucket-name or Amazon S3 access-point-alias with folder location on Amazon S3 where Timestream for LiveAnalytics writes the output file objects. The S3 bucket should be owned by the same account and in the same region. In addition to the query result set, Timestream for LiveAnalytics writes the manifest and metadata files to specified destination folder. 

PARTITIONED\$1BY clause  

```
partitioned_by = ARRAY [col_name[,…] , (default: none)
```
The `partitioned_by` clause is used in queries to group and analyze data at a granular level. When you export your query results to the S3 bucket, you can choose to partition the data based on one or more columns in the select query. When partitioning the data, the exported data is divided into subsets based on the partition column and each subset is stored in a separate folder. Within the results folder that contains your exported data, a sub-folder `folder/results/partition column = partition value/` is automatically created. However, note that partitioned columns are not included in the output file.   
`partitioned_by` is not a mandatory clause in the syntax. If you choose to export the data without any partitioning, you can exclude the clause in the syntax.   

**Example**  
Assuming you are monitoring clickstream data of your website and have 5 channels of traffic namely `direct`, `Social Media`, `Organic Search`, `Other`, and `Referral`. When exporting the data, you can choose to partition the data using the column `Channel`. Within your data folder, `s3://bucketname/results`, you will have five folders each with their respective channel name, for instance, `s3://bucketname/results/channel=Social Media/.` Within this folder you will find the data of all the customers that landed on your website through the `Social Media` channel. Similarly, you will have other folders for the remaining channels.
Exported data partitioned by Channel column  

![\[Folder structure showing channels: Direct, Organic search, Other, Referral, and Social media.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/unload-results.png)


FORMAT  

```
format = [ '{ CSV | PARQUET }' , default: CSV
```
The keywords to specify the format of the query results written to your S3 bucket. You can export the data either as a comma separated value (CSV) using a comma (,) as the default delimiter or in the Apache Parquet format, an efficient open columnar storage format for analytics. 

COMPRESSION  

```
compression = [ '{ GZIP | NONE }' ], default: GZIP
```
You can compress the exported data using compression algorithm GZIP or have it uncompressed by specifying the `NONE` option.

ENCRYPTION  

```
encryption = [ '{ SSE_KMS | SSE_S3 }' ], default: SSE_S3
```
The output files on Amazon S3 are encrypted using your selected encryption option. In addition to your data, the manifest and metadata files are also encrypted based on your selected encryption option. We currently support SSE\$1S3 and SSE\$1KMS encryption. SSE\$1S3 is a server-side encryption with Amazon S3 encrypting the data using 256-bit advanced encryption standard (AES) encryption. SSE\$1KMS is a server-side encryption to encrypt data using customer-managed keys.

KMS\$1KEY  

```
kms_key = '<string>'
```
KMS Key is a customer-defined key to encrypt exported query results. KMS Key is securely managed by AWS Key Management Service (AWS KMS) and used to encrypt data files on Amazon S3.

FIELD\$1DELIMITER  

```
field_delimiter ='<character>' , default: (,)
```
When exporting the data in CSV format, this field specifies a single ASCII character that is used to separate fields in the output file, such as pipe character (\$1), a comma (,), or tab (/t). The default delimiter for CSV files is a comma character. If a value in your data contains the chosen delimiter, the delimiter will be quoted with a quote character. For instance, if the value in your data contains `Time,stream`, then this value will be quoted as `"Time,stream"` in the exported data. The quote character used by Timestream for LiveAnalytics is double quotes (").  
Avoid specifying the carriage return character (ASCII 13, hex `0D`, text '\$1r') or the line break character (ASCII 10, hex 0A, text '\$1n') as the `FIELD_DELIMITER` if you want to include headers in the CSV, since that will prevent many parsers from being able to parse the headers correctly in the resulting CSV output.

ESCAPED\$1BY  

```
escaped_by = '<character>', default: (\)
```
When exporting the data in CSV format, this field specifies the character that should be treated as an escape character in the data file written to S3 bucket. Escaping happens in the following scenarios:  

1. If the value itself contains the quote character (") then it will be escaped using an escape character. For example, if the value is `Time"stream`, where (\$1) is the configured escape character, then it will be escaped as `Time\"stream`. 

1. If the value contains the configured escape character, it will be escaped. For example, if the value is `Time\stream`, then it will be escaped as `Time\\stream`. 
If the exported output contains complex data type in the like Arrays, Rows or Timeseries, it will be serialized as a JSON string. Following is an example.    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/export-unload-concepts.html)

INCLUDE\$1HEADER  

```
include_header = 'true' , default: 'false'
```
When exporting the data in CSV format, this field lets you include column names as the first row of the exported CSV data files.  
The accepted values are 'true' and 'false' and the default value is 'false'. Text transformation options such as `escaped_by` and `field_delimiter` apply to headers as well.  
When including headers, it is important that you not select a carriage return character (ASCII 13, hex 0D, text '\$1r') or a line break character (ASCII 10, hex 0A, text '\$1n') as the `FIELD_DELIMITER`, since that will prevent many parsers from being able to parse the headers correctly in the resulting CSV output.

MAX\$1FILE\$1SIZE  

```
max_file_size = 'X[MB|GB]' , default: '78GB'
```
This field specifies the maximum size of the files that the `UNLOAD` statement creates in Amazon S3. The `UNLOAD` statement can create multiple files but the maximum size of each file written to Amazon S3 will be approximately what is specified in this field.  
The value of the field must be between 16 MB and 78 GB, inclusive. You can specify it in integer such as `12GB`, or in decimals such as `0.5GB` or `24.7MB`. The default value is 78 GB.  
The actual file size is approximated when the file is being written, so the actual maximum size may not be exactly equal to the number you specify.

## What is written to my S3 bucket?
<a name="export-unload-common-questions-what-is-written"></a>

For every successfully executed UNLOAD query, Timestream for LiveAnalytics writes your query results, metadata file and manifest file into the S3 bucket. If you have partitioned the data, you have all the partition folders in the results folder. Manifest file contains a list of the files that were written by the UNLOAD command. Metadata file contains information that describes the characteristics, properties, and attributes of the written data. 

## What is the exported file name?
<a name="export-unload-common-questions-what-is-filename"></a>

The exported file name contains two components, the first component is the queryID and the second component is a unique identifier.

CSV files

```
S3://bucket_name/results/<queryid>_<UUID>.csv
S3://bucket_name/results/<partitioncolumn>=<partitionvalue>/<queryid>_<UUID>.csv
```

Compressed CSV file

```
S3://bucket_name/results/<partitioncolumn>=<partitionvalue>/<queryid>_<UUID>.gz 
```

Parquet file

```
S3://bucket_name/results/<partitioncolumn>=<partitionvalue>/<queryid>_<UUID>.parquet
```

Metadata and Manifest files

```
S3://bucket_name/<queryid>_<UUID>_manifest.json 
S3://bucket_name/<queryid>_<UUID>_metadata.json
```

As the data in CSV format is stored at a file level, when you compress the data when exporting to S3, the file will have a “.gz” extension. However, the data in Parquet is compressed at column level so even when you compress the data while exporting, the file will still have .parquet extension.

## What information does each file contain?
<a name="export-unload-common-questions-what-information"></a>

### Manifest file
<a name="export-unload-common-questions-what-information-manifest"></a>

The manifest file provides information on the list of files that are exported with the UNLOAD execution. The manifest file is available in the provided S3 bucket with a file name: `s3://<bucket_name>/<queryid>_<UUID>_manifest.json`. The manifest file will contain the url of the files in the results folder, the number of records and size of the respective files, and the query metadata (which is total bytes and total rows exported to S3 for the query). 

```
{
  "result_files": [
    {
        "url":"s3://my_timestream_unloads/ec2_metrics/AEDAGANLHLBH4OLISD3CVOZZRWPX5GV2XCXRBKCVD554N6GWPWWXBP7LSG74V2Q_1448466917_szCL4YgVYzGXj2lS.gz", 
        "file_metadata": 
            { 
                "content_length_in_bytes": 32295, 
                "row_count": 10 
            }
    },
    {
        "url":"s3://my_timestream_unloads/ec2_metrics/AEDAGANLHLBH4OLISD3CVOZZRWPX5GV2XCXRBKCVD554N6GWPWWXBP7LSG74V2Q_1448466917_szCL4YgVYzGXj2lS.gz", 
        "file_metadata": 
            { 
                "content_length_in_bytes": 62295, 
                "row_count": 20 
            }
    },
  ],
  "query_metadata": 
    {
      "content_length_in_bytes": 94590, 
      "total_row_count": 30,
      "result_format": "CSV",
      "result_version": "Amazon Timestream version 1.0.0"  
    },
  "author": {
        "name": "Amazon Timestream", 
        "manifest_file_version": "1.0" 
  }
}
```

### Metadata
<a name="export-unload-common-questions-what-information-metadata"></a>

The metadata file provides additional information about the data set such as column name, column type, and schema. The metadata file is available in the provided S3 bucket with a file name: S3://bucket\$1name/<queryid>\$1<UUID>\$1metadata.json 

Following is an example of a metadata file.

```
{
    "ColumnInfo": [
        {
            "Name": "hostname",
            "Type": {
                "ScalarType": "VARCHAR"
            }
        },
        {
            "Name": "region",
            "Type": {
                "ScalarType": "VARCHAR"
            }
        },
        {
            "Name": "measure_name",
            "Type": {
                "ScalarType": "VARCHAR"
            }
        },
        {
            "Name": "cpu_utilization",
            "Type": {
                "TimeSeriesMeasureValueColumnInfo": {
                    "Type": {
                        "ScalarType": "DOUBLE"
                    }
                }
            }
        }
  ],
  "Author": {
        "Name": "Amazon Timestream", 
        "MetadataFileVersion": "1.0" 
  }
}
```

The column information shared in the metadata file has same structure as `ColumnInfo` sent in Query API response for `SELECT` queries. 

### Results
<a name="export-unload-common-questions-what-information-results"></a>

Results folder contains your exported data in either Apache Parquet or CSV format. 

## Example
<a name="export-unload-example-short"></a>

When you submit an `UNLOAD` query like below via Query API,

```
UNLOAD(SELECT user_id, ip_address, event, session_id, measure_name, time, query, quantity, product_id, channel 
                    FROM sample_clickstream.sample_shopping WHERE time BETWEEN ago(2d) AND now()) 
                TO 's3://my_timestream_unloads/withoutpartition/' WITH ( format='CSV', compression='GZIP')
```

`UNLOAD` query response will have 1 row \$1 3 columns. Those 3 columns are:
+ rows of type BIGINT - indicating the number of rows exported
+ metadataFile of type VARCHAR - which is the S3 URI of metadata file exported
+ manifestFile of type VARCHAR - which is the S3 URI of manifest file exported

You will get the following response from Query API:

```
{
    "Rows": [
        {
            "Data": [
                {
                    "ScalarValue": "20" # No of rows in output across all files
                },
                {
                    "ScalarValue": "s3://my_timestream_unloads/withoutpartition/AEDAAANGH3D7FYHOBQGQQMEAISCJ45B42OWWJMOT4N6RRJICZUA7R25VYVOHJIY_<UUID>_metadata.json" #Metadata file
                },
                {
                    "ScalarValue": "s3://my_timestream_unloads/withoutpartition/AEDAAANGH3D7FYHOBQGQQMEAISCJ45B42OWWJMOT4N6RRJICZUA7R25VYVOHJIY_<UUID>_manifest.json" #Manifest file
                }
            ]
        }
    ],
    "ColumnInfo": [
        {
            "Name": "rows",
            "Type": {
                "ScalarType": "BIGINT"
            }
        },
        {
            "Name": "metadataFile",
            "Type": {
                "ScalarType": "VARCHAR"
            }
        },
        {
            "Name": "manifestFile",
            "Type": {
                "ScalarType": "VARCHAR"
            }
        }
    ],
    "QueryId": "AEDAAANGH3D7FYHOBQGQQMEAISCJ45B42OWWJMOT4N6RRJICZUA7R25VYVOHJIY",
    "QueryStatus": {
        "ProgressPercentage": 100.0,
        "CumulativeBytesScanned": 1000,
        "CumulativeBytesMetered": 10000000
    }
}
```

## Data types
<a name="export-unload-data-types-explanation"></a>

The `UNLOAD` statement supports all data types of Timestream for LiveAnalytics’s query language described in [Supported data types](supported-data-types.md) except `time` and `unknown`.

# Prerequisites for UNLOAD from Timestream for LiveAnalytics
<a name="export-unload-prerequisites"></a>

Following are prerequisites for writing data to S3 using `UNLOAD` from Timestream for LiveAnalytics.
+ You must have permission to read data from the Timestream for LiveAnalytics table(s) to be used in an `UNLOAD` command.
+ You must have an Amazon S3 bucket in the same AWS Region as your Timestream for LiveAnalytics resources.
+ For the selected S3 bucket, ensure that the [S3 bucket policy](https://docs.aws.amazon.com/AmazonS3/latest/userguide/example-bucket-policies.html) also has permissions to allow Timestream for LiveAnalytics to export the data.
+ The credentials used to execute `UNLOAD` query must have necessary AWS Identity and Access Management (IAM) permissions that allows Timestream for LiveAnalytics to write the data to S3. An example policy would be as follows:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [{
            "Effect": "Allow",
            "Action": [
                "timestream:Select",
                "timestream:ListMeasures",
                "timestream:WriteRecords",
                "timestream:Unload"
            ],
            "Resource": "arn:aws:timestream:us-east-2:111122223333:database/database_name/table/table_name"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetBucketAcl",
                "s3:PutObject",
                "s3:GetObject",
                "s3:AbortMultipartUpload"
            ],
            "Resource": [
                "arn:aws:s3:::S3_Bucket_Created",
                "arn:aws:s3:::S3_Bucket_Created/*"
            ]
        }
    ]
}
```

------

For additional context on these S3 write permissions, refer to the [Amazon Simple Storage Service guide](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html#mpuAndPermissions). If you are using a KMS key for encrypting the exported data, see the following for the additional IAM policies required.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
      {
        "Effect": "Allow",
        "Action": [
            "kms:DescribeKey",
            "kms:Decrypt",
            "kms:GenerateDataKey*"
        ],
        "Resource": "arn:aws:kms:us-east-2:111122223333:key/*",
        "Condition": {
            "ForAnyValue:StringLike": {
                "kms:ResourceAliases": "alias/Alias_For_Generated_Key"
            }
        }
    }, {
        "Effect": "Allow",
        "Action": [
            "kms:CreateGrant"
        ],
        "Resource": "arn:aws:kms:us-east-2:111122223333:key/*",
        "Condition": {
            "ForAnyValue:StringEquals": {
                "kms:EncryptionContextKeys": "aws:timestream:database_name"
            },
            "Bool": {
                "kms:GrantIsForAWSResource": true
            },
            "StringLike": {
                "kms:ViaService": "timestream.us-east-2.amazonaws.com"
            },
            "ForAnyValue:StringLike": {
                "kms:ResourceAliases": "alias/Alias_For_Generated_Key"
            }
        }
    }
]
}
```

------

# Best practices for UNLOAD from Timestream for LiveAnalytics
<a name="export-unload-best-practices"></a>

Following are best practices related to the UNLOAD command.
+ The amount of data that can be exported to S3 bucket using the `UNLOAD` command is not bounded. However, the query times out in 60 minutes and we recommend exporting no more than 60GB of data in a single query. If you need to export more than 60GB of data, split the job across multiple queries.
+ While you can send thousands of requests to S3 to upload the data, it is recommended to parallelize the write operations to multiple S3 prefixes. Refer to documentation [here](https://docs.aws.amazon.com/AmazonS3/latest/userguide/optimizing-performance.html). S3 API call rate could be throttled when multiple readers/writers access the same folder. 
+ Given the limit on S3 key length for defining a prefix, we recommend having bucket and folder names within 10-15 characters, especially when using `partitioned_by` clause. 
+ When you receive a 4XX or 5XX for queries containing the `UNLOAD` statement, it is possible that partial results are written into the S3 bucket. Timestream for LiveAnalytics does not delete any data from your bucket. Before executing another `UNLOAD` query with same S3 destination, we recommend to manually delete the files created by the failed query. You can identify the files written by a failed query with the corresponding `QueryExecutionId`. For failed queries, Timestream for LiveAnalytics does not export a manifest file to the S3 bucket. 
+ Timestream for LiveAnalytics uses multi-part upload to export query results to S3. When you receive a 4XX or 5XX from Timestream for LiveAnalytics for queries containing an UNLOAD statement, Timestream for LiveAnalytics does a best-effort abortion of multi-part upload but it is possible that some incomplete parts are left behind. Hence, we recommended to set up an auto cleanup of incomplete multi-part uploads in your S3 bucket by following the guidelines [here](https://aws.amazon.com/blogs/aws-cloud-financial-management/discovering-and-deleting-incomplete-multipart-uploads-to-lower-amazon-s3-costs/).

## Recommendations for accessing the data in CSV format using CSV parser
<a name="export-unload-common-questions-what-information-recommendations-csv"></a>
+ CSV parsers don’t allow you to have same character in delimiter, escape, and quote character.
+ Some CSV parsers cannot interpret complex data types such as Arrays, we recommend interpreting those through JSON deserializer. 

## Recommendations for accessing the data in Parquet format
<a name="export-unload-common-questions-what-information-recommendations-parquet"></a>

1. If your use case requires UTF-8 character support in schema aka column name, we recommend using [Parquet-mr library](https://github.com/apache/parquet-mr).

1. The timestamp in your results is represented as a 12 byte integer (INT96)

1. Timeseries will be represented as `array<row<time, value>>`, other nested structures will use corresponding datatypes supported in Parquet format

## Using partition\$1by clause
<a name="export-unload-best-practices-partition-by"></a>
+ The column used in the `partitioned_by` field should be the last column in the select query. If more than one column is used in the `partitioned_by` field, the columns should be the last columns in the select query and in the same order as used in the `partition_by` field.
+ The column values used to partition the data (`partitioned_by` field) can contain only ASCII characters. While Timestream for LiveAnalytics allows UTF-8 characters in the values, S3 supports only ASCII characters as object keys.

# Example use case for UNLOAD from Timestream for LiveAnalytics
<a name="export-unload-example-use-case"></a>

Assume you are monitoring user session metrics, traffic sources, and product purchases of your e-commerce website. You are using Timestream for LiveAnalytics to derive real-time insights into user behavior, product sales, and perform marketing analytics on traffic channels (organic search, social media, direct traffic, paid campaigns and others) that drive customers to the website. 

**Topics**
+ [Exporting the data without any partitions](#export-unload-example-sample-1)
+ [Partitioning data by channel](#export-unload-example-sample-2)
+ [Partitioning data by event](#export-unload-example-sample-3)
+ [Partitioning data by both channel and event](#export-unload-example-sample-4)
+ [Manifest and metadata files](#export-unload-example-manifest-metadata)
+ [Using Glue crawlers to build Glue Data Catalog](#export-unload-example-using-glue-crawlers)

## Exporting the data without any partitions
<a name="export-unload-example-sample-1"></a>

You want to export the last two days of your data in CSV format.

```
UNLOAD(SELECT user_id, ip_address, event, session_id, measure_name, time, 
query, quantity, product_id, channel 
FROM sample_clickstream.sample_shopping 
WHERE time BETWEEN ago(2d) AND now())  
TO 's3://<bucket_name>/withoutpartition' 
WITH (  format='CSV',   
compression='GZIP')
```

## Partitioning data by channel
<a name="export-unload-example-sample-2"></a>

You want to export the last two days of data in CSV format but would like to have the data from each traffic channel in a separate folder. To do this, you need to partition the data using the `channel` column as shown in the following.

```
UNLOAD(SELECT user_id, ip_address, event, session_id, measure_name, time, 
query, quantity, product_id, channel 
FROM sample_clickstream.sample_shopping 
WHERE time BETWEEN ago(2d) AND now())  
TO 's3://<bucket_name>/partitionbychannel/' 
WITH (  
partitioned_by = ARRAY ['channel'], 
format='CSV',   
compression='GZIP')
```

## Partitioning data by event
<a name="export-unload-example-sample-3"></a>

You want to export the last two days of data in CSV format but would like to have the data for each event in a separate folder. To do this, you need to partition the data using the `event` column as shown in the following.

```
UNLOAD(SELECT user_id, ip_address, channel, session_id, measure_name, time, 
query, quantity, product_id, event 
FROM sample_clickstream.sample_shopping 
WHERE time BETWEEN ago(2d) AND now())  
TO 's3://<bucket_name>/partitionbyevent/' 
WITH (  
partitioned_by = ARRAY ['event'], 
format='CSV',   
compression='GZIP')
```

## Partitioning data by both channel and event
<a name="export-unload-example-sample-4"></a>

You want to export the last two days of data in CSV format but would like to have the data for each channel and within channel store each event in a separate folder. To do this, you need to partition the data using both `channel` and `event` column as shown in the following.

```
UNLOAD(SELECT user_id, ip_address, session_id, measure_name, time, 
query, quantity, product_id, channel,event 
FROM sample_clickstream.sample_shopping 
WHERE time BETWEEN ago(2d) AND now())  
TO 's3://<bucket_name>/partitionbychannelevent/' 
WITH (  
partitioned_by = ARRAY ['channel','event'], 
format='CSV',   
compression='GZIP')
```

## Manifest and metadata files
<a name="export-unload-example-manifest-metadata"></a>

### Manifest file
<a name="export-unload-common-questions-what-information-manifest"></a>

The manifest file provides information on the list of files that are exported with the UNLOAD execution. The manifest file is available in the provided S3 bucket with a file name: `S3://bucket_name/<queryid>_<UUID>_manifest.json`. The manifest file will contain the url of the files in the results folder, the number of records and size of the respective files, and the query metadata (which is total bytes and total rows exported to S3 for the query). 

```
{
  "result_files": [
    {
        "url":"s3://my_timestream_unloads/ec2_metrics/AEDAGANLHLBH4OLISD3CVOZZRWPX5GV2XCXRBKCVD554N6GWPWWXBP7LSG74V2Q_1448466917_szCL4YgVYzGXj2lS.gz", 
        "file_metadata": 
            { 
                "content_length_in_bytes": 32295, 
                "row_count": 10 
            }
    },
    {
        "url":"s3://my_timestream_unloads/ec2_metrics/AEDAGANLHLBH4OLISD3CVOZZRWPX5GV2XCXRBKCVD554N6GWPWWXBP7LSG74V2Q_1448466917_szCL4YgVYzGXj2lS.gz", 
        "file_metadata": 
            { 
                "content_length_in_bytes": 62295, 
                "row_count": 20 
            }
    },
  ],
  "query_metadata": 
    {
      "content_length_in_bytes": 94590, 
      "total_row_count": 30,
      "result_format": "CSV",
      "result_version": "Amazon Timestream version 1.0.0"  
    },
  "author": {
        "name": "Amazon Timestream", 
        "manifest_file_version": "1.0" 
  }
}
```

### Metadata
<a name="export-unload-common-questions-what-information-metadata"></a>

The metadata file provides additional information about the data set such as column name, column type, and schema. The metadata file is available in the provided S3 bucket with a file name: S3://bucket\$1name/<queryid>\$1<UUID>\$1metadata.json 

Following is an example of a metadata file.

```
{
    "ColumnInfo": [
        {
            "Name": "hostname",
            "Type": {
                "ScalarType": "VARCHAR"
            }
        },
        {
            "Name": "region",
            "Type": {
                "ScalarType": "VARCHAR"
            }
        },
        {
            "Name": "measure_name",
            "Type": {
                "ScalarType": "VARCHAR"
            }
        },
        {
            "Name": "cpu_utilization",
            "Type": {
                "TimeSeriesMeasureValueColumnInfo": {
                    "Type": {
                        "ScalarType": "DOUBLE"
                    }
                }
            }
        }
  ],
  "Author": {
        "Name": "Amazon Timestream", 
        "MetadataFileVersion": "1.0" 
  }
}
```

The column information shared in the metadata file has same structure as `ColumnInfo` sent in Query API response for `SELECT` queries. 

## Using Glue crawlers to build Glue Data Catalog
<a name="export-unload-example-using-glue-crawlers"></a>

1. Login to your account with Admin credentials for the following validation.

1. Create a Crawler for Glue Database using the guidelines provided [here](https://docs.aws.amazon.com/glue/latest/ug/tutorial-add-crawler.html). Please note that the S3 folder to be provided in the datasource should be the `UNLOAD` result folder such as `s3://my_timestream_unloads/results`.

1. Run the crawler following the guidelines [here](https://docs.aws.amazon.com/glue/latest/ug/tutorial-add-crawler.html#tutorial-add-crawler-step2).

1. View the Glue table.
   + Go to **AWS Glue** → **Tables**.
   + You will see a new table created with table prefix provided while creating the crawler.
   + You can see the schema and partition information by clicking the table details view.

The following are other AWS services and open-source projects that use the AWS Glue Data Catalog.
+ **Amazon Athena** – For more information, see [Understanding tables, databases, and data catalogs](https://docs.aws.amazon.com/athena/latest/ug/understanding-tables-databases-and-the-data-catalog.html) in the Amazon Athena User Guide.
+ **Amazon Redshift Spectrum** – For more information, see [Querying external data using Amazon Redshift Spectrum](https://docs.aws.amazon.com/redshift/latest/dg/c-using-spectrum.html) in the Amazon Redshift Database Developer Guide.
+ **Amazon EMR** – For more information, see [Use resource-based policies for Amazon EMR access to AWS Glue Data Catalog](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-iam-roles-glue.html) in the Amazon EMR Management Guide.
+ **AWS Glue Data Catalog client for Apache Hive metastore** – For more information about this GitHub project, see [AWS Glue Data Catalog Client for Apache Hive Metastore](https://github.com/awslabs/aws-glue-data-catalog-client-for-apache-hive-metastore).

# Limits for UNLOAD from Timestream for LiveAnalytics
<a name="export-unload-limits"></a>

Following are limits related to the `UNLOAD` command.
+ Concurrency for queries using the `UNLOAD` statement is 1 query per second (QPS). Exceeding the query rate might result in throttling.
+ Queries containing `UNLOAD` statement can export at most 100 partitions per query. We recommend to check the distinct count of the selected column before using it to partition the exported data.
+ Queries containing `UNLOAD` statement time out after 60 minutes.
+ The maximum size of the files that the `UNLOAD` statement creates in Amazon S3 is 78 GB.

For other limits for Timestream for LiveAnalytics, see [QuotasDefault quotas](ts-limits.md)

# Using query insights to optimize queries in Amazon Timestream
<a name="using-query-insights"></a>

Query insights is a performance tuning feature that helps you optimize your queries, improve their performance, and reduce costs. With query insights, you can assess the temporal, time-based, and spatial partition key-based pruning efficiency of your queries. Using query insights, you can also identify areas for improvement to enhance query performance. In addition, with query insights, you can evaluate how effectively your queries use time-based and partition key-based indexing to optimize data retrieval. To optimize query performance, it's essential to fine-tune both the temporal and spatial parameters that govern query execution.

**Topics**
+ [Benefits of query insights](#query-insights-benefits)
+ [Optimizing data access in Amazon Timestream](query-insights-optimize-data-access-pattern.md)
+ [Enabling query insights in Amazon Timestream](enable-query-insights.md)
+ [Optimizing queries using query insights response](optimize-query-using-query-insights.md)

## Benefits of query insights
<a name="query-insights-benefits"></a>

The following are the key benefits of using query insights: 
+ **Identifying inefficient queries** – Query insights provides information on the time-based and attribute-based pruning of the tables accessed by the query. This information helps you identify the tables that are sub-optimally accessed.
+ **Optimizing your data model and partitioning** – You can use the query insights information to access and fine-tune your data model and partitioning strategy.
+ **Tuning queries** – Query insights highlights opportunities to use indexes more effectively.

# Optimizing data access in Amazon Timestream
<a name="query-insights-optimize-data-access-pattern"></a>

You can optimize the data access patterns in Amazon Timestream using the Timestream partitioning scheme or data organization techniques.

**Topics**
+ [Timestream partitioning scheme](#query-insights-optimize-data-access-partitioning-scheme)
+ [Data organization](#query-insights-optimize-data-access-data-org)

## Timestream partitioning scheme
<a name="query-insights-optimize-data-access-partitioning-scheme"></a>

Amazon Timestream uses a highly scalable partitioning scheme where each Timestream table can have hundreds, thousands, or even millions of independent partitions. A highly available partition tracking and indexing service manages the partitioning, minimizing the impact of failures and making the system more resilient.

![\[Timestream partitioning scheme\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/QueryInsights/ts-partitioning-scheme.png)


## Data organization
<a name="query-insights-optimize-data-access-data-org"></a>

Timestream stores each data point it ingests in a single partition. As you ingest data into a Timestream table, Timestream automatically creates partitions based on the timestamps, partition key, and other context attributes in the data. In addition to partitioning the data on time (temporal partitioning), Timestream also partitions the data based on the selected partitioning key and other dimensions (spatial partitioning). This approach is designed to distribute write traffic and allow for effective pruning of data for queries.

The query insights feature provides valuable insights into the pruning efficiency of the query, which includes query spatial coverage and query temporal coverage.

**Topics**
+ [QuerySpatialCoverage](#query-insights-data-org-query-spatial-cvg)
+ [QueryTemporalCoverage](#query-insights-data-org-query-temporal-cvg)

### QuerySpatialCoverage
<a name="query-insights-data-org-query-spatial-cvg"></a>

The [QuerySpatialCoverage](https://docs.aws.amazon.com/timestream/latest/developerguide/API_query_QuerySpatialCoverage.html) metric provides insights into the spatial coverage of the executed query and the table with the most inefficient spatial pruning. This information can help you identify areas of improvement in the partitioning strategy to enhance spatial pruning. The value for the `QuerySpatialCoverage` metric ranges between 0 and 1. The lower the value of the metric, the more optimal the query pruning on the spatial axis. For example, a value of 0.1 indicates that the query scans 10% of the spatial axis. A value of 1 indicates that the query scans 100% of the spatial axis.

**Example Using query insights to analyze a query's spatial coverage**  
Say that you've a Timestream database that stores weather data. Assume that the temperature is recorded every hour from weather stations located across different states in United States. Imagine that you choose `State` as the [customer-defined partitioning key](customer-defined-partition-keys.md) (CDPK) to partition the data by state.  
Suppose that you execute a query to retrieve the average temperature for all weather stations in California between 2 PM and 4 PM on a specific day. The following example shows the query for this scenario.  

```
SELECT AVG(temperature) 
FROM "weather_data"."hourly_weather"
WHERE time >= '2024-10-01 14:00:00' AND time < '2024-10-01 16:00:00' 
  AND state = 'CA';
```
Using the query insights feature, you can analyze the query's spatial coverage. Imagine that the `QuerySpatialCoverage` metric returns a value of 0.02. This means that the query only scanned 2% of the spatial axis, which is efficient. In this case, the query was able to effectively prune the spatial range, only retrieving data from California and ignoring data from other states.  
On the contrary, if the `QuerySpatialCoverage` metric returned a value of 0.8, it would indicate that the query scanned 80% of the spatial axis, which is less efficient. This might suggest that the partitioning strategy needs to be refined to improve spatial pruning. For example, you can select the partition key as city or region instead of a state. By analyzing the `QuerySpatialCoverage` metric, you can identify opportunities to optimize your partitioning strategy and improve the performance of your queries.

The following image shows poor spatial pruning.

![\[Result provided by the QuerySpatialCoverage metric that shows poor spatial pruning.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/QueryInsights/QuerySpatialCoverageMetricResult.png)


To improve spatial pruning efficiency, you can do one or both of the following:
+ Add `measure_name`, the default paritioning key, or use the CDPK predicates in your query.
+ If you've already added the attributes mentioned in the previous point, remove functions around these attributes or clauses, such as `LIKE`.

### QueryTemporalCoverage
<a name="query-insights-data-org-query-temporal-cvg"></a>

The `QueryTemporalCoverage` metric provides insights into the temporal range scanned by the executed query, including the table with the largest time range scanned. The value for the `QueryTemporalCoverage` metric is time range represented in nanoseconds. The lower the value of this metric, the more optimal the query pruning on the temporal range. For example, a query scanning last few minutes of data is more performant than a query scanning the entire time range of the table.

**Example**  
Say that you've a Timestream database that stores IoT sensor data, with measurements taken every minute from devices located in a manufacturing plant. Assume that you've partitioned your data by `device_ID`.  
Suppose that you execute a query to retrieve the average sensor reading for a specific device over the last 30 minutes. The following example shows the query for this scenario.  

```
SELECT AVG(sensor_reading) 
FROM "sensor_data"."factory_1"
WHERE device_id = 'DEV_123' 
  AND time >= NOW() - INTERVAL 30 MINUTE and time < NOW();
```
Using the query insights feature, you can analyze the temporal range scanned by the query. Imagine the `QueryTemporalCoverage` metric returns a value of 1800000000000 nanoseconds (30 minutes). This means that the query only scanned the last 30 minutes of data, which is a relatively narrow temporal range. This is a good sign because it indicates that the query was able to effectively prune the temporal partitioning and only retrieved the requested data.  
On the contrary, if the `QueryTemporalCoverage` metric returned a value of 1 year in nanoseconds, it indicates that the query scanned one year of time range in the table, which is less efficient. This might suggest that the query is not optimized for temporal pruning, and you could improve it by adding time filters.

The following image shows poor temporal pruning.

![\[Result provided by the QueryTemporalCoverage metric that shows poor temporal pruning.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/QueryInsights/QueryTemporalCoverageMetricResult.png)


To improve temporal pruning, we recommend that you do one or all of the following:
+ Add the missing time predicates in the query and make sure that the time predicates are pruning the desired time window.
+ Remove functions, such as `MAX()`, around the time predicates.
+ Add time predicates to all the sub queries. This is important if your sub queries are joining large tables or performing complex operations.

# Enabling query insights in Amazon Timestream
<a name="enable-query-insights"></a>

You can enable query insights for your queries with insights delivered directly through the query response. Enabling query insights doesn't require additional infrastructure or incur any additional costs. When you enable query insights, it returns query performance related metadata fields in addition to query results as part of your query response. You can use this information to tune your queries to improve query performance and reduce query cost.

For information about enabling query insights, see [Run a query](console_timestream.md#console_timestream.queries.using-console).

To view examples of the responses returned by enabling query insights, see [Examples for scheduled queries](https://docs.aws.amazon.com/timestream/latest/developerguide/API_query_ExecuteScheduledQuery.html#API_query_ExecuteScheduledQuery_Examples).

**Note**  
When you enable query insights, it rate limits the query to 1 query per second (QPS). To avoid performance impacts, we strongly recommend that you enable query insights only during the evaluation phase of your queries, before deploying them to production.
The insights provided in query insights are eventually consistent, which means they might change as new data is continuously ingested into the tables.

# Optimizing queries using query insights response
<a name="optimize-query-using-query-insights"></a>

Say that you're using Amazon Timestream for LiveAnalytics to monitor energy consumption across various locations. Imagine that you've two tables in your database named `raw-metrics` and `aggregate-metrics`.

The `raw-metrics` table stores detailed energy data at the device level and contains the following columns:
+ Timestamp
+ State, for example, Washington
+ Device ID
+ Energy consumption

The data for this table is collected and stored at a minute-by-minute granularity. The table uses `State` as the CDPK.

The `aggregate-metrics` table stores the result of a scheduled query to aggregate the energy consumption data across all devices hourly. This table contains the following columns:
+ Timestamp
+ State, for example, Washington
+ Total energy consumption

The `aggregate-metrics` table stores this data at an hourly granularity. The table uses `State` as the CDPK.

**Topics**
+ [Querying energy consumption for the last 24 hours](#query-energy-consumption-data)
+ [Optimizing the query for temporal range](#optimize-query-temporal-range)
+ [Optimizing the query for spatial coverage](#optimize-query-spatial-coverage)
+ [Improved query performance](#improved-query-performance)

## Querying energy consumption for the last 24 hours
<a name="query-energy-consumption-data"></a>

Say that you want to extract the total energy consumed in Washington over the last 24 hours. To find this data, you can leverage the strengths of both the tables: `raw-metrics` and `aggregate-metrics`. The `aggregate-metrics` table provides hourly energy consumption data for the last 23 hours, while the `raw-metrics` table offers minute-granular data for the last one hour. By querying across both tables, you can get a complete and accurate picture of energy consumption in Washington over the last 24 hours.

```
SELECT am.time, am.state, am.total_energy_consumption, 
rm.time, rm.state, rm.device_id, rm.energy_consumption
FROM 
 "metrics"."aggregate-metrics" am
 LEFT JOIN "metrics"."raw-metrics" rm ON am.state = rm.state
WHERE rm.time >= ago(1h) and rm.time < now()
```

This example query is provided for illustrative purposes only and might not work as is. It's intended to demonstrate the concept, but you might need to modify it to fit your specific use case or environment.

After executing this query, you might notice that the query response time is slower than expected. To identify the root cause of this performance issue, you can use the query insights feature to analyze the query's performance and optimize its execution.

The following example shows the query insights response.

```
queryInsightsResponse={
                QuerySpatialCoverage: {
                    Max: {
                        Value: 1.0,
                        TableArn: arn:aws:timestream:us-east-1:123456789012:database/metrics/table/raw-metrics,
                        PartitionKey: [State]
                    }
                },
                QueryTemporalRange: {
                    Max: {
                        Value:31540000000000000 //365 days,
                        TableArn: arn:aws:timestream:us-east-1:123456789012:database/metrics/table/aggregate-metrics
                    }
                },
                QueryTableCount: 2,
                OutputRows: 83,
                OutputBytes: 590
```

The query insights response provides the following information:
+ **Temporal range**: The query scanned an excessive 365-day temporal range for the `aggregate-metrics` table. This indicates an inefficient use of temporal filtering.
+ **Spatial coverage**: The query scanned the entire spatial range (100%) of the `raw-metrics` table. This suggests that the spatial filtering isn't being utilized effectively.

If your query accesses more than one table, query insights provides the metrics for the table with most sub-optimal access pattern.

## Optimizing the query for temporal range
<a name="optimize-query-temporal-range"></a>

Based on the query insights response, you can optimize the query for temporal range as shown in the following example.

```
SELECT am.time, am.state, am.total_energy_consumption, 
rm.time, rm.state, rm.device_id, rm.energy_consumption
FROM 
  "metrics"."aggregate-metrics" am
  LEFT JOIN "metrics"."raw-metrics" rm ON am.state = rm.state
WHERE 
  am.time >=  ago(23h) and am.time < now()
  AND rm.time >=  ago(1h) and rm.time < now()
  AND rm.state = 'Washington'
```

If you run the `QueryInsights` command again, it returns the following response.

```
queryInsightsResponse={
                QuerySpatialCoverage: {
                    Max: {
                        Value: 1.0,
                        TableArn: arn:aws:timestream:us-east-1:123456789012:database/metrics/table/aggregate-metrics,
                        PartitionKey: [State]
                    }
                },
                QueryTemporalRange: {
                    Max: {
                        Value: 82800000000000 //23 hours,
                        TableArn: arn:aws:timestream:us-east-1:123456789012:database/metrics/table/aggregate-metrics
                    }
                },
                QueryTableCount: 2,
                OutputRows: 83,
                OutputBytes: 590
```

This response shows that the spatial coverage for the `aggregate-metrics` table is still 100%, which is inefficient. The following section shows how to optimze the query for spatial coverage.

## Optimizing the query for spatial coverage
<a name="optimize-query-spatial-coverage"></a>

Based on the query insights response, you can optimize the query for spatial coverage as shown in the following example.

```
SELECT am.time, am.state, am.total_energy_consumption, 
rm.time, rm.state, rm.device_id, rm.energy_consumption
FROM 
  "metrics"."aggregate-metrics" am
  LEFT JOIN "metrics"."raw-metrics" rm ON am.state = rm.state
WHERE 
  am.time >=  ago(23h) and am.time < now()
  AND am.state ='Washington'
  AND rm.time >=  ago(1h) and rm.time < now()
  AND rm.state = 'Washington'
```

If you run the `QueryInsights` command again, it returns the following response.

```
queryInsightsResponse={
                QuerySpatialCoverage: {
                    Max: {
                        Value: 0.02,
                        TableArn: arn:aws:timestream:us-east-1:123456789012:database/metrics/table/aggregate-metrics,
                        PartitionKey: [State]
                    }
                },
                QueryTemporalRange: {
                    Max: {
                        Value: 82800000000000 //23 hours,
                        TableArn: arn:aws:timestream:us-east-1:123456789012:database/metrics/table/aggregate-metrics
                    }
                },
                QueryTableCount: 2,
                OutputRows: 83,
                OutputBytes: 590
```

## Improved query performance
<a name="improved-query-performance"></a>

After optimizing the query, query insights provides the following information:
+ Temporal pruning for the `aggregate-metrics` table is 23 hours. This indicates that only 23 hours of the temporal range is scanned.
+ Spatial pruning for `aggregate-metrics` table is 0.02. This indicates that only 2% of the table's spatial range data is being scanned. The query scans a very small portion of the tables leading to fast performance and reduced resource utilization. The improved pruning efficiency indicates that the query is now optimized for performance.

# Working with AWS Backup
<a name="backups"></a>

The data protection functionality in Amazon Timestream for LiveAnalytics is a fully managed solution to help you meet your regulatory compliance and business continuity requirements. The functionality is enabled through native integration with AWS Backup, a unified backup service designed to simplify the creation, migration, restoration, and deletion of backups, while providing improved reporting and auditing. Through integration with AWS Backup, you can use a fully managed, policy-driven centralized data protection solution to create immutable backups and centrally manage data protection of your application data spanning Timestream and other AWS services supported by AWS Backup.

To use the functionality, you must [opt-in](https://docs.aws.amazon.com/aws-backup/latest/devguide/service-opt-in.html) to allow AWS Backup to protect your Timestream resources. Opt-in choices apply to the specific account and AWS Region, so you might have to opt in to multiple Regions using the same account. For more information on AWS Backup, see the [AWS Backup Developer Guide](https://docs.aws.amazon.com/aws-backup/latest/devguide/whatisbackup.html).

Data Protection functionality available through AWS Backup includes the following.

**Scheduled backups**—You can set up regularly scheduled backups of your Timestream for LiveAnalytics tables using backup plans.

**Cross-account and cross-Region copying**—You can automatically copy your backups to another backup vault in a different AWS Region or account, which allows you to support your data protection requirements.

**Cold storage tiering**—You can configure your backups to implement life cycle rules to delete or transition backups to colder storage. This can help you optimize your backup costs.

**Tags**—You can automatically tag your backups for billing and cost allocation purposes.

**Encryption**—Your backup data is stored in the AWS Backup vault. This allows you to encrypt and secure your backups by using an AWS KMS key that is independent from your Timestream for LiveAnalytics table encryption key.

**Secure backups using the WORM model**—You can use AWS Backup Vault Lock to enable a write-once-read-many (WORM) setting for your backups. With AWS Backup Vault Lock, you can add an additional layer of defense that protects backups from inadvertent or malicious delete operations, changes to backup retention periods, and updates to lifecycle settings. To learn more, see [AWS Backup Vault Lock](https://docs.aws.amazon.com/aws-backup/latest/devguide/vault-lock.html).

The data protection functionality is available in all regions To learn more about the functionality, see the [AWS Backup Developer Guide](https://docs.aws.amazon.com/aws-backup/latest/devguide/whatisbackup.html).

# Backing up and restoring Timestream tables: How it works
<a name="backups-how-it-works"></a>

You can create backups of your Amazon Timestream tables. This section provides an overview of what happens during the backup and restore process.

**Topics**
+ [Backups](#backups-backups)
+ [Restores](#backups-restores)

## Backups
<a name="backups-backups"></a>

You can use the on-demand backup feature to create full backups of your Amazon Timestream for LiveAnalytics tables. This section provides an overview of what happens during the backup and restore process.

You can create a backup of your Timestream data at a table granularity. You can initiate a backup of the selected table using either Timestream console, or AWS Backup console, SDK, or CLI. The backup is created asynchronously and all the data in the table until the backup initiation time is included in the backup. However, there is a possibility that some of the data ingested into the table while the backup is in progress might also be included in the backup. To protect your data, you can either create a one-time on-demand backup or schedule a recurring backup of your table.

While a backup is in progress, you cannot do the following.
+ Pause or cancel the backup operation.
+ Delete the source table of the backup.
+ Disable backups on a table if a backup for that table is in progress.

Once configured, AWS Backup provides automated backup schedules, retention management, and lifecycle management, removing the need for custom scripts and manual processes. For more information, see the [AWS Backup Developer Guide](https://docs.aws.amazon.com/aws-backup/latest/devguide/whatisbackup.html)

All Timestream for LiveAnalytics backups are incremental in nature, implying that the first backup of a table is a full backup and every subsequent backup of the same table is an incremental backup, copying only the changes to the data since the last backup. As the data in Timestream for LiveAnalytics is stored in a collection of partitions, all the partitions that changed either due to ingesting new data or updates to the existing data since the last backup are copied during subsequent backups. 

If you are using Timestream for LiveAnalytics console, the backups created for all the resources in the account are listed in the **Backups** tab. Additionally, the backups are also listed in the **Table** details.

## Restores
<a name="backups-restores"></a>

You can restore a table from the Timestream for LiveAnalytics console, or AWS Backup console, SDK, or AWS CLI. You can either restore the entire data from your backup, or configure the table retention settings to restore select data. When you initiate a restore, you can configure the following table settings.
+ Database Name
+ Table Name
+ Memory store retention
+ Magnetic store retention
+ Enable Magnetic storage writes
+ S3 error logs location (optional)
+ IAM role that AWS Backup will assume when restoring the backup

The preceding configurations are independent of the source table. To restore all the data in your backup, we recommend that you configure the new table settings such that the sum of memory store retention period and magnetic store retention period is greater than the difference between the oldest timestamp and now. When you select a backup that is incremental to restore, all data (incremental \$1 underlying full data) is restored. Upon successful restore, the table is in active state and you can perform ingestion and/or query operations on the restored table. However, you cannot perform these operations while the restore is in progress. Once restored, the table is similar to any other table in your account.

**Example Restore the all data from a backup**  
This example has the following assumptions.  

*Oldest timestamp*—`August 1, 2021 0:00:00`
+ *Now*—`November 9, 2022 0:00:00`
To restore all data from a backup, enter and compare values as follows.  

1. Enter **Memory store retention** and **Magnetic store retention**. For example, assume these values.
   + *Memory store retention*—12 hours
   + *Magnetic store retention*—500 days

1. Find the sum of **Memory store retention** and **Magnetic store retention**.

   ```
   12 hours + (500 * 24 hours) =
   12 hours + 12,000 hours =
   12,012 hours
   ```

1. Find the difference between **Oldest timestamp** and now.

   ```
   November 9, 2022 0:00:00 - August 1, 2021 0:00:00 =
   465 days =
   465 * 24 hours =
   11,160 hours
   ```

1. Ensure the sum of retention values in the second step is greater than difference of times in the third step. Adjust the retention times if necessary.

   ```
   12,012 > 11,160
   true
   ```

**Example Restore select data from a backup**  
This example has the following assumption.  
+ *Now*—`November 9, 2022 0:00:00`
To restore only select data from a backup, enter and compare values as follows.  

1. Determine the earliest timestamp required. For example, assume `December 4, 2021 0:00:00`.

1. Find the difference between the earliest timestamp required and now.

   ```
   November 9, 2022 0:00:00 - December 4, 2021 0:00:00 =
   340 days =
   340 * 24 hours =
   8,160 hours
   ```

1. Enter the desired value for **Memory store retention**. For example, enter 12 hours.

1. Subtract the value from the difference in the second step.

   ```
   8,160 hours - 12 hours =
   8148 hours
   ```

1. Enter that value for **Magnetic store retention**.

You can copy a backup of your Timestream for LiveAnalytics table data to a different AWS Region and then restore it in that new Region. You can copy and then restore backups between AWS commercial Regions, and AWS GovCloud (US) Regions. You pay only for the data you copy from the source Region and the data you restore to a new table in the destination Region.

Once the table is restored, you must manually set up the following on the restored table.
+ AWS Identity and Access Management (IAM) policies
+ Tags
+ Scheduled Queries

Restore times are directly related to the configuration of your tables. These include the size of your tables, the number of underlying partitions, the amount of data restored to memory store, and other variables. A best practice when planning for disaster recovery is to regularly document average restore completion times and establish how these times affect your overall Recovery Time Objective (RTO).

All backup and restore console and API actions are captured and recorded in AWS CloudTrail for logging, continuous monitoring, and auditing.

# Creating backups of Amazon Timestream tables
<a name="backups-creating"></a>

This section describes how to enable AWS Backup and create on-demand and scheduled backups for Amazon Timestream.

**Topics**
+ [Enabling AWS Backup to protect Timestream for LiveAnalytics data](#backups-enabling)
+ [Creating on-demand backups](#backups-on-demand)
+ [Scheduled backups](#backups-scheduled)

## Enabling AWS Backup to protect Timestream for LiveAnalytics data
<a name="backups-enabling"></a>

You must enable AWS Backup to use it with Timestream for LiveAnalytics.

To enable AWS Backup in the Timestream for LiveAnalytics console, perform the following steps.

1.  Sign in to the [AWS Management Console](https://console.aws.amazon.com/timestream). 

1. A pop-up banner appears at the top of your Timestream for LiveAnalytics dashboard page to enable AWS Backup to support Timestream for LiveAnalytics data. Otherwise, from the navigation pane, choose **Backups**.

1. In the **Backup** window, you will see the banner to enable AWS Backup. Choose **Enable**.

   Data Protection through AWS Backup is now available for your Timestream for LiveAnalytics tables.

To enable through AWS Backup, refer to AWS Backup documentation to enable via console and programmatically.

If you choose to disable AWS Backup from protection your Timestream for LiveAnalytics data after those have been enabled, log in through AWS Backup console and move the toggle to the left.

 If you can’t enable or disable the AWS Backup features, your AWS admin may need to perform those actions.

## Creating on-demand backups
<a name="backups-on-demand"></a>

To create an on-demand backup of a Timestream for LiveAnalytics table, follow these steps.

1. Sign in to the [AWS Management Console](https://console.aws.amazon.com/timestream).

1. In the navigation pane on the left side of the console, choose **Backups**.

1. Choose **Create on-demand backup**.

1. Continue to select the settings in the backup window.

1. You can either create a backup now, initiates a backup immediately, or select a backup window to start the backup.

1. Select the lifecycle management policy of your backup. You can transition your backup data into cold storage where you have to retain the backup for a minimum of 90 days. You can set the required retention period for your backup You can either select an existing vault or or select **create new backup vault** to navigate to AWS Backup console and create a new backup vault <documentation link on creating a new backup vault here>

1. Select the appropriate IAM role.

1. If you want to assign one or more tags to your on-demand backup, enter a **key** and optional **value**, and choose **Add tag**.

1. Choose to create an on-demand backup. This takes you to the **Backup** page, where you will see a list of jobs.

1. Choose the **Backup job ID** for the resource that you chose to back up to see the details of that job.

## Scheduled backups
<a name="backups-scheduled"></a>

To schedule a backup, refer to [Create a scheduled backup](https://docs.aws.amazon.com/aws-backup/latest/devguide/create-a-scheduled-backup.html).

# Restoring a backup of an Amazon Timestream table
<a name="backups-restoring"></a>

This section describes how to restore a backup of an Amazon Timestream table.

**Topics**
+ [Restoring a Timestream for LiveAnalytics table from AWS Backup](#backups-restoring-from)
+ [Restoring a Timestream for LiveAnalytics table to another Region or account](#backups-restoring-to)

## Restoring a Timestream for LiveAnalytics table from AWS Backup
<a name="backups-restoring-from"></a>

To restore your Timestream for LiveAnalytics table from AWS Backup using Timestream for LiveAnalytics console, follow these steps.

1. Sign in to the [AWS Management Console](https://console.aws.amazon.com/timestream).

1. In the navigation pane on the left side of the console, choose **Backups**.

1. To restore a resource, choose the radio button next to the recovery point ID of the resource. In the upper-right corner of the pane, choose **Restore**.

1. Enter the table configuration settings, namely **Database name** and **Table Name**. Please note, the restored table name should be different from the original source table name.

1. Configure the memory and magnetic store retention settings.

1. For **Restore role**, choose the IAM role that AWS Backup will assume for this restore.

1. Choose **Restore backup**. A message at the top of the page provides information about the restore job.

**Note**  
You are charged for restoring the entire backup irrespective of the configured memory and magnetic store retention periods. However, once the restore is completed, your restored table will only contain the data within the configured retention periods.

## Restoring a Timestream for LiveAnalytics table to another Region or account
<a name="backups-restoring-to"></a>

To restore a Timestream for LiveAnalytics table to another Region or account, you will first need to copy the backup to that new Region or account. In order to copy to another account, that account must first grant you permission. After you have copied your Timestream for LiveAnalytics backup to the new Region or account, it can be restored with the process in the previous section.

# Copying a backup of a Amazon Timestream table
<a name="backups-copying"></a>

You can make a copy of a current backup. You can copy backups to multiple AWS accounts or AWS Regions on demand or automatically as part of a scheduled backup plan. Cross-Region replication is especially valuable if you have business continuity or compliance requirements to store backups a minimum distance away from your production data.

Cross-account backups are useful for securely copying your backups to one or more AWS accounts in your organization for operational or security reasons. If your original backup is inadvertently deleted, you can copy the backup from its destination account to its source account, and then start the restore. Before you can do this, you must have two accounts that belong to the same organization in the Organizations service and required permissions for the accounts. When you copy an incremental backup into another account or Region, the associated full backup is also copied.

Copies inherit the source backup's configuration unless you specify otherwise. There is one exception. If you specify your new copy to "Never" expire. With this setting, the new copy still inherits its source expiration date. If you want your new backup copy to be permanent, either set your source backups to never expire, or specify your new copy to expire 100 years after its creation.

To copy a backup from Timestream console, follow these steps.

1. Sign in to the [AWS Management Console](https://console.aws.amazon.com/timestream).

1. In the navigation pane on the left side of the console, choose **Backups**.

1. Choose the radio button next to the recovery point ID of the resource. In the upper-right corner of the pane, select **Actions** and choose **Copy**.

1. Select **Continue to AWS Backup** and follow the steps for [Cross account backup](https://docs.aws.amazon.com/aws-backup/latest/devguide/cross-region-backup.html).

Copying on-demand and scheduled backups across accounts and Regions is not natively supported in the Timestream for LiveAnalytics console currently and you have to navigate to AWS Backup to perform the operation. 

# Deleting backups
<a name="backups-deleting"></a>

This section describes how to delete a backup of a Timestream for LiveAnalytics table.

To delete a backup from Timestream console, follow these steps.

1. Sign in to the [AWS Management Console](https://console.aws.amazon.com/timestream).

1. In the navigation pane on the left side of the console, choose **Backups**.

1. Choose the radio button next to the recovery point ID of the resource. In the upper-right corner of the pane, select **Actions** and choose **Delete**.

1. Select **Continue to AWS Backup** and follow the steps for deleting backups at [Deleting backups](https://docs.aws.amazon.com/aws-backup/latest/devguide/deleting-backups.html).

**Note**  
When you delete a backup that is incremental, only the incremental backup is deleted and the underlying full backup is not deleted.

# Quota and limits
<a name="backups-limits"></a>

AWS Backup limits the backups to one concurrent backup per resource. Therefore, additional scheduled or on-demand backup requests for the resource are queued and will start only after the existing backup job is completed. If the backup job is not started or completed within the backup window, the request fails. For more information about AWS Backup limits, see [AWS Backup Limits](https://docs.aws.amazon.com/aws-backup/latest/devguide/aws-backup-limits.html) in the AWS Backup Developer Guide.

When creating a backup, you can execute up to four concurrent backups per account. Similarly, you can execute one concurrent restore per account. When you initiate more than four backup jobs simultaneously, only four backup jobs are initiated and the remaining jobs will be periodically retried. Once initiated, if the backup job is not completed within the configured backup window duration, the backup job fails. If the failed backup job is an on-demand backup, you can retry the backup and for scheduled backups, the job is attempted in the following schedule.

# Customer-defined partition keys
<a name="customer-defined-partition-keys"></a>

Amazon Timestream for LiveAnalytics customer-defined partition keys is a feature in Timestream for LiveAnalytics that enables customers to define their own partition keys for their tables. Partitioning is a technique used to distribute data across multiple physical storage units, allowing for faster and more efficient data retrieval. With customer-defined partition keys, customers can create a partitioning schema that better aligns with their query patterns and use cases.

With Timestream for LiveAnalytics customer-defined partition keys, customers can choose one dimension names as a partition key for their tables. This allows for more flexibility in defining the partitioning schema for their data. By selecting the right partition key, customers can optimize their data model, improving their query performance, and reduce query latency.

**Topics**
+ [Using customer-defined partition keys](customer-defined-partition-keys-using.md)
+ [Getting started with customer-defined partition keys](customer-defined-partition-keys-getting-started.md)
+ [Checking partitioning schema configuration](customer-defined-partition-keys-checking-configuration.md)
+ [Updating partitioning schema configuration](customer-defined-partition-keys-updating-configuration.md)
+ [Advantages of customer-defined partition keys](customer-defined-partition-keys-advantages.md)
+ [Limitations of customer-defined partition keys](customer-defined-partition-keys-limitations.md)
+ [Customer-defined partition keys and low cardinality dimensions](customer-defined-partition-keys-low-cardinality-dimensions.md)
+ [Creating partition keys for existing tables](customer-defined-partition-keys-creating.md)
+ [Timestream for LiveAnalytics schema validation with custom composite partition keys](customer-defined-partition-keys-schema-validation.md)

# Using customer-defined partition keys
<a name="customer-defined-partition-keys-using"></a>

If you have a well-defined query pattern with high cardinality dimensions and require low query latency, a Timestream for LiveAnalytics customer-defined partition key can be a useful tool to enhance your data model. For instance, if you are a retail company tracking customer interactions on your website, the main access patterns would likely be by customer ID and timestamp. By defining customer ID as the partition key, your data can be distributed evenly, allowing for reduced latency, ultimately improving the user experience.

Another example is in the healthcare industry, where wearable devices collect sensor data to track patients' vital signs. The main access pattern would be by Device ID and timestamp, with high cardinality on both dimensions. By defining Device ID as the partition key, can optimize your query execution and ensure a sustained long term query performance.

In summary, Timestream for LiveAnalytics customer-defined partition keys are most useful when you have a clear query pattern, high cardinality dimensions, and need low latency for your queries. By defining a partition key that aligns with your query pattern, you can optimize your query execution and ensure a sustained long term performance query performance.



# Getting started with customer-defined partition keys
<a name="customer-defined-partition-keys-getting-started"></a>

From the console, choose **Tables** and create a new table. You can also use an SDK to access the `CreateTable` action to create new tables that can include a customer-defined partition key.

## Create a table with a dimension type partition key
<a name="code-samples.create-table-with-dimension-type-partition-key"></a>

You can use the following code snippets to create a table with a dimension type partition key.

------
#### [  Java  ]

```
public void createTableWithDimensionTypePartitionKeyExample() {
        System.out.println("Creating table");
        CreateTableRequest createTableRequest = new CreateTableRequest();
        createTableRequest.setDatabaseName(DATABASE_NAME);
        createTableRequest.setTableName(TABLE_NAME);
        final RetentionProperties retentionProperties = new RetentionProperties()
                .withMemoryStoreRetentionPeriodInHours(HT_TTL_HOURS)
                .withMagneticStoreRetentionPeriodInDays(CT_TTL_DAYS);
        createTableRequest.setRetentionProperties(retentionProperties);

        // Can specify enforcement level with OPTIONAL or REQUIRED
        final List<PartitionKey> partitionKeyWithDimensionAndOptionalEnforcement = Collections.singletonList(new PartitionKey()
            .withName(COMPOSITE_PARTITION_KEY_DIM_NAME)
            .withType(PartitionKeyType.DIMENSION)
            .withEnforcementInRecord(PartitionKeyEnforcementLevel.OPTIONAL));
        Schema schema = new Schema();
        schema.setCompositePartitionKey(partitionKeyWithDimensionAndOptionalEnforcement);
        createTableRequest.setSchema(schema);
        
        try {
            writeClient.createTable(createTableRequest);
            System.out.println("Table [" + TABLE_NAME + "] successfully created.");
        } catch (ConflictException e) {
            System.out.println("Table [" + TABLE_NAME + "] exists on database [" + DATABASE_NAME + "] . Skipping database creation");
        }
    }
```

------
#### [  Java v2  ]

```
public void createTableWithDimensionTypePartitionKeyExample() {
        System.out.println("Creating table"); 
        final RetentionProperties retentionProperties = RetentionProperties.builder()
                .memoryStoreRetentionPeriodInHours(HT_TTL_HOURS)
                .magneticStoreRetentionPeriodInDays(CT_TTL_DAYS)
                .build();
        // Can specify enforcement level with OPTIONAL or REQUIRED
        final List<PartitionKey> partitionKeyWithDimensionAndOptionalEnforcement = Collections.singletonList(PartitionKey
                .builder()
                .name(COMPOSITE_PARTITION_KEY_DIM_NAME)
                .type(PartitionKeyType.DIMENSION)
                .enforcementInRecord(PartitionKeyEnforcementLevel.OPTIONAL)
                .build());
        final Schema schema = Schema.builder()
                .compositePartitionKey(partitionKeyWithDimensionAndOptionalEnforcement).build();
        final CreateTableRequest createTableRequest = CreateTableRequest.builder()
                .databaseName(DATABASE_NAME)
                .tableName(TABLE_NAME)
                .retentionProperties(retentionProperties)
                .schema(schema)
                .build();

        try {
            writeClient.createTable(createTableRequest);
            System.out.println("Table [" + TABLE_NAME + "] successfully created.");
        } catch (ConflictException e) {
            System.out.println("Table [" + TABLE_NAME + "] exists on database [" + DATABASE_NAME + "] . Skipping database creation");
        }
    }
```

------
#### [  Go v1 ]

```
func createTableWithDimensionTypePartitionKeyExample(){ 
        // Can specify enforcement level with OPTIONAL or REQUIRED
        partitionKeyWithDimensionAndOptionalEnforcement := []*timestreamwrite.PartitionKey{
                {
                    Name:                aws.String(CompositePartitionKeyDimName),
                    EnforcementInRecord: aws.String("OPTIONAL"),
                    Type:                aws.String("DIMENSION"),
                },
        }     
        createTableInput := &timestreamwrite.CreateTableInput{
             DatabaseName: aws.String(*databaseName),
             TableName:    aws.String(*tableName),
             // Enable MagneticStoreWrite for Table
             MagneticStoreWriteProperties: &timestreamwrite.MagneticStoreWriteProperties{
                 EnableMagneticStoreWrites: aws.Bool(true),
                 // Persist MagneticStoreWrite rejected records in S3
                 MagneticStoreRejectedDataLocation: &timestreamwrite.MagneticStoreRejectedDataLocation{
                     S3Configuration: &timestreamwrite.S3Configuration{
                         BucketName:       aws.String("timestream-sample-bucket"),
                         ObjectKeyPrefix:  aws.String("TimeStreamCustomerSampleGo"),
                         EncryptionOption: aws.String("SSE_S3"),
                     },
                 },
             },   
             Schema: &timestreamwrite.Schema{
                 CompositePartitionKey: partitionKeyWithDimensionAndOptionalEnforcement,
             }
         }
         _, err := writeSvc.CreateTable(createTableInput)
    }
```

------
#### [  Go v2 ]

```
  func (timestreamBuilder TimestreamBuilder) CreateTableWithDimensionTypePartitionKeyExample() error {
         partitionKeyWithDimensionAndOptionalEnforcement := []types.PartitionKey{
             {
                 Name:                aws.String(CompositePartitionKeyDimName),
                 EnforcementInRecord: types.PartitionKeyEnforcementLevelOptional,
                 Type:                types.PartitionKeyTypeDimension,
             },
         }
         _, err := timestreamBuilder.WriteSvc.CreateTable(context.TODO(), &timestreamwrite.CreateTableInput{
             DatabaseName: aws.String(databaseName),
             TableName:    aws.String(tableName),
             MagneticStoreWriteProperties: &types.MagneticStoreWriteProperties{
                 EnableMagneticStoreWrites: aws.Bool(true),
                 // Persist MagneticStoreWrite rejected records in S3
                 MagneticStoreRejectedDataLocation: &types.MagneticStoreRejectedDataLocation{
                     S3Configuration: &types.S3Configuration{
                         BucketName:       aws.String(s3BucketName),
                         EncryptionOption: "SSE_S3",
                     },
                 },
             },
             Schema: &types.Schema{
                 CompositePartitionKey: partitionKeyWithDimensionAndOptionalEnforcement,
             },
         })
      
         if err != nil {
             fmt.Println("Error:")
             fmt.Println(err)
         } else {
             fmt.Println("Create table is successful")
         }
         return err
     }
```

------
#### [  Python  ]

```
def create_table_with_measure_name_type_partition_key(self):
        print("Creating table")
        retention_properties = {
            'MemoryStoreRetentionPeriodInHours': HT_TTL_HOURS,
            'MagneticStoreRetentionPeriodInDays': CT_TTL_DAYS
        }
        partitionKey_with_measure_name = [
            {'Type': 'MEASURE'}
        ]
        schema = {
            'CompositePartitionKey': partitionKey_with_measure_name
        }
        try:
            self.client.create_table(DatabaseName=DATABASE_NAME, TableName=TABLE_NAME,
                                     RetentionProperties=retention_properties, Schema=schema)
            print("Table [%s] successfully created." % TABLE_NAME)
        except self.client.exceptions.ConflictException:
            print("Table [%s] exists on database [%s]. Skipping table creation" % (
                TABLE_NAME, DATABASE_NAME))
        except Exception as err:
            print("Create table failed:", err)
```

------

# Checking partitioning schema configuration
<a name="customer-defined-partition-keys-checking-configuration"></a>

You can check how a table configuration for partitioning schema in a couple of ways. From the console, choose **Databases** and choose the table to check. You can also use an SDK to access the `DescribeTable` action.

## Describe a table with a partition key
<a name="code-samples.describe-table-checking-partition-key"></a>

You can use the following code snippets to describe a table with a partition key.

------
#### [  Java  ]

```
    public void describeTable() {
        System.out.println("Describing table");
        final DescribeTableRequest describeTableRequest = new DescribeTableRequest();
        describeTableRequest.setDatabaseName(DATABASE_NAME);
        describeTableRequest.setTableName(TABLE_NAME);
        try {
            DescribeTableResult result = amazonTimestreamWrite.describeTable(describeTableRequest);
            String tableId = result.getTable().getArn();
            System.out.println("Table " + TABLE_NAME + " has id " + tableId);
            // If table is created with composite partition key, it can be described with
            // System.out.println(result.getTable().getSchema().getCompositePartitionKey());
        } catch (final Exception e) {
            System.out.println("Table " + TABLE_NAME + " doesn't exist = " + e);
            throw e;
        }
    }
```

The following is an example output.

1. Table has dimension type partition key

   ```
   [{Type: DIMENSION,Name: hostId,EnforcementInRecord: OPTIONAL}]
   ```

1. Table has measure name type partition key

   ```
   [{Type: MEASURE,}]
   ```

1. Getting composite partition key from a table created without specifying composite partition key

   ```
   [{Type: MEASURE,}]
   ```

------
#### [  Java v2  ]

```
  public void describeTable() {
        System.out.println("Describing table");
        final DescribeTableRequest describeTableRequest = DescribeTableRequest.builder()
                .databaseName(DATABASE_NAME).tableName(TABLE_NAME).build();
        try {
            DescribeTableResponse response = writeClient.describeTable(describeTableRequest);
            String tableId = response.table().arn();
            System.out.println("Table " + TABLE_NAME + " has id " + tableId);
            // If table is created with composite partition key, it can be described with
            // System.out.println(response.table().schema().compositePartitionKey());
        } catch (final Exception e) {
            System.out.println("Table " + TABLE_NAME + " doesn't exist = " + e);
            throw e;
        }
    }
```

The following is an example output.

1. Table has dimension type partition key

   ```
   [PartitionKey(Type=DIMENSION, Name=hostId, EnforcementInRecord=OPTIONAL)]
   ```

1. Table has measure name type partition key

   ```
   [PartitionKey(Type=MEASURE)]
   ```

1. Getting composite partition key from a table created without specifying composite partition key will return

   ```
   [PartitionKey(Type=MEASURE)]
   ```

------
#### [  Go v1 ]

```
    <tablistentry>
     <tabname> Go </tabname>
     <tabcontent>
      <programlisting language="go"></programlisting>
     </tabcontent>
    </tablistentry>
```

The following is an example output.

```
{
  Table: {
    Arn: "arn:aws:timestream:us-west-2:533139590831:database/devops/table/host_metrics_dim_pk_1",
    CreationTime: 2023-05-31 01:52:00.511 +0000 UTC,
    DatabaseName: "devops",
    LastUpdatedTime: 2023-05-31 01:52:00.511 +0000 UTC,
    MagneticStoreWriteProperties: {
      EnableMagneticStoreWrites: true,
      MagneticStoreRejectedDataLocation: {
        S3Configuration: {
          BucketName: "timestream-sample-bucket-west",
          EncryptionOption: "SSE_S3",
          ObjectKeyPrefix: "TimeStreamCustomerSampleGo"
        }
      }
    },
    RetentionProperties: {
      MagneticStoreRetentionPeriodInDays: 73000,
      MemoryStoreRetentionPeriodInHours: 6
    },
    Schema: {
      CompositePartitionKey: [{
          EnforcementInRecord: "OPTIONAL",
          Name: "hostId",
          Type: "DIMENSION"
        }]
    },
    TableName: "host_metrics_dim_pk_1",
    TableStatus: "ACTIVE"
  }
}
```

------
#### [  Go v2 ]

```
 func (timestreamBuilder TimestreamBuilder) DescribeTable() (*timestreamwrite.DescribeTableOutput, error) {
         describeTableInput := &timestreamwrite.DescribeTableInput{
             DatabaseName: aws.String(databaseName),
             TableName:    aws.String(tableName),
         }
        describeTableOutput, err := timestreamBuilder.WriteSvc.DescribeTable(context.TODO(), describeTableInput)
    
        if err != nil {
            fmt.Printf("Failed to describe table with Error: %s", err.Error())
        } else {
            fmt.Printf("Describe table is successful : %s\n", JsonMarshalIgnoreError(*describeTableOutput))
            // If table is created with composite partition key, it will be included in the output
        }
    
        return describeTableOutput, err
    }
```

The following is an example output.

```
{
  "Table": {
    "Arn":"arn:aws:timestream:us-east-1:351861611069:database/cdpk-wr-db/table/host_metrics_dim_pk",
    "CreationTime":"2023-05-31T22:36:10.66Z",
    "DatabaseName":"cdpk-wr-db",
    "LastUpdatedTime":"2023-05-31T22:36:10.66Z",
    "MagneticStoreWriteProperties":{
      "EnableMagneticStoreWrites":true,
      "MagneticStoreRejectedDataLocation":{
        "S3Configuration":{
          "BucketName":"error-configuration-sample-s3-bucket-cq8my",
          "EncryptionOption":"SSE_S3",
          "KmsKeyId":null,"ObjectKeyPrefix":null
        }
      }
    },
    "RetentionProperties":{
      "MagneticStoreRetentionPeriodInDays":73000,
      "MemoryStoreRetentionPeriodInHours":6
    },
    "Schema":{
      "CompositePartitionKey":[{
        "Type":"DIMENSION",
        "EnforcementInRecord":"OPTIONAL",
        "Name":"hostId"
      }]
    },
    "TableName":"host_metrics_dim_pk",
    "TableStatus":"ACTIVE"
  },
  "ResultMetadata":{}
}
```

------
#### [  Python  ]

```
  def describe_table(self):
        print('Describing table')
        try:
            result = self.client.describe_table(DatabaseName=DATABASE_NAME, TableName=TABLE_NAME)
            print("Table [%s] has id [%s]" % (TABLE_NAME, result['Table']['Arn']))
            # If table is created with composite partition key, it can be described with
            # print(result['Table']['Schema'])
        except self.client.exceptions.ResourceNotFoundException:
            print("Table doesn't exist")
        except Exception as err:
            print("Describe table failed:", err)
```

The following is an example output.

1. Table has dimension type partition key

   ```
   [{'CompositePartitionKey': [{'Type': 'DIMENSION', 'Name': 'hostId', 'EnforcementInRecord': 'OPTIONAL'}]}]
   ```

1. Table has measure name type partition key

   ```
   [{'CompositePartitionKey': [{'Type': 'MEASURE'}]}]
   ```

1. Getting composite partition key from a table created without specifying composite partition key 

   ```
   [{'CompositePartitionKey': [{'Type': 'MEASURE'}]}]
   ```

------

# Updating partitioning schema configuration
<a name="customer-defined-partition-keys-updating-configuration"></a>

You can update table configuration for partitioning schema with an SDK with access the `UpdateTable` action.

## Update a table with a partition key
<a name="code-samples.update-table-updating-partition-key"></a>

You can use the following code snippets to update a table with a partition key.

------
#### [  Java  ]

```
    public void updateTableCompositePartitionKeyEnforcement() {
        System.out.println("Updating table");

        UpdateTableRequest updateTableRequest = new UpdateTableRequest();
        updateTableRequest.setDatabaseName(DATABASE_NAME);
        updateTableRequest.setTableName(TABLE_NAME);

        // Can update enforcement level for dimension type partition key with OPTIONAL or REQUIRED enforcement
        final List<PartitionKey> partitionKeyWithDimensionAndRequiredEnforcement = Collections.singletonList(new PartitionKey()
            .withName(COMPOSITE_PARTITION_KEY_DIM_NAME)
            .withType(PartitionKeyType.DIMENSION)
            .withEnforcementInRecord(PartitionKeyEnforcementLevel.REQUIRED));
        Schema schema = new Schema();
        schema.setCompositePartitionKey(partitionKeyWithDimensionAndRequiredEnforcement);
        updateTableRequest.withSchema(schema);

        writeClient.updateTable(updateTableRequest);
        System.out.println("Table updated");
```

------
#### [  Java v2  ]

```
    public void updateTableCompositePartitionKeyEnforcement() {
        System.out.println("Updating table");
        // Can update enforcement level for dimension type partition key with OPTIONAL or REQUIRED enforcement
        final List<PartitionKey> partitionKeyWithDimensionAndRequiredEnforcement = Collections.singletonList(PartitionKey
            .builder()
            .name(COMPOSITE_PARTITION_KEY_DIM_NAME)
            .type(PartitionKeyType.DIMENSION)
            .enforcementInRecord(PartitionKeyEnforcementLevel.REQUIRED)
            .build());
        final Schema schema = Schema.builder()
                .compositePartitionKey(partitionKeyWithDimensionAndRequiredEnforcement).build();
        final UpdateTableRequest updateTableRequest = UpdateTableRequest.builder()
                .databaseName(DATABASE_NAME).tableName(TABLE_NAME).schema(schema).build();

        writeClient.updateTable(updateTableRequest);
        System.out.println("Table updated");
```

------
#### [  Go v1 ]

```
 // Update table partition key enforcement attribute
    updateTableInput := &timestreamwrite.UpdateTableInput{
         DatabaseName: aws.String(*databaseName),
         TableName:    aws.String(*tableName),
         // Can update enforcement level for dimension type partition key with OPTIONAL or REQUIRED enforcement
         Schema: &timestreamwrite.Schema{
             CompositePartitionKey: []*timestreamwrite.PartitionKey{
                 {
                         Name:                aws.String(CompositePartitionKeyDimName),
                         EnforcementInRecord: aws.String("REQUIRED"),
                         Type:                aws.String("DIMENSION"),
                 },
             }},
     }
     updateTableOutput, err := writeSvc.UpdateTable(updateTableInput)
         if err != nil {
             fmt.Println("Error:")
             fmt.Println(err)
         } else {
             fmt.Println("Update table is successful, below is the output:")
             fmt.Println(updateTableOutput)
         }
```

------
#### [  Go v2 ]

```
 // Update table partition key enforcement attribute
         updateTableInput := &timestreamwrite.UpdateTableInput{
             DatabaseName: aws.String(*databaseName),
             TableName:    aws.String(*tableName),
             // Can update enforcement level for dimension type partition key with OPTIONAL or REQUIRED enforcement
             Schema: &types.Schema{
                 CompositePartitionKey: []types.PartitionKey{
                     {
                         Name:                aws.String(CompositePartitionKeyDimName),
                         EnforcementInRecord: types.PartitionKeyEnforcementLevelRequired,
                         Type:                types.PartitionKeyTypeDimension,
                     },
                 }},
         }
         updateTableOutput, err := timestreamBuilder.WriteSvc.UpdateTable(context.TODO(), updateTableInput)
         if err != nil {
             fmt.Println("Error:")
             fmt.Println(err)
         } else {
             fmt.Println("Update table is successful, below is the output:")
             fmt.Println(updateTableOutput)
         }
```

------
#### [  Python  ]

```
    def update_table(self):
        print('Updating table')
        try:
            # Can update enforcement level for dimension type partition key with OPTIONAL or REQUIRED enforcement
            partition_key_with_dimension_and_required_enforcement = [
                {
                    'Type': 'DIMENSION', 
                    'Name': COMPOSITE_PARTITION_KEY_DIM_NAME, 
                    'EnforcementInRecord': 'REQUIRED'
                }
            ]
            schema = {
                'CompositePartitionKey': partition_key_with_dimension_and_required_enforcement
            }
            self.client.update_table(DatabaseName=DATABASE_NAME, TableName=TABLE_NAME,
                                     Schema=schema)
            print('Table updated.')
        except Exception as err:
            print('Update table failed:', err)
```

------

# Advantages of customer-defined partition keys
<a name="customer-defined-partition-keys-advantages"></a>

**Enhanced query performance: **Customer-defined partition keys enable you to optimize your query execution and improve overall query performance. By defining partition keys that align with your query patterns, you can minimize data scanning and optimize data pruning, resulting in lower query latency.

**Better long term performance predictability: **Customer-defined partition keys allow customers to distribute data evenly across partitions, improving the efficiency of data management. This will ensure that your query performance remains stable as your data stored scales over time.

# Limitations of customer-defined partition keys
<a name="customer-defined-partition-keys-limitations"></a>

As a Timestream for LiveAnalytics user, it's important to keep in mind the limitations around a customer partition key. Firstly, it requires a good understanding of your workload and query patterns. This means that you should have a clear idea of which dimensions are most frequently use as main filtering conditions in queries and have high cardinality to make the most effective use of partition keys.

Secondly, partition keys need to be defined at the time of table creation and cannot be added to existing tables. This means that you should carefully consider your partitioning strategy before creating a table to ensure that it aligns with your business needs.

Lastly, it's important to note that once the table has been created, you cannot change the partition key afterwards. This means that you should thoroughly test and evaluate your partitioning strategy before committing to it. With these limitations in mind, Timestream's customer-defined partition key can greatly improve query performance and long term satisfaction.

# Customer-defined partition keys and low cardinality dimensions
<a name="customer-defined-partition-keys-low-cardinality-dimensions"></a>

If you decide to use a partition key with very low cardinality, such as a specific region or state, it is important to note that the data for for other entities such as `customerID`, `ProductCategory`, and others, could end up spread across too many partitions sometimes with little or no data present. This can lead to inefficient query execution and decreased performance.

To avoid this, we recommend you choose dimensions that are not only part of your key filtering condition but have higher cardinality. This will help ensure that the data is evenly distributed across the partitions and improve query performance.

# Creating partition keys for existing tables
<a name="customer-defined-partition-keys-creating"></a>

If you already have tables in Timestream for LiveAnalytics and want to use customer-defined partition keys, you will need to migrate your data into a new table with the desired partitioning schema definition. This can be done using export to S3 and batch load together, which involves exporting the data from the existing table to S3, modifying the data to include the partition key (if necessary) and adding headers to your CSV files, and then importing the data into a new table with the desired partitioning schema defined. Keep in mind that this method can be time consuming and costly, especially for large tables.

Alternatively, you can use scheduled queries to migrate your data to a new table with the desired partitioning schema. This method involves creating a scheduled query that reads from the existing table and writes to the new table. The scheduled query can be set up to run on a regular basis until all the data has been migrated. Keep in mind that you will be charged for reading and writing the data during the migration process.

# Timestream for LiveAnalytics schema validation with custom composite partition keys
<a name="customer-defined-partition-keys-schema-validation"></a>

Schema validation in Timestream for LiveAnalytics helps ensure that data ingested into the database complies with the specified schema, minimizing ingestion errors and improving data quality. In particular, schema validation is especially useful when adopting customer-defined partition key with the goal of optimizing your query performance.

## What is Timestream for LiveAnalytics schema validation with customer-defined partition keys?
<a name="customer-defined-partition-keys-schema-validation-what-is"></a>

Timestream for LiveAnalytics schema validation is a feature that validates data being ingested into a Timestream for LiveAnalytics table based on a predefined schema. This schema defines the data model, including partition key, data types, and constraints for the records being inserted.

When using a customer-defined partition key, schema validation becomes even more crucial. Partition keys allow you to specify a partition key, which determines how your data is stored in Timestream for LiveAnalytics. By validating the incoming data against the schema with a custom partition key, you can enforce data consistency, detect errors early, and improve the overall quality of the data stored in Timestream for LiveAnalytics.

## How to Use Timestream for LiveAnalytics schema validation with custom composite partition keys
<a name="customer-defined-partition-keys-schema-validation-using"></a>

To use Timestream for LiveAnalytics schema validation with custom composite partition keys, follow these steps:

**Think about what your query patterns will look like: **To properly choose and define the schema for your Timestream for LiveAnalytics table you should start with your query requirements.

**Specify custom composite partition keys: **When creating the table, specify a custom partition key. This key determines the attribute that will be used to partition the table data. You can choose between dimension keys and measure keys for partitioning. A dimension key partitions data based on a dimension name, while a measure key partitions data based on the measure name.

**Set enforcement levels: **To ensure proper data partitioning and the benefits that come with it, Amazon Timestream for LiveAnalytics allows you to set enforcement levels for each partition key in your schema. The enforcement level determines whether the partition key dimension is required or optional when ingesting records. You can choose between two options: `REQUIRED`, which means the partition key must be present in the ingested record, and `OPTIONAL`, which means the partition key doesn't have to be present. It is recommended that you use the `REQUIRED` enforcement level when using a customer-defined partition to ensure that your data is properly partitioned and you get the full benefits of this feature. Additionally, you can change the enforcement level configuration at any time after the schema creation to adjust to your data ingestion requirements.

**Ingest data: **When ingesting data into the Timestream for LiveAnalytics table, the schema validation process will check the records against the defined schema with custom composite partition keys. If the records do not adhere to the schema, Timestream for LiveAnalytics will return a validation error.

**Handle validation errors:** In case of validation errors, Timestream for LiveAnalytics will return a `ValidationException` or a `RejectedRecordsException`, depending on the type of error. Make sure to handle these exceptions in your application and take appropriate action, such as fixing the incorrect records and retrying the ingestion.

**Update enforcement levels: **If necessary, you can update the enforcement level of partition keys after table creation using the `UpdateTable` action. However, it's important to note that some aspects of the partition key configuration, such as the name, and type, cannot be changed after table creation. If you change the enforcement level from `REQUIRED` to `OPTIONAL`, all records will be accepted regardless of the presence of the attribute selected as the customer-defined partition key. Conversely, if you change the enforcement level from `OPTIONAL` to `REQUIRED`, you may start seeing 4xx write errors for records that don't meet this condition. Therefore, it's essential to choose the appropriate enforcement level for your use case when creating your table, based on your data's partitioning requirements.

## When to use Timestream for LiveAnalytics schema validation with custom composite partition keys
<a name="customer-defined-partition-keys-schema-validation-when-to-use"></a>

Timestream for LiveAnalytics schema validation with custom composite partition keys should be used in scenarios where data consistency, quality, and optimized partitioning are crucial. By enforcing a schema during data ingestion, you can prevent errors and inconsistencies that might lead to incorrect analysis or loss of valuable insights.

## Interaction with batch load jobs
<a name="customer-defined-partition-keys-schema-validation-when-to-use-batch-load"></a>

When setting up a batch load job to import data into a table with a customer-defined partition key, there are a few scenarios that could affect the process:

1. If the enforcement level is set to `OPTIONAL`, an alert will be displayed on the console during the creation flow if the partition key is not mapped during job configuration. This alert will not appear when using the API or CLI.

1. If the enforcement level is set to `REQUIRED`, the job creation will be rejected unless the partition key is mapped to a source data column.

1. If the enforcement level is changed to `REQUIRED` after the job is created, the job will continue to execute, but any records that do not have the proper mapping for the partition key will be rejected with a 4xx error.

## Interaction with scheduled query
<a name="customer-defined-partition-keys-schema-validation-when-to-use-scheduled-query"></a>

When setting up a scheduled query job for calculating and storing aggregates, rollups, and other forms of preprocessed data into a table with a customer-defined partition key, there are a few scenarios that could affect the process:

1. If the enforcement level is set to `OPTIONAL`, an alert will be displayed if the partition key is not mapped during job configuration. This alert will not appear when using the API or CLI.

1. If the enforcement level is set to `REQUIRED`, the job creation will be rejected unless the partition key is mapped to a source data column.

1. If the enforcement level is changed to `REQUIRED` after the job is created and the scheduled query results does not contain the partition key dimension, all the next iterations of the job will fail.

# Adding tags and labels to resources
<a name="tagging-keyspaces"></a>

 You can label Amazon Timestream for LiveAnalytics resources using *tags*. Tags let you categorize your resources in different ways—for example, by purpose, owner, environment, or other criteria. Tags can help you do the following: 
+  Quickly identify a resource based on the tags that you assigned to it. 
+  See AWS bills broken down by tags. 

 Tagging is supported by AWS services like Amazon Elastic Compute Cloud (Amazon EC2), Amazon Simple Storage Service (Amazon S3), Timestream for LiveAnalytics, and more. Efficient tagging can provide cost insights by enabling you to create reports across services that carry a specific tag. 

 To get started with tagging, do the following: 

1.  Understand [Tagging restrictions](https://docs.aws.amazon.com/timestream/latest/developerguide/TaggingRestrictions.html). 

1.  Create tags by using [Tagging operations](https://docs.aws.amazon.com/timestream/latest/developerguide/Tagging.Operations.html). 

 Finally, it is good practice to follow optimal tagging strategies. For information, see [AWS Tagging Strategies](https://d0.awsstatic.com/aws-answers/AWS_Tagging_Strategies.pdf). 

# Tagging restrictions
<a name="TaggingRestrictions"></a>

 Each tag consists of a key and a value, both of which you define. The following restrictions apply: 
+  Each Timestream for LiveAnalytics table can have only one tag with the same key. If you try to add an existing tag, the existing tag value is updated to the new value. 
+ A value acts as a descriptor within a tag category. In Timestream for LiveAnalytics the value cannot be empty or null.
+  Tag keys and values are case sensitive. 
+  The maximum key length is 128 Unicode characters. 
+ The maximum value length is 256 Unicode characters. 
+  The allowed characters are letters, white space, and numbers, plus the following special characters: `+ - = . _ : /` 
+  The maximum number of tags per resource is 50.
+  AWS-assigned tag names and values are automatically assigned the `aws:` prefix, which you can't assign. AWS-assigned tag names don't count toward the tag limit of 50. User-assigned tag names have the prefix `user:` in the cost allocation report. 
+  You can't backdate the application of a tag. 

# Tagging operations
<a name="Tagging.Operations"></a>

You can add, list, edit, or delete tags for databases and tables using the Amazon Timestream for LiveAnalytics console, query language, or the AWS Command Line Interface (AWS CLI). 

**Topics**
+ [Adding tags to new or existing databases and tables using the console](#Tagging.Operations.using-console)

## Adding tags to new or existing databases and tables using the console
<a name="Tagging.Operations.using-console"></a>

You can use the Timestream for LiveAnalytics console to add tags to new databases, tables and scheduled queries when you create them. You can also add, edit, or delete tags for existing tables.

**To tag databases when creating them (console)**

1. Open the Timestream console at [https://console.aws.amazon.com/timestream](https://console.aws.amazon.com/timestream).

1. In the navigation pane, choose **Databases**, and then choose **Create database**.

1. On the **Create database** page, provide a name for the database. Enter a key and value for the tag, and then choose **Add new tag**.

1. Choose **Create database**.

**To tag tables when creating them (console)**

1. Open the Timestream console at [https://console.aws.amazon.com/timestream](https://console.aws.amazon.com/timestream).

1. In the navigation pane, choose **Tables**, and then choose **Create table**.

1. On the **Create Timestream for LiveAnalytics table** page, provide a name for the table. Enter a key and value for the tag, and choose **Add new tag**. 

1. Choose **Create table**.

**To tag scheduled queries when creating them (console)**

1. Open the Timestream console at [https://console.aws.amazon.com/timestream](https://console.aws.amazon.com/timestream).

1. In the navigation pane, choose **Scheduled queries**, and then choose **Create scheduled query**.

1. On the **Step 3. Configure query settings** page, choose **Add new tag**. Enter a key and value for the tag. Choose **Add new tag** to add additional tags.

1. Choose **Next**.

**To tag existing resources (console)**

1. Open the Timestream console at [https://console.aws.amazon.com/timestream](https://console.aws.amazon.com/timestream).

1. In the navigation pane, choose **Databases**, **Tables** or **Scheduled queries**.

1. Choose a database or table in the list. Then choose **Manage tags** to add, edit, or delete your tags.

For information about tag structure, see [Tagging restrictions](TaggingRestrictions.md). 

# Security in Timestream for LiveAnalytics
<a name="security"></a>

Cloud security at AWS is the highest priority. As an AWS customer, you benefit from a data center and network architecture that is built to meet the requirements of the most security-sensitive organizations.

Security is a shared responsibility between AWS and you. The [shared responsibility model](https://aws.amazon.com/compliance/shared-responsibility-model/) describes this as security *of* the cloud and security *in* the cloud:
+ **Security of the cloud** – AWS is responsible for protecting the infrastructure that runs AWS services in the AWS Cloud. AWS also provides you with services that you can use securely. The effectiveness of our security is regularly tested and verified by third-party auditors as part of the [AWS compliance programs](https://aws.amazon.com/compliance/programs/). To learn about the compliance programs that apply to Timestream for LiveAnalytics, see [AWS Services in Scope by Compliance Program](https://aws.amazon.com/compliance/services-in-scope/).
+ **Security in the cloud** – Your responsibility is determined by the AWS service that you use. You are also responsible for other factors including the sensitivity of your data, your organization's requirements, and applicable laws and regulations. 

This documentation will help you understand how to apply the shared responsibility model when using Timestream for LiveAnalytics. The following topics show you how to configure Timestream for LiveAnalytics to meet your security and compliance objectives. You'll also learn how to use other AWS services that can help you to monitor and secure your Timestream for LiveAnalytics resources. 

**Topics**
+ [Data protection in Timestream for LiveAnalytics](data-protection.md)
+ [Identity and access management for Amazon Timestream for LiveAnalytics](security-iam.md)
+ [Logging and monitoring in Timestream for LiveAnalytics](monitoring.md)
+ [Resilience in Amazon Timestream Live Analytics](disaster-recovery-resiliency.md)
+ [Infrastructure security in Amazon Timestream Live Analytics](infrastructure-security.md)
+ [Configuration and vulnerability analysis in Timestream](ConfigAndVulnerability.md)
+ [Incident response in Timestream for LiveAnalytics](IncidentResponse.md)
+ [VPC endpoints (AWS PrivateLink)](VPCEndpoints.md)
+ [Security best practices for Amazon Timestream for LiveAnalytics](best-practices-security.md)

# Data protection in Timestream for LiveAnalytics
<a name="data-protection"></a>

The AWS [shared responsibility model](https://aws.amazon.com/compliance/shared-responsibility-model/) applies to data protection in Amazon Timestream Live Analytics. As described in this model, AWS is responsible for protecting the global infrastructure that runs all of the AWS Cloud. You are responsible for maintaining control over your content that is hosted on this infrastructure. You are also responsible for the security configuration and management tasks for the AWS services that you use. For more information about data privacy, see the [Data Privacy FAQ](https://aws.amazon.com/compliance/data-privacy-faq/). For information about data protection in Europe, see the [AWS Shared Responsibility Model and GDPR](https://aws.amazon.com/blogs/security/the-aws-shared-responsibility-model-and-gdpr/) blog post on the *AWS Security Blog*.

For data protection purposes, we recommend that you protect AWS account credentials and set up individual users with AWS IAM Identity Center or AWS Identity and Access Management (IAM). That way, each user is given only the permissions necessary to fulfill their job duties. We also recommend that you secure your data in the following ways:
+ Use multi-factor authentication (MFA) with each account.
+ Use SSL/TLS to communicate with AWS resources. We require TLS 1.2 and recommend TLS 1.3.
+ Set up API and user activity logging with AWS CloudTrail. For information about using CloudTrail trails to capture AWS activities, see [Working with CloudTrail trails](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-trails.html) in the *AWS CloudTrail User Guide*.
+ Use AWS encryption solutions, along with all default security controls within AWS services.
+ Use advanced managed security services such as Amazon Macie, which assists in discovering and securing sensitive data that is stored in Amazon S3.
+ If you require FIPS 140-3 validated cryptographic modules when accessing AWS through a command line interface or an API, use a FIPS endpoint. For more information about the available FIPS endpoints, see [Federal Information Processing Standard (FIPS) 140-3](https://aws.amazon.com/compliance/fips/).

We strongly recommend that you never put confidential or sensitive information, such as your customers' email addresses, into tags or free-form text fields such as a **Name** field. This includes when you work with Timestream Live Analytics or other AWS services using the console, API, AWS CLI, or AWS SDKs. Any data that you enter into tags or free-form text fields used for names may be used for billing or diagnostic logs. If you provide a URL to an external server, we strongly recommend that you do not include credentials information in the URL to validate your request to that server.

For more detailed information on Timestream for LiveAnalytics data protection topics like Encryption at Rest and Key Management, select any of the available topics below.

**Topics**
+ [Encryption at rest](EncryptionAtRest.md)
+ [Encryption in transit](EncryptionInTransit.md)
+ [Key management](KeyManagement.md)

# Encryption at rest
<a name="EncryptionAtRest"></a>

Timestream for LiveAnalytics encryption at rest provides enhanced security by encrypting all your data at rest using encryption keys stored in [AWS Key Management Service (AWS KMS)](https://aws.amazon.com/kms/). This functionality helps reduce the operational burden and complexity involved in protecting sensitive data. With encryption at rest, you can build security-sensitive applications that meet strict encryption compliance and regulatory requirements. 
+ Encryption is turned on by default on your Timestream for LiveAnalytics database, and cannot be turned off. The industry standard AES-256 encryption algorithm is the default encryption algorithm used.
+ AWS KMS is required for encryption at rest in Timestream for LiveAnalytics.
+ You cannot encrypt only a subset of items in a table.
+  You don't need to modify your database client applications to use encryption. 

 If you do not provide a key, Timestream for LiveAnalytics creates and uses an AWS KMS key named `alias/aws/timestream` in your account. 

You may use your own customer managed key in KMS to encrypt your Timestream for LiveAnalytics data. For more information on keys in Timestream for LiveAnalytics, see [Key management](KeyManagement.md). 

 Timestream for LiveAnalytics stores your data in two storage tiers, memory store and magnetic store. Memory store data is encrypted using a Timestream for LiveAnalytics service key. Magnetic store data is encrypted using your AWS KMS key. 

The Timestream Query service requires credentials to access your data. These credentials are encrypted using your KMS key.

**Note**  
Timestream for LiveAnalytics doesn't call AWS KMS for every Decrypt operation. Instead, it maintains a local cache of keys for 5 minutes with active traffic. Any permission changes are propagated through the Timestream for LiveAnalytics system with eventual consistency within at most 5 minutes.

# Encryption in transit
<a name="EncryptionInTransit"></a>

All your Timestream Live Analytics data is encrypted in transit. By default, all communications to and from Timestream for LiveAnalytics are protected by using Transport Layer Security (TLS) encryption. 

# Key management
<a name="KeyManagement"></a>

 You can manage keys for Amazon Timestream Live Analytics using the [AWS Key Management Service (AWS KMS)](https://docs.aws.amazon.com/kms/latest/developerguide/). **Timestream Live Analytics requires the use of KMS to encrypt your data.** You have the following options for key management, depending on how much control you require over your keys: 

**Database and table resources**
+  *Timestream Live Analytics-managed key: * If you do not provide a key, Timestream Live Analytics will create a `alias/aws/timestream` key using KMS. 
+  *Customer managed key: * KMS customer managed keys are supported. Choose this option if you require more control over the permissions and lifecycle of your keys, including the ability to have them automatically rotated on an annual basis.

**Scheduled query resource**
+  *Timestream Live Analytics-owned key: * If you do not provide a key, Timestream Live Analytics will use its own a KMS key to encrypt the Query resource, this key is present in timestream account. See [AWS owned keys](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-owned-cmk) in the KMS developer guide for more details.
+  *Customer managed key: * KMS customer managed keys are supported. Choose this option if you require more control over the permissions and lifecycle of your keys, including the ability to have them automatically rotated on an annual basis.

KMS keys in an external key store (XKS) are not supported.

# Identity and access management for Amazon Timestream for LiveAnalytics
<a name="security-iam"></a>

AWS Identity and Access Management (IAM) is an AWS service that helps an administrator securely control access to AWS resources. IAM administrators control who can be *authenticated* (signed in) and *authorized* (have permissions) to use Timestream for LiveAnalytics resources. IAM is an AWS service that you can use with no additional charge.

**Topics**
+ [Audience](#security_iam_audience)
+ [Authenticating with identities](#security_iam_authentication)
+ [Managing access using policies](#security_iam_access-manage)
+ [How Amazon Timestream for LiveAnalytics works with IAM](security_iam_service-with-iam.md)
+ [AWS managed policies for Amazon Timestream Live Analytics](security-iam-awsmanpol.md)
+ [Amazon Timestream for LiveAnalytics identity-based policy examples](security_iam_id-based-policy-examples.md)
+ [Troubleshooting Amazon Timestream for LiveAnalytics identity and access](security_iam_troubleshoot.md)

## Audience
<a name="security_iam_audience"></a>

How you use AWS Identity and Access Management (IAM) differs based on your role:
+ **Service user** - request permissions from your administrator if you cannot access features (see [Troubleshooting Amazon Timestream for LiveAnalytics identity and access](security_iam_troubleshoot.md))
+ **Service administrator** - determine user access and submit permission requests (see [How Amazon Timestream for LiveAnalytics works with IAM](security_iam_service-with-iam.md))
+ **IAM administrator** - write policies to manage access (see [Amazon Timestream for LiveAnalytics identity-based policy examples](security_iam_id-based-policy-examples.md))

## Authenticating with identities
<a name="security_iam_authentication"></a>

Authentication is how you sign in to AWS using your identity credentials. You must be authenticated as the AWS account root user, an IAM user, or by assuming an IAM role.

You can sign in as a federated identity using credentials from an identity source like AWS IAM Identity Center (IAM Identity Center), single sign-on authentication, or Google/Facebook credentials. For more information about signing in, see [How to sign in to your AWS account](https://docs.aws.amazon.com/signin/latest/userguide/how-to-sign-in.html) in the *AWS Sign-In User Guide*.

For programmatic access, AWS provides an SDK and CLI to cryptographically sign requests. For more information, see [AWS Signature Version 4 for API requests](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv.html) in the *IAM User Guide*.

### IAM users and groups
<a name="security_iam_authentication-iamuser"></a>

An *[IAM user](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html)* is an identity with specific permissions for a single person or application. We recommend using temporary credentials instead of IAM users with long-term credentials. For more information, see [Require human users to use federation with an identity provider to access AWS using temporary credentials](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#bp-users-federation-idp) in the *IAM User Guide*.

An [https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_groups.html) specifies a collection of IAM users and makes permissions easier to manage for large sets of users. For more information, see [Use cases for IAM users](https://docs.aws.amazon.com/IAM/latest/UserGuide/gs-identities-iam-users.html) in the *IAM User Guide*.

### IAM roles
<a name="security_iam_authentication-iamrole"></a>

An *[IAM role](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html)* is an identity with specific permissions that provides temporary credentials. You can assume a role by [switching from a user to an IAM role (console)](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-console.html) or by calling an AWS CLI or AWS API operation. For more information, see [Methods to assume a role](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_manage-assume.html) in the *IAM User Guide*.

IAM roles are useful for federated user access, temporary IAM user permissions, cross-account access, cross-service access, and applications running on Amazon EC2. For more information, see [Cross account resource access in IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies-cross-account-resource-access.html) in the *IAM User Guide*.

## Managing access using policies
<a name="security_iam_access-manage"></a>

You control access in AWS by creating policies and attaching them to AWS identities or resources. A policy defines permissions when associated with an identity or resource. AWS evaluates these policies when a principal makes a request. Most policies are stored in AWS as JSON documents. For more information about JSON policy documents, see [Overview of JSON policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#access_policies-json) in the *IAM User Guide*.

Using policies, administrators specify who has access to what by defining which **principal** can perform **actions** on what **resources**, and under what **conditions**.

By default, users and roles have no permissions. An IAM administrator creates IAM policies and adds them to roles, which users can then assume. IAM policies define permissions regardless of the method used to perform the operation.

### Identity-based policies
<a name="security_iam_access-manage-id-based-policies"></a>

Identity-based policies are JSON permissions policy documents that you attach to an identity (user, group, or role). These policies control what actions identities can perform, on which resources, and under what conditions. To learn how to create an identity-based policy, see [Define custom IAM permissions with customer managed policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create.html) in the *IAM User Guide*.

Identity-based policies can be *inline policies* (embedded directly into a single identity) or *managed policies* (standalone policies attached to multiple identities). To learn how to choose between managed and inline policies, see [Choose between managed policies and inline policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies-choosing-managed-or-inline.html) in the *IAM User Guide*.

### Resource-based policies
<a name="security_iam_access-manage-resource-based-policies"></a>

Resource-based policies are JSON policy documents that you attach to a resource. Examples include IAM *role trust policies* and Amazon S3 *bucket policies*. In services that support resource-based policies, service administrators can use them to control access to a specific resource. You must [specify a principal](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_principal.html) in a resource-based policy.

Resource-based policies are inline policies that are located in that service. You can't use AWS managed policies from IAM in a resource-based policy.

### Access control lists (ACLs)
<a name="security_iam_access-manage-acl"></a>

Access control lists (ACLs) control which principals (account members, users, or roles) have permissions to access a resource. ACLs are similar to resource-based policies, although they do not use the JSON policy document format.

Amazon S3, AWS WAF, and Amazon VPC are examples of services that support ACLs. To learn more about ACLs, see [Access control list (ACL) overview](https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html) in the *Amazon Simple Storage Service Developer Guide*.

### Other policy types
<a name="security_iam_access-manage-other-policies"></a>

AWS supports additional policy types that can set the maximum permissions granted by more common policy types:
+ **Permissions boundaries** – Set the maximum permissions that an identity-based policy can grant to an IAM entity. For more information, see [Permissions boundaries for IAM entities](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html) in the *IAM User Guide*.
+ **Service control policies (SCPs)** – Specify the maximum permissions for an organization or organizational unit in AWS Organizations. For more information, see [Service control policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html) in the *AWS Organizations User Guide*.
+ **Resource control policies (RCPs)** – Set the maximum available permissions for resources in your accounts. For more information, see [Resource control policies (RCPs)](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_rcps.html) in the *AWS Organizations User Guide*.
+ **Session policies** – Advanced policies passed as a parameter when creating a temporary session for a role or federated user. For more information, see [Session policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session) in the *IAM User Guide*.

### Multiple policy types
<a name="security_iam_access-manage-multiple-policies"></a>

When multiple types of policies apply to a request, the resulting permissions are more complicated to understand. To learn how AWS determines whether to allow a request when multiple policy types are involved, see [Policy evaluation logic](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html) in the *IAM User Guide*.

# How Amazon Timestream for LiveAnalytics works with IAM
<a name="security_iam_service-with-iam"></a>

Before you use IAM to manage access to Timestream for LiveAnalytics, you should understand what IAM features are available to use with Timestream for LiveAnalytics. To get a high-level view of how Timestream for LiveAnalytics and other AWS services work with IAM, see [AWS Services That Work with IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html) in the *IAM User Guide*.

**Topics**
+ [Timestream for LiveAnalytics identity-based policies](#security_iam_service-with-iam-id-based-policies)
+ [Timestream for LiveAnalytics resource-based policies](#security_iam_service-with-iam-resource-based-policies)
+ [Authorization based on Timestream for LiveAnalytics tags](#security_iam_service-with-iam-tags)
+ [Timestream for LiveAnalytics IAM roles](#security_iam_service-with-iam-roles)

## Timestream for LiveAnalytics identity-based policies
<a name="security_iam_service-with-iam-id-based-policies"></a>

With IAM identity-based policies, you can specify allowed or denied actions and resources as well as the conditions under which actions are allowed or denied. Timestream for LiveAnalytics supports specific actions and resources, and condition keys. To learn about all of the elements that you use in a JSON policy, see [IAM JSON Policy Elements Reference](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements.html) in the *IAM User Guide*.

### Actions
<a name="security_iam_service-with-iam-id-based-policies-actions"></a>

Administrators can use AWS JSON policies to specify who has access to what. That is, which **principal** can perform **actions** on what **resources**, and under what **conditions**.

The `Action` element of a JSON policy describes the actions that you can use to allow or deny access in a policy. Include actions in a policy to grant permissions to perform the associated operation.

 You can specify the following actions in the Action element of an IAM policy statement. Use policies to grant permissions to perform an operation in AWS. When you use an action in a policy, you usually allow or deny access to the API operation, CLI command or SQL command with the same name. 

 In some cases, a single action controls access to an API operation as well as SQL command. Alternatively, some operations require several different actions. 

For a list of supported Timestream for LiveAnalytics `Action`'s, see the table below:

**Note**  
For all database-specific `Actions`, you can specify a database ARN to limit the action to a particular database.


| Actions | Description | Access level | Resource types (\$1required) | 
| --- | --- | --- | --- | 
|  DescribeEndpoints  |  Returns the Timestream endpoint that subsequent requests must be made to.   |  All  |  \$1  | 
|  Select  |  Run queries on Timestream that select data from one or more tables. [See this note for a detailed explanation](#security_iam_service-with-iam-id-based-policies-actions.select-vs-selectvalues)  |  Read  |  table\$1  | 
|  CancelQuery  |  Cancel a query.  |  Read  |  \$1  | 
|  ListTables  |  Get the list of tables.  |  List  |  database\$1  | 
|  ListDatabases  |  Get the list of databases.  |  List  |  \$1  | 
|  ListMeasures  |  Get the list of measures.  |  Read  |  table\$1  | 
|  DescribeTable  |  Get the table description.  |  Read  |  table\$1  | 
|  DescribeDatabase  |  Get the database description.  |  Read  |  database\$1  | 
|  SelectValues  |  Run queries that do not require a particular resource to be specified. [See this note for a detailed explanation](#security_iam_service-with-iam-id-based-policies-actions.select-vs-selectvalues).  |  Read  |  \$1  | 
|  WriteRecords  |  Insert data into Timestream.  |  Write  |  table\$1  | 
|  CreateTable  |  Create a table.  |  Write  |  database\$1  | 
|  CreateDatabase  |  Create a database.  |  Write  |  \$1  | 
|  DeleteDatabase  |  Delete a database.  |  Write  |  \$1  | 
|  UpdateDatabase  |  Update a database.  |  Write  |  \$1  | 
|  DeleteTable  |  Delete a table.  |  Write  |  database\$1  | 
|  UpdateTable  |  Update a table.   |  Write  |  database\$1  | 

#### SelectValues vs. select:
<a name="security_iam_service-with-iam-id-based-policies-actions.select-vs-selectvalues"></a>

`SelectValues` is an `Action` that is used for queries that *do not* require a resource. An example of a query that does not require a resource is as follows:

```
SELECT 1
```

Notice that this query does not refer to a particular Timestream for LiveAnalytics resource. Consider another example:

```
SELECT now()
```

This query returns the current timestamp using the `now()` function, but does not require a resource to be specified. `SelectValues` is often used for testing, so that Timestream for LiveAnalytics can run queries without resources. Now, consider a `Select` query:

```
SELECT * FROM database.table
```

This type of query requires a resource, specifcially an Timestream for LiveAnalytics `table` , so that the specified data can be fetched from the table.

### Resources
<a name="security_iam_service-with-iam-id-based-policies-resources"></a>

Administrators can use AWS JSON policies to specify who has access to what. That is, which **principal** can perform **actions** on what **resources**, and under what **conditions**.

The `Resource` JSON policy element specifies the object or objects to which the action applies. As a best practice, specify a resource using its [Amazon Resource Name (ARN)](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html). For actions that don't support resource-level permissions, use a wildcard (\$1) to indicate that the statement applies to all resources.

```
"Resource": "*"
```

In Timestream for LiveAnalytics databases and tables can be used in the `Resource` element of IAM permissions.

The Timestream for LiveAnalytics database resource has the following ARN:

```
arn:${Partition}:timestream:${Region}:${Account}:database/${DatabaseName}
```

The Timestream for LiveAnalytics table resource has the following ARN:

```
arn:${Partition}:timestream:${Region}:${Account}:database/${DatabaseName}/table/${TableName}
```

For more information about the format of ARNs, see [Amazon Resource Names (ARNs) and AWS Service Namespaces](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html).

For example, to specify the `database` keyspace in your statement, use the following ARN:

```
"Resource": "arn:aws:timestream:us-east-1:123456789012:database/mydatabase"
```

To specify all databases that belong to a specific account, use the wildcard (\$1):

```
"Resource": "arn:aws:timestream:us-east-1:123456789012:database/*"
```

Some Timestream for LiveAnalytics actions, such as those for creating resources, cannot be performed on a specific resource. In those cases, you must use the wildcard (\$1).

```
"Resource": "*"
```

### Condition keys
<a name="security_iam_service-with-iam-id-based-policies-conditionkeys"></a>

Timestream for LiveAnalytics does not provide any service-specific condition keys, but it does support using some global condition keys. To see all AWS global condition keys, see [AWS Global Condition Context Keys](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html) in the *IAM User Guide*.

### Examples
<a name="security_iam_service-with-iam-id-based-policies-examples"></a>

To view examples of Timestream for LiveAnalytics identity-based policies, see [Amazon Timestream for LiveAnalytics identity-based policy examples](security_iam_id-based-policy-examples.md).

## Timestream for LiveAnalytics resource-based policies
<a name="security_iam_service-with-iam-resource-based-policies"></a>

Timestream for LiveAnalytics does not support resource-based policies. To view an example of a detailed resource-based policy page, see [https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html).

## Authorization based on Timestream for LiveAnalytics tags
<a name="security_iam_service-with-iam-tags"></a>

You can manage access to your Timestream for LiveAnalytics resources by using tags. To manage resource access based on tags, you provide tag information in the [condition element](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html) of a policy using the `timestream:ResourceTag/key-name`, `aws:RequestTag/key-name`, or `aws:TagKeys` condition keys. For more information about tagging Timestream for LiveAnalytics resources, see [Adding tags and labels to resources](tagging-keyspaces.md).

To view example identity-based policies for limiting access to a resource based on the tags on that resource, see [Timestream for LiveAnalytics resource access based on tags](security_iam_id-based-policy-examples.md#security_iam_id-based-policy-examples-tags).

## Timestream for LiveAnalytics IAM roles
<a name="security_iam_service-with-iam-roles"></a>

An [IAM role](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) is an entity within your AWS account that has specific permissions.

### Using temporary credentials with Timestream for LiveAnalytics
<a name="security_iam_service-with-iam-roles-tempcreds"></a>

You can use temporary credentials to sign in with federation, assume an IAM role, or to assume a cross-account role. You obtain temporary security credentials by calling AWS STS API operations such as [AssumeRole](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html) or [GetFederationToken](https://docs.aws.amazon.com/STS/latest/APIReference/API_GetFederationToken.html). 

### Service-linked roles
<a name="security_iam_service-with-iam-roles-service-linked"></a>

Timestream for LiveAnalytics does not support service-linked roles.

### Service roles
<a name="security_iam_service-with-iam-roles-service"></a>

Timestream for LiveAnalytics does not support service roles.

# AWS managed policies for Amazon Timestream Live Analytics
<a name="security-iam-awsmanpol"></a>







An AWS managed policy is a standalone policy that is created and administered by AWS. AWS managed policies are designed to provide permissions for many common use cases so that you can start assigning permissions to users, groups, and roles.

Keep in mind that AWS managed policies might not grant least-privilege permissions for your specific use cases because they're available for all AWS customers to use. We recommend that you reduce permissions further by defining [ customer managed policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#customer-managed-policies) that are specific to your use cases.

You cannot change the permissions defined in AWS managed policies. If AWS updates the permissions defined in an AWS managed policy, the update affects all principal identities (users, groups, and roles) that the policy is attached to. AWS is most likely to update an AWS managed policy when a new AWS service is launched or new API operations become available for existing services.

For more information, see [AWS managed policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#aws-managed-policies) in the *IAM User Guide*.

**Topics**
+ [AmazonTimestreamInfluxDBFullAccess](#security-iam-awsmanpol-AmazonTimestreamInfluxDBFullAccess)
+ [AmazonTimestreamReadOnlyAccess](#security-iam-awsmanpol-AmazonTimestreamReadOnlyAccess)
+ [AmazonTimestreamConsoleFullAccess](#security-iam-awsmanpol-AmazonTimestreamConsoleFullAccess)
+ [AmazonTimestreamFullAccess](#security-iam-awsmanpol-AmazonTimestreamFullAccess)
+ [Policy updates](#security-iam-awsmanpol-updates)









## AWS managed policy: AmazonTimestreamInfluxDBFullAccess
<a name="security-iam-awsmanpol-AmazonTimestreamInfluxDBFullAccess"></a>

You can attach `AmazonTimestreamInfluxDBFullAccess` to your users, groups, and roles. The policy access to create, update, delete and list Amazon Timestream InfluxDB instances.

**Permission details**  
This policy includes the following permission:
+ `Amazon Timestream` – Provides full administrative access to create, update, delete and list Amazon Timestream InfluxDB instances and create and list parameter groups. 

To review this policy in JSON format, see [AmazonTimestreamInfluxDBFullAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonTimestreamInfluxDBFullAccess.html).

## AWS managed policy: AmazonTimestreamReadOnlyAccess
<a name="security-iam-awsmanpol-AmazonTimestreamReadOnlyAccess"></a>





You can attach `AmazonTimestreamReadOnlyAccess` to your users, groups, and roles. The policy provides read-only access to Amazon Timestream.

**Permission details**  
This policy includes the following permission:
+ `Amazon Timestream` – Provides read-only access to Amazon Timestream. This policy also grants permission to cancel any running query.

To review this policy in JSON format, see [AmazonTimestreamReadOnlyAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonTimestreamReadOnlyAccess.html).

## AWS managed policy: AmazonTimestreamConsoleFullAccess
<a name="security-iam-awsmanpol-AmazonTimestreamConsoleFullAccess"></a>





You can attach `AmazonTimestreamConsoleFullAccess` to your users, groups, and roles.

The policy provides full access to manage Amazon Timestream using the AWS Management Console. This policy also grants permissions for certain AWS KMS operations and operations to manage your saved queries.

**Permission details**  
This policy includes the following permissions:
+ `Amazon Timestream` – Grants principals full access to Amazon Timestream.
+ `AWS KMS` – Allows principals to list aliases and describe keys.
+ `Amazon S3` – Allows principals to list all Amazon S3 buckets.
+ `Amazon SNS` – Allows principals to list Amazon SNS topics.
+ `IAM` – Allows principals to list IAM roles.
+ `DBQMS` – Allows principals to access, create, delete, describe, and update queries. The Database Query Metadata Service (dbqms) is an internal-only service. It provides your recent and saved queries for the query editor on the AWS Management Console for multiple AWS services, including Amazon Timestream.
+ `Pricing` – Allows principals to access pricing estimation for InfluxDB resource configuration during creation.
+ `Marketplace` – Allows principals to access marketplace resources and create agreements for InfluxDB Cluster with Read Replicas creation.

To review this policy in JSON format, see [AmazonTimestreamConsoleFullAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonTimestreamConsoleFullAccess.html).

## AWS managed policy: AmazonTimestreamFullAccess
<a name="security-iam-awsmanpol-AmazonTimestreamFullAccess"></a>





You can attach `AmazonTimestreamFullAccess` to your users, groups, and roles.

The policy provides full access to Amazon Timestream. This policy also grants permissions for certain AWS KMS operations.

**Permission details**  
This policy includes the following permissions:
+ `Amazon Timestream` – Grants principals full access to Amazon Timestream.
+ `AWS KMS` – Allows principals to list aliases and describe keys.
+ `Amazon S3` – Allows principals to list all Amazon S3 buckets.

To review this policy in JSON format, see [AmazonTimestreamFullAccess](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AmazonTimestreamFullAccess.html).

## Timestream Live Analytics updates to AWS managed policies
<a name="security-iam-awsmanpol-updates"></a>



View details about updates to AWS managed policies for Timestream Live Analytics since this service began tracking these changes. For automatic alerts about changes to this page, subscribe to the RSS feed on the [Timestream Live Analytics Document history](doc-history.md) page.




| Change | Description | Date | 
| --- | --- | --- | 
|  [AmazonTimestreamConsoleFullAccess](#security-iam-awsmanpol-AmazonTimestreamConsoleFullAccess) – Update to an existing policy  |  Timestream for InfluxDB has added Influx Enterprise marketplace product ID to the existing `AmazonTimestreamInfluxDBFullAccess` managed policy to support subscription to enterprise marketplace offerings. These permissions are restricted to specific AWS Marketplace products through a condition that limits the access to only certain `ProductIds`. See [AmazonTimestreamInfluxDBFullAccess](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol-influxdb.html#iam.identitybasedpolicies.predefinedpolicies).  | October 17, 2025 | 
|  [AmazonTimestreamConsoleFullAccess](#security-iam-awsmanpol-AmazonTimestreamConsoleFullAccess) – Update to an existing policy  |  Added the AWS Marketplace permissions to the existing `AmazonTimestreamConsoleFullAccess` managed policy to access marketplace resources and create agreements for InfluxDB Cluster with Read Replicas creation. Timestream Live Analytics has also updated this managed policy by adding an `Sid` field. The policy update doesn't impact the usage of the `AmazonTimestreamConsoleFullAccess` managed policy.  | August 20, 2025 | 
|  [AmazonTimestreamConsoleFullAccess](#security-iam-awsmanpol-AmazonTimestreamConsoleFullAccess) – Update to an existing policy  |  Added the `pricing:GetProducts` action to the existing `AmazonTimestreamConsoleFullAccess` managed policy to provide pricing estimations for InfluxDB resource configurations during creation. The policy update doesn't impact the usage of the `AmazonTimestreamConsoleFullAccess` managed policy.  | June 10, 2025 | 
|  [AmazonTimestreamReadOnlyAccess](#security-iam-awsmanpol-AmazonTimestreamReadOnlyAccess) – Update to an existing policy  |  Added the `timestream:DescribeAccountSettings` action to the existing `AmazonTimestreamReadOnlyAccess` managed policy. This action is used for describing AWS account settings. Timestream Live Analytics has also updated this managed policy by adding an `Sid` field. The policy update doesn't impact the usage of the `AmazonTimestreamReadOnlyAccess` managed policy.  | June 03, 2024 | 
|  [AmazonTimestreamReadOnlyAccess](#security-iam-awsmanpol-AmazonTimestreamReadOnlyAccess) – Update to an existing policy  |  Added the `timestream:DescribeBatchLoadTask` and `timestream:ListBatchLoadTasks` actions to the existing `AmazonTimestreamReadOnlyAccess` managed policy. These actions are used when listing and describing batch load tasks. The policy update doesn't impact the usage of the `AmazonTimestreamReadOnlyAccess` managed policy.  | February 24, 2023 | 
|  [AmazonTimestreamReadOnlyAccess](#security-iam-awsmanpol-AmazonTimestreamReadOnlyAccess) – Update to an existing policy  |  Added the `timestream:DescribeScheduledQuery` and `timestream:ListScheduledQueries` actions to the existing `AmazonTimestreamReadOnlyAccess` managed policy. These actions are used when listing and describing existing scheduled queries. The policy update doesn't impact the usage of the `AmazonTimestreamReadOnlyAccess` managed policy.  | November 29, 2021 | 
|  [AmazonTimestreamConsoleFullAccess](#security-iam-awsmanpol-AmazonTimestreamConsoleFullAccess) – Update to an existing policy  |  Added the `s3:ListAllMyBuckets` action to the existing `AmazonTimestreamConsoleFullAccess` managed policy. This action is used when you specify an Amazon S3 bucket for Timestream to log magnetic store write errors. The policy update doesn't impact the usage of the `AmazonTimestreamConsoleFullAccess` managed policy.  | November 29, 2021 | 
|  [AmazonTimestreamFullAccess](#security-iam-awsmanpol-AmazonTimestreamFullAccess) – Update to an existing policy  |  Added the `s3:ListAllMyBuckets` action to the existing `AmazonTimestreamFullAccess` managed policy. This action is used when you specify an Amazon S3 bucket for Timestream to log magnetic store write errors. The policy update doesn't impact the usage of the `AmazonTimestreamFullAccess` managed policy.  | November 29, 2021 | 
|  [AmazonTimestreamConsoleFullAccess](#security-iam-awsmanpol-AmazonTimestreamConsoleFullAccess) – Update to an existing policy  |  Removed redundant actions from the existing `AmazonTimestreamConsoleFullAccess` managed policy. Previously, this policy included a redundant action `dbqms:DescribeQueryHistory`. The updated policy removes the redundant action. The policy update doesn't impact the usage of the `AmazonTimestreamConsoleFullAccess` managed policy.  | April 23, 2021 | 
|  Timestream Live Analytics started tracking changes  |  Timestream Live Analytics started tracking changes for its AWS managed policies.  | April 21, 2021 | 

# Amazon Timestream for LiveAnalytics identity-based policy examples
<a name="security_iam_id-based-policy-examples"></a>

By default, IAM users and roles don't have permission to create or modify Timestream for LiveAnalytics resources. They also can't perform tasks using the AWS Management Console, CQLSH, AWS CLI, or AWS API. An IAM administrator must create IAM policies that grant users and roles permission to perform specific API operations on the specified resources they need. The administrator must then attach those policies to the IAM users or groups that require those permissions.

To learn how to create an IAM identity-based policy using these example JSON policy documents, see [Creating Policies on the JSON Tab](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create.html#access_policies_create-json-editor) in the *IAM User Guide*.

**Topics**
+ [Policy best practices](#security_iam_service-with-iam-policy-best-practices)
+ [Using the Timestream for LiveAnalytics console](#security_iam_id-based-policy-examples-console)
+ [Allow users to view their own permissions](#security_iam_id-based-policy-examples-view-own-permissions)
+ [Common operations in Timestream for LiveAnalytics](#security_iam_id-based-policy-examples-common-operations)
+ [Timestream for LiveAnalytics resource access based on tags](#security_iam_id-based-policy-examples-tags)
+ [Scheduled queries](#security_iam_id-based-policy-examples-sheduledqueries)

## Policy best practices
<a name="security_iam_service-with-iam-policy-best-practices"></a>

Identity-based policies determine whether someone can create, access, or delete Timestream for LiveAnalytics resources in your account. These actions can incur costs for your AWS account. When you create or edit identity-based policies, follow these guidelines and recommendations:
+ **Get started with AWS managed policies and move toward least-privilege permissions** – To get started granting permissions to your users and workloads, use the *AWS managed policies* that grant permissions for many common use cases. They are available in your AWS account. We recommend that you reduce permissions further by defining AWS customer managed policies that are specific to your use cases. For more information, see [AWS managed policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#aws-managed-policies) or [AWS managed policies for job functions](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_job-functions.html) in the *IAM User Guide*.
+ **Apply least-privilege permissions** – When you set permissions with IAM policies, grant only the permissions required to perform a task. You do this by defining the actions that can be taken on specific resources under specific conditions, also known as *least-privilege permissions*. For more information about using IAM to apply permissions, see [ Policies and permissions in IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html) in the *IAM User Guide*.
+ **Use conditions in IAM policies to further restrict access** – You can add a condition to your policies to limit access to actions and resources. For example, you can write a policy condition to specify that all requests must be sent using SSL. You can also use conditions to grant access to service actions if they are used through a specific AWS service, such as CloudFormation. For more information, see [ IAM JSON policy elements: Condition](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html) in the *IAM User Guide*.
+ **Use IAM Access Analyzer to validate your IAM policies to ensure secure and functional permissions** – IAM Access Analyzer validates new and existing policies so that the policies adhere to the IAM policy language (JSON) and IAM best practices. IAM Access Analyzer provides more than 100 policy checks and actionable recommendations to help you author secure and functional policies. For more information, see [Validate policies with IAM Access Analyzer](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-policy-validation.html) in the *IAM User Guide*.
+ **Require multi-factor authentication (MFA)** – If you have a scenario that requires IAM users or a root user in your AWS account, turn on MFA for additional security. To require MFA when API operations are called, add MFA conditions to your policies. For more information, see [ Secure API access with MFA](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_configure-api-require.html) in the *IAM User Guide*.

For more information about best practices in IAM, see [Security best practices in IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html) in the *IAM User Guide*.

## Using the Timestream for LiveAnalytics console
<a name="security_iam_id-based-policy-examples-console"></a>

Timestream for LiveAnalytics does not require specific permissions to access the Amazon Timestream for LiveAnalytics console. You need at least read-only permissions to list and view details about the Timestream for LiveAnalytics resources in your AWS account. If you create an identity-based policy that is more restrictive than the minimum required permissions, the console won't function as intended for entities (IAM users or roles) with that policy.

## Allow users to view their own permissions
<a name="security_iam_id-based-policy-examples-view-own-permissions"></a>

This example shows how you might create a policy that allows IAM users to view the inline and managed policies that are attached to their user identity. This policy includes permissions to complete this action on the console or programmatically using the AWS CLI or AWS API.

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "ViewOwnUserInfo",
            "Effect": "Allow",
            "Action": [
                "iam:GetUserPolicy",
                "iam:ListGroupsForUser",
                "iam:ListAttachedUserPolicies",
                "iam:ListUserPolicies",
                "iam:GetUser"
            ],
            "Resource": ["arn:aws:iam::*:user/${aws:username}"]
        },
        {
            "Sid": "NavigateInConsole",
            "Effect": "Allow",
            "Action": [
                "iam:GetGroupPolicy",
                "iam:GetPolicyVersion",
                "iam:GetPolicy",
                "iam:ListAttachedGroupPolicies",
                "iam:ListGroupPolicies",
                "iam:ListPolicyVersions",
                "iam:ListPolicies",
                "iam:ListUsers"
            ],
            "Resource": "*"
        }
    ]
}
```

## Common operations in Timestream for LiveAnalytics
<a name="security_iam_id-based-policy-examples-common-operations"></a>

Below are sample IAM policies that allow for common operations in the Timestream for LiveAnalytics service.

**Topics**
+ [Allowing all operations](#security_iam_id-based-policy-examples-common-operations.all)
+ [Allowing SELECT operations](#security_iam_id-based-policy-examples-common-operations.select)
+ [Allowing SELECT operations on multiple resources](#security_iam_id-based-policy-examples-common-operations.select-multiple-resources)
+ [Allowing metadata operations](#security_iam_id-based-policy-examples-common-operations.metadata)
+ [Allowing INSERT operations](#security_iam_id-based-policy-examples-common-operations.insert)
+ [Allowing CRUD operations](#security_iam_id-based-policy-examples-common-operations.crud)
+ [Cancel queries and select data without specifying resources](#security_iam_id-based-policy-examples-common-operations.cancel-selectvalues)
+ [Create, describe, delete and describe a database](#security_iam_id-based-policy-examples-common-operations.cddd)
+ [Limit listed databases by tag`{"Owner": "${username}"}`](#security_iam_id-based-policy-examples-common-operations.list-by-tag)
+ [List all tables in a database](#security_iam_id-based-policy-examples-common-operations.list-all-tables)
+ [Create, describe, delete, update and select on a table](#security_iam_id-based-policy-examples-common-operations.cddus-table)
+ [Limit a query by table](#security_iam_id-based-policy-examples-common-operations.limit-query-table)

### Allowing all operations
<a name="security_iam_id-based-policy-examples-common-operations.all"></a>

The following is a sample policy that allows all operations in Timestream for LiveAnalytics.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "timestream:*"
            ],
            "Resource": "*"
        }
    ]
}
```

------

### Allowing SELECT operations
<a name="security_iam_id-based-policy-examples-common-operations.select"></a>

The following sample policy allows `SELECT`-style queries on a specific resource.

**Note**  
Replace `<account_ID>` with your Amazon account ID.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "timestream:Select",
                "timestream:DescribeTable",
                "timestream:ListMeasures"
            ],
            "Resource": "arn:aws:timestream:us-east-1:111122223333:database/sampleDB/table/DevOps"
        },
        {
            "Effect": "Allow",
            "Action": [
                "timestream:DescribeEndpoints",
                "timestream:SelectValues",
                "timestream:CancelQuery"
            ],
            "Resource": "*"
        }
    ]
}
```

------

### Allowing SELECT operations on multiple resources
<a name="security_iam_id-based-policy-examples-common-operations.select-multiple-resources"></a>

The following sample policy allows `SELECT`-style queries on multiple resources. 

**Note**  
Replace `<account_ID>` with your Amazon account ID.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "timestream:Select",
                "timestream:DescribeTable",
                "timestream:ListMeasures"
            ],
            "Resource": [
                "arn:aws:timestream:us-east-1:111122223333:database/sampleDB/table/DevOps",
                "arn:aws:timestream:us-east-1:111122223333:database/sampleDB/table/DevOps1",
                "arn:aws:timestream:us-east-1:111122223333:database/sampleDB/table/DevOps2"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "timestream:DescribeEndpoints",
                "timestream:SelectValues",
                "timestream:CancelQuery"
            ],
            "Resource": "*"
        }
    ]
}
```

------

### Allowing metadata operations
<a name="security_iam_id-based-policy-examples-common-operations.metadata"></a>

The following sample policy allows the user to perform metadata queries, but does not allow the user to perform operations that read or write actual data in Timestream for LiveAnalytics.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "timestream:DescribeEndpoints",
                "timestream:DescribeTable",
                "timestream:ListMeasures",
                "timestream:SelectValues",
                "timestream:ListTables",
                "timestream:ListDatabases",
                "timestream:CancelQuery"
            ],
            "Resource": "*"
        }
    ]
}
```

------

### Allowing INSERT operations
<a name="security_iam_id-based-policy-examples-common-operations.insert"></a>

The following sample policy allows a user to perform an `INSERT` operation on `database/sampleDB/table/DevOps` in account `<account_id>`.

**Note**  
Replace `<account_ID>` with your Amazon account ID.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Action": [
                "timestream:WriteRecords"
            ],
            "Resource": [
                "arn:aws:timestream:us-east-1:111122223333:database/sampleDB/table/DevOps"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "timestream:DescribeEndpoints"
            ],
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}
```

------

### Allowing CRUD operations
<a name="security_iam_id-based-policy-examples-common-operations.crud"></a>

The following sample policy allows a user to perform CRUD operations in Timestream for LiveAnalytics.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "timestream:DescribeEndpoints",
                "timestream:CreateTable",
                "timestream:DescribeTable",
                "timestream:CreateDatabase",
                "timestream:DescribeDatabase",
                "timestream:ListTables",
                "timestream:ListDatabases",
                "timestream:DeleteTable",
                "timestream:DeleteDatabase",
                "timestream:UpdateTable",
                "timestream:UpdateDatabase"
            ],
            "Resource": "*"
        }
    ]
}
```

------

### Cancel queries and select data without specifying resources
<a name="security_iam_id-based-policy-examples-common-operations.cancel-selectvalues"></a>

The following sample policy allows a user to cancel queries and perform `Select` queries on data that does not require resource specification:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "timestream:SelectValues",
                "timestream:CancelQuery"
            ],
            "Resource": "*"
        }
    ]
}
```

------

### Create, describe, delete and describe a database
<a name="security_iam_id-based-policy-examples-common-operations.cddd"></a>

The following sample policy allows a user to create, describe, delete and describe database `sampleDB`:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "timestream:CreateDatabase",
                "timestream:DescribeDatabase",
                "timestream:DeleteDatabase",
                "timestream:UpdateDatabase"
            ],
            "Resource": "arn:aws:timestream:us-east-1:111122223333:database/sampleDB"
        }
    ]
}
```

------

### Limit listed databases by tag`{"Owner": "${username}"}`
<a name="security_iam_id-based-policy-examples-common-operations.list-by-tag"></a>

The following sample policy allows a user to list all databases that that are tagged with key value pair `{"Owner": "${username}"}`:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "timestream:ListDatabases"
            ],
            "Resource": "arn:aws:timestream:us-east-1:111122223333:database/*",
            "Condition": {
                "StringEquals": {
                    "aws:ResourceTag/Owner": "${aws:username}"
                }
            }
        }
    ]
}
```

------

### List all tables in a database
<a name="security_iam_id-based-policy-examples-common-operations.list-all-tables"></a>

The following sample policy to list all tables in database `sampleDB`:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "timestream:ListTables"
            ],
            "Resource": "arn:aws:timestream:us-east-1:111122223333:database/sampleDB/"
        }
    ]
}
```

------

### Create, describe, delete, update and select on a table
<a name="security_iam_id-based-policy-examples-common-operations.cddus-table"></a>

The following sample policy allows a user to create tables, describe tables, delete tables, update tables, and perform `Select` queries on table `DevOps` in database `sampleDB`:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "timestream:CreateTable",
                "timestream:DescribeTable",
                "timestream:DeleteTable",
                "timestream:UpdateTable",
                "timestream:Select"
            ],
            "Resource": "arn:aws:timestream:us-east-1:111122223333:database/sampleDB/table/DevOps"
        }
    ]
}
```

------

### Limit a query by table
<a name="security_iam_id-based-policy-examples-common-operations.limit-query-table"></a>

The following sample policy allows a user to query all tables except `DevOps` in database `sampleDB`:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "timestream:Select"
            ],
            "Resource": "arn:aws:timestream:us-east-1:111122223333:database/sampleDB/table/*"
        },
        {
            "Effect": "Deny",
            "Action": [
                "timestream:Select"
            ],
            "Resource": "arn:aws:timestream:us-east-1:111122223333:database/sampleDB/table/DevOps"
        }
    ]
}
```

------

## Timestream for LiveAnalytics resource access based on tags
<a name="security_iam_id-based-policy-examples-tags"></a>

You can use conditions in your identity-based policy to control access to Timestream for LiveAnalytics resources based on tags. This section provides some examples. 

The following example shows how you can create a policy that grants permissions to a user to view a table if the table's `Owner` contains the value of that user's user name.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "ReadOnlyAccessTaggedTables",
            "Effect": "Allow",
            "Action": "timestream:Select",
            "Resource": "arn:aws:timestream:us-east-2:111122223333:database/mydatabase/table/*",
            "Condition": {
                "StringEquals": {
                    "aws:ResourceTag/Owner": "${aws:username}"
                }
            }
        }
    ]
}
```

------

You can attach this policy to the IAM users in your account. If a user named `richard-roe` attempts to view an Timestream for LiveAnalytics table, the table must be tagged `Owner=richard-roe` or `owner=richard-roe`. Otherwise, he is denied access. The condition tag key `Owner` matches both `Owner` and `owner` because condition key names are not case-sensitive. For more information, see [IAM JSON Policy Elements: Condition](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html) in the *IAM User Guide*.

The following policy grants permissions to a user to create tables with tags if the tag passed in request has a key `Owner` and a value `username`:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "CreateTagTableUser",
            "Effect": "Allow",
            "Action": [
                "timestream:CreateTable",
                "timestream:TagResource"
            ],
            "Resource": "arn:aws:timestream:us-east-2:111122223333:database/mydatabase/table/*",
            "Condition": {
                "ForAnyValue:StringEquals": {
                    "aws:RequestTag/Owner": "${aws:username}"
                }
            }
        }
    ]
}
```

------

The policy below allows use of the `DescribeDatabase` API on any Database that has the `env` tag set to either `dev` or `test`:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "AllowDescribe",
            "Effect": "Allow",
            "Action": [
                "timestream:DescribeEndpoints",
                "timestream:DescribeDatabase"
            ],
            "Resource": "*"
        },
        {
            "Sid": "AllowTagAccessForDevResources",
            "Effect": "Allow",
            "Action": [
                "timestream:TagResource"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "aws:RequestTag/env": [
                        "test",
                        "dev"
                    ]
                }
            }
        }
    ]
}
```

------

This policy uses a `Condition` key to allow a tag that has the key `env` and a value of `test`, `qa`, or `dev` to be added to a resource.

## Scheduled queries
<a name="security_iam_id-based-policy-examples-sheduledqueries"></a>

### List, delete, update, execute ScheduledQuery
<a name="security_iam_id-based-policy-examples-sheduledqueries-alloperations"></a>

The following sample policy allows a user to list, delete, update and execute scheduled queries.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "timestream:DeleteScheduledQuery",
                "timestream:ExecuteScheduledQuery",
                "timestream:UpdateScheduledQuery",
                "timestream:ListScheduledQueries",
                "timestream:DescribeEndpoints"
            ],
            "Resource": "*"
        }
    ]
}
```

------

### CreateScheduledQuery using a customer managed KMS key
<a name="security_iam_id-based-policy-examples-sheduledqueries-create"></a>

The following sample policy allows a user to create a scheduled query that is encrypted using a customer managed KMS key; *<keyid for ScheduledQuery>*.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Action": [
                "iam:PassRole"
            ],
            "Resource": [
                "arn:aws:iam::123456789012:role/ScheduledQueryExecutionRole"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "timestream:CreateScheduledQuery",
                "timestream:DescribeEndpoints"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "kms:DescribeKey",
                "kms:GenerateDataKey"
            ],
            "Resource": "arn:aws:kms:us-west-2:123456789012:key/<keyid for ScheduledQuery>",
            "Effect": "Allow"
        }
    ]
}
```

------

### DescribeScheduledQuery using a customer managed KMS key
<a name="security_iam_id-based-policy-examples-sheduledqueries-describe"></a>

The following sample policy allows a user to describe a scheduled query that was created using a customer managed KMS key; *<keyid for ScheduledQuery>*.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Action": [
                "timestream:DescribeScheduledQuery",
                "timestream:DescribeEndpoints"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "kms:Decrypt"
            ],
            "Resource": "arn:aws:kms:us-west-2:123456789012:key/<keyid for ScheduledQuery>",
            "Effect": "Allow"
        }
    ]
}
```

------

### Execution role permissions (using a customer managed KMS key for scheduled query and SSE-KMS for error reports)
<a name="security_iam_id-based-policy-examples-sheduledqueries-execrole"></a>

Attach the following sample policy to the IAM role specified in the `ScheduledQueryExecutionRoleArn` parameter, of the `CreateScheduledQuery` API that uses customer managed KMS key for the scheduled query encryption and `SSE-KMS` encryption for error reports. 

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Action": [
                "kms:GenerateDataKey"
            ],
            "Resource": "arn:aws:kms:us-west-2:123456789012:key/<keyid for ScheduledQuery>",
            "Effect": "Allow"
        },
        {
            "Action": [
                "kms:Decrypt"
            ],
            "Resource": [
                "arn:aws:kms:us-west-2:123456789012:key/<keyid for database-1>",
                "arn:aws:kms:us-west-2:123456789012:key/<keyid for database-n>",
                "arn:aws:kms:us-west-2:123456789012:key/<keyid for ScheduledQuery>"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "sns:Publish"
            ],
            "Resource": [
                "arn:aws:sns:us-west-2:123456789012:scheduled-query-notification-topic-*"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "timestream:Select",
                "timestream:SelectValues",
                "timestream:WriteRecords"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "s3:PutObject",
                "s3:GetBucketAcl"
            ],
            "Resource": [
                "arn:aws:s3:::scheduled-query-error-bucket",
                "arn:aws:s3:::scheduled-query-error-bucket/*"
            ],
            "Effect": "Allow"
        }
    ]
}
```

------

### Execution role trust relationship
<a name="security_iam_id-based-policy-examples-sheduledqueries-exectrust"></a>

The following is the trust relationship for the IAM role specified in the `ScheduledQueryExecutionRoleArn` parameter of the `CreateScheduledQuery` API.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "timestream.amazonaws.com"
                ]
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
```

------

### Allow access to all scheduled queries created within an account
<a name="security_iam_id-based-policy-examples-sheduledqueries-accountid"></a>

Attach the following sample policy to the IAM role specified in the `ScheduledQueryExecutionRoleArn` parameter, of the `CreateScheduledQuery` API, to allow access to all scheduled queries created within the an account *Account\$1ID*.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "timestream.amazonaws.com"
            },
            "Action": "sts:AssumeRole",
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": "Account_ID"
                },
                "ArnLike": {
                    "aws:SourceArn": "arn:aws:timestream:us-west-2:111122223333:scheduled-query/*"
                }
            }
        }
    ]
}
```

------

### Allow access to all scheduled queries with a specific name
<a name="security_iam_id-based-policy-examples-sheduledqueries-queryname"></a>

Attach the following sample policy to the IAM role specified in the `ScheduledQueryExecutionRoleArn` parameter, of the `CreateScheduledQuery` API, to allow access to all scheduled queries with a name that starts with *Scheduled\$1Query\$1Name*, within account *Account\$1ID*.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "timestream.amazonaws.com"
            },
            "Action": "sts:AssumeRole",
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": "Account_ID"
                },
                "ArnLike": {
                    "aws:SourceArn": "arn:aws:timestream:us-west-2:111122223333:scheduled-query/Scheduled_Query_Name*"
                }
            }
        }
    ]
}
```

------

# Troubleshooting Amazon Timestream for LiveAnalytics identity and access
<a name="security_iam_troubleshoot"></a>

Use the following information to help you diagnose and fix common issues that you might encounter when working with Timestream for LiveAnalytics and IAM.

**Topics**
+ [I am not authorized to perform an action in Timestream for LiveAnalytics](#security_iam_troubleshoot-no-permissions)
+ [I am not authorized to perform iam:PassRole](#security_iam_troubleshoot-passrole)
+ [I want to allow people outside of my AWS account to access my Timestream for LiveAnalytics resources](#security_iam_troubleshoot-cross-account-access)

## I am not authorized to perform an action in Timestream for LiveAnalytics
<a name="security_iam_troubleshoot-no-permissions"></a>

If the AWS Management Console tells you that you're not authorized to perform an action, then you must contact your administrator for assistance. Your administrator is the person that provided you with your sign-in credentials.

The following example error occurs when the `mateojackson` IAM user tries to use the console to view details about a *table* but does not have `timestream:Select` permissions for the table.

```
User: arn:aws:iam::123456789012:user/mateojackson is not authorized to perform: timestream:Select on resource: mytable
```

In this case, Mateo asks his administrator to update his policies to allow him to access the `mytable` resource using the `timestream:Select` action.

## I am not authorized to perform iam:PassRole
<a name="security_iam_troubleshoot-passrole"></a>

If you receive an error that you're not authorized to perform the `iam:PassRole` action, your policies must be updated to allow you to pass a role to Timestream for LiveAnalytics.

Some AWS services allow you to pass an existing role to that service instead of creating a new service role or service-linked role. To do this, you must have permissions to pass the role to the service.

The following example error occurs when an IAM user named `marymajor` tries to use the console to perform an action in Timestream for LiveAnalytics. However, the action requires the service to have permissions that are granted by a service role. Mary does not have permissions to pass the role to the service.

```
User: arn:aws:iam::123456789012:user/marymajor is not authorized to perform: iam:PassRole
```

In this case, Mary's policies must be updated to allow her to perform the `iam:PassRole` action.

If you need help, contact your AWS administrator. Your administrator is the person who provided you with your sign-in credentials.

## I want to allow people outside of my AWS account to access my Timestream for LiveAnalytics resources
<a name="security_iam_troubleshoot-cross-account-access"></a>

You can create a role that users in other accounts or people outside of your organization can use to access your resources. You can specify who is trusted to assume the role. For services that support resource-based policies or access control lists (ACLs), you can use those policies to grant people access to your resources.

To learn more, consult the following:
+ To learn whether Timestream for LiveAnalytics supports these features, see [How Amazon Timestream for LiveAnalytics works with IAM](security_iam_service-with-iam.md).
+ To learn how to provide access to your resources across AWS accounts that you own, see [Providing access to an IAM user in another AWS account that you own](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_aws-accounts.html) in the *IAM User Guide*.
+ To learn how to provide access to your resources to third-party AWS accounts, see [Providing access to AWS accounts owned by third parties](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_third-party.html) in the *IAM User Guide*.
+ To learn how to provide access through identity federation, see [Providing access to externally authenticated users (identity federation)](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_common-scenarios_federated-users.html) in the *IAM User Guide*.
+ To learn the difference between using roles and resource-based policies for cross-account access, see [Cross account resource access in IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies-cross-account-resource-access.html) in the *IAM User Guide*.

# Logging and monitoring in Timestream for LiveAnalytics
<a name="monitoring"></a>

Monitoring is an important part of maintaining the reliability, availability, and performance of Timestream for LiveAnalytics and your AWS solutions. You should collect monitoring data from all of the parts of your AWS solution so that you can more easily debug a multi-point failure if one occurs. However, before you start monitoring Timestream for LiveAnalytics, you should create a monitoring plan that includes answers to the following questions:
+ What are your monitoring goals?
+ What resources will you monitor?
+ How often will you monitor these resources?
+ What monitoring tools will you use?
+ Who will perform the monitoring tasks?
+ Who should be notified when something goes wrong?

The next step is to establish a baseline for normal Timestream for LiveAnalytics performance in your environment, by measuring performance at various times and under different load conditions. As you monitor Timestream for LiveAnalytics, store historical monitoring data so that you can compare it with current performance data, identify normal performance patterns and performance anomalies, and devise methods to address issues.

To establish a baseline, you should, at a minimum, monitor the following items:
+ System errors, so that you can determine whether any requests resulted in an error.

**Topics**
+ [Monitoring tools](monitoring-automated-manual.md)
+ [Logging Timestream for LiveAnalytics API calls with AWS CloudTrail](logging-using-cloudtrail.md)

# Monitoring tools
<a name="monitoring-automated-manual"></a>

AWS provides various tools that you can use to monitor Timestream for LiveAnalytics. You can configure some of these tools to do the monitoring for you, while some of the tools require manual intervention. We recommend that you automate monitoring tasks as much as possible.

**Topics**
+ [Automated monitoring tools](#monitoring-automated_tools)
+ [Manual monitoring tools](#monitoring-manual-tools)

## Automated monitoring tools
<a name="monitoring-automated_tools"></a>

You can use the following automated monitoring tools to watch Timestream for LiveAnalytics and report when something is wrong:
+ **Amazon CloudWatch Alarms** – Watch a single metric over a time period that you specify, and perform one or more actions based on the value of the metric relative to a given threshold over a number of time periods. The action is a notification sent to an Amazon Simple Notification Service (Amazon SNS) topic or Amazon EC2 Auto Scaling policy. CloudWatch alarms do not invoke actions simply because they are in a particular state; the state must have changed and been maintained for a specified number of periods. For more information, see [Monitoring with Amazon CloudWatch](monitoring-cloudwatch.md).

## Manual monitoring tools
<a name="monitoring-manual-tools"></a>

Another important part of monitoring Timestream for LiveAnalytics involves manually monitoring those items that the CloudWatch alarms don't cover. The Timestream for LiveAnalytics, CloudWatch, Trusted Advisor, and other AWS Management Console dashboards provide an at-a-glance view of the state of your AWS environment.
+ The CloudWatch home page shows the following:
  + Current alarms and status
  + Graphs of alarms and resources
  + Service health status

  In addition, you can use CloudWatch to do the following: 
  + Create [customized dashboards](https://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/CloudWatch_Dashboards.html) to monitor the services you care about
  + Graph metric data to troubleshoot issues and discover trends
  + Search and browse all your AWS resource metrics
  + Create and edit alarms to be notified of problems

# Logging Timestream for LiveAnalytics API calls with AWS CloudTrail
<a name="logging-using-cloudtrail"></a>



Timestream for LiveAnalytics is integrated with AWS CloudTrail, a service that provides a record of actions taken by a user, role, or an AWS service in Timestream for LiveAnalytics. CloudTrail captures Data Definition Language (DDL) API calls for Timestream for LiveAnalytics as events. The calls that are captured include calls from the Timestream for LiveAnalytics console and code calls to the Timestream for LiveAnalytics API operations. If you create a trail, you can enable continuous delivery of CloudTrail events to an Amazon Simple Storage Service (Amazon S3) bucket, including events for Timestream for LiveAnalytics. If you don't configure a trail, you can still view the most recent events on the CloudTrail console in **Event history**. Using the information collected by CloudTrail, you can determine the request that was made to Timestream for LiveAnalytics, the IP address from which the request was made, who made the request, when it was made, and additional details. 

To learn more about CloudTrail, see the [AWS CloudTrail User Guide](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/).

## Timestream for LiveAnalytics information in CloudTrail
<a name="service-name-info-in-cloudtrail"></a>

CloudTrail is enabled on your AWS account when you create the account. When activity occurs in Timestream for LiveAnalytics, that activity is recorded in a CloudTrail event along with other AWS service events in **Event history**. You can view, search, and download recent events in your AWS account. For more information, see [Viewing Events with CloudTrail Event History](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/view-cloudtrail-events.html). 

**Warning**  
Currently, Timestream for LiveAnalytics generates CloudTrail events for all management and `Query` API operations, but does not generate events for `WriteRecords` and `DescribeEndpoints` APIs. 

For an ongoing record of events in your AWS account, including events for Timestream for LiveAnalytics, create a trail. A *trail* enables CloudTrail to deliver log files to an Amazon S3 bucket. By default, when you create a trail in the console, the trail applies to all AWS Regions. The trail logs events from all Regions in the AWS partition and delivers the log files to the Amazon S3 bucket that you specify. Additionally, you can configure other AWS services to further analyze and act upon the event data collected in CloudTrail logs.

For more information, see the following topics in the *AWS CloudTrail User Guide*: 
+ [Overview for Creating a Trail](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-create-and-update-a-trail.html)
+ [CloudTrail Supported Services and Integrations](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-aws-service-specific-topics.html#cloudtrail-aws-service-specific-topics-integrations)
+ [Configuring Amazon SNS Notifications for CloudTrail](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/getting_notifications_top_level.html)
+ [Receiving CloudTrail Log Files from Multiple Regions](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/receive-cloudtrail-log-files-from-multiple-regions.html)
+ [Receiving CloudTrail Log Files from Multiple Accounts](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-receive-logs-from-multiple-accounts.html)
+ [Logging data events](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/logging-data-events-with-cloudtrail.html)

Every event or log entry contains information about who generated the request. The identity information helps you determine the following: 
+ Whether the request was made with root or AWS Identity and Access Management (IAM) user credentials
+ Whether the request was made with temporary security credentials for a role or federated user
+ Whether the request was made by another AWS service

For more information, see the [CloudTrail userIdentity Element](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-user-identity.html).

For `Query` API events:
+ Create a trail that receives all events or select events with Timestream for LiveAnalytics resource type `AWS::Timestream::Database` or `AWS::Timestream::Table`.
+ `Query` API requests that do not access any database or table or that result in a validation exception due to a malformed query string are recorded in CloudTrail with a resource type `AWS::Timestream::Database` and an ARN value of:

  ```
  arn:aws:timestream:(region):(accountId):database/NO_RESOURCE_ACCESSED
  ```

  These events are delivered only to trails that receive events with resource type `AWS::Timestream::Database`.

# Resilience in Amazon Timestream Live Analytics
<a name="disaster-recovery-resiliency"></a>

The AWS global infrastructure is built around AWS Regions and Availability Zones. AWS Regions provide multiple physically separated and isolated Availability Zones, which are connected with low-latency, high-throughput, and highly redundant networking. With Availability Zones, you can design and operate applications and databases that automatically fail over between zones without interruption. Availability Zones are more highly available, fault tolerant, and scalable than traditional single or multiple data center infrastructures. 

For more information about AWS Regions and Availability Zones, see [AWS Global Infrastructure](https://aws.amazon.com/about-aws/global-infrastructure/).

For information about data protection functionality for Timestream available through AWS Backup, see [Working with AWS Backup](backups.md).

# Infrastructure security in Amazon Timestream Live Analytics
<a name="infrastructure-security"></a>

As a managed service, Amazon Timestream Live Analytics is protected by the AWS global network security procedures that are described in the [Amazon Web Services: Overview of Security Processes](https://d0.awsstatic.com/whitepapers/Security/AWS_Security_Whitepaper.pdf) whitepaper.

You use AWS published API calls to access Timestream Live Analytics through the network. Clients must support Transport Layer Security (TLS) 1.0 or later. We recommend TLS 1.2 or later. Clients must also support cipher suites with perfect forward secrecy (PFS) such as Ephemeral Diffie-Hellman (DHE) or Elliptic Curve Ephemeral Diffie-Hellman (ECDHE). Most modern systems such as Java 7 and later support these modes.

Additionally, requests must be signed by using an access key ID and a secret access key that is associated with an IAM principal. Or you can use the [AWS Security Token Service](https://docs.aws.amazon.com/STS/latest/APIReference/Welcome.html) (AWS STS) to generate temporary security credentials to sign requests.

Timestream Live Analytics is architected so that your traffic is isolated to the specific AWS Region that your Timestream Live Analytics instance resides in.

# Configuration and vulnerability analysis in Timestream
<a name="ConfigAndVulnerability"></a>

 Configuration and IT controls are a shared responsibility between AWS and you, our customer. For more information, see the AWS [shared responsibility model](https://aws.amazon.com/compliance/shared-responsibility-model/). In addition to the shared responsibility model, Timestream for LiveAnalytics users should be aware of the following: 
+ It is the customer responsibility to patch their client applications with the relevant client side dependencies.
+ Customers should consider penetration testing if appropriate (see [https://aws.amazon.com/security/penetration-testing/](https://aws.amazon.com/security/penetration-testing/).)

# Incident response in Timestream for LiveAnalytics
<a name="IncidentResponse"></a>

Amazon Timestream for LiveAnalytics service incidents are reported in the [Personal Health Dashboard](https://phd.aws.amazon.com/phd/home#/). You can learn more about the dashboard and AWS Health [here](https://docs.aws.amazon.com//health/latest/ug/what-is-aws-health.html).

Timestream for LiveAnalytics supports reporting using AWS CloudTrail. For more information, see [Logging Timestream for LiveAnalytics API calls with AWS CloudTrail](logging-using-cloudtrail.md). 

# VPC endpoints (AWS PrivateLink)
<a name="VPCEndpoints"></a>

You can establish a private connection between your VPC and Amazon Timestream for LiveAnalytics by creating an *interface VPC endpoint*. Interface endpoints are powered by [AWS PrivateLink](https://aws.amazon.com/privatelink), a technology that enables you to privately access Timestream for LiveAnalytics APIs without an internet gateway, NAT device, VPN connection, or AWS Direct Connect connection. Instances in your VPC don't need public IP addresses to communicate with Timestream for LiveAnalytics APIs. Traffic between your VPC and Timestream for LiveAnalytics does not leave the Amazon network. 

Each interface endpoint is represented by one or more [Elastic Network Interfaces](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html) in your subnets. For more information on Interface VPC endpoints, see [Interface VPC endpoints (AWS PrivateLink)](https://docs.aws.amazon.com/vpc/latest/userguide/vpce-interface.html) in the *Amazon VPC User Guide*.

To get started with Timestream for LiveAnalytics and VPC endpoints, we've provided information on specific considerations for Timestream for LiveAnalytics with VPC endpoints, creating an interface VPC endpoint for Timestream for LiveAnalytics, creating a VPC endpoint policy for Timestream for LiveAnalytics, and using the Timestream client (for either the Write or Query SDK) with VPC endpoints..

**Topics**
+ [How VPC endpoints work with Timestream](VPCEndpoints.vpc-endpoint-considerations.md)
+ [Creating an interface VPC endpoint for Timestream for LiveAnalytics](VPCEndpoints.vpc-endpoint-create.md)
+ [Creating a VPC endpoint policy for Timestream for LiveAnalytics](VPCEndpoints.vpc-endpoint-policy.md)

# How VPC endpoints work with Timestream
<a name="VPCEndpoints.vpc-endpoint-considerations"></a>

 When you create a VPC endpoint to access either the Timestream Write or Timestream Query SDK, all requests are routed to endpoints within the Amazon network and do not access the public internet. More specifically, your requests are routed to the write and query endpoints of the cell that your account has been mapped to for a given region. To learn more about Timestream's cellular architecture and cell-specific endpoints, you can refer to [Cellular architecture](architecture.md#cells). For example, suppose that your account has been mapped to `cell1` in `us-west-2`, and you've set up VPC interface endpoints for writes (`ingest-cell1.timestream.us-west-2.amazonaws.com`) and queries (`query-cell1.timestream.us-west-2.amazonaws.com`). In this case, any write requests sent using these endpoints will stay entirely within the Amazon network and will not access the public internet. 

## Considerations for Timestream VPC endpoints
<a name="VPCEndpoints.vpc-endpoint-considerations.how-it-works"></a>

Consider the following when creating a VPC endpoint for Timestream:
+ Before you set up an interface VPC endpoint for Timestream for LiveAnalytics, ensure that you review [Interface endpoint properties and limitations](https://docs.aws.amazon.com/vpc/latest/userguide/vpce-interface.html#vpce-interface-limitations) in the *Amazon VPC User Guide*. 
+ Timestream for LiveAnalytics supports making calls to [all of its API actions](https://docs.aws.amazon.com/timestream/latest/developerguide/API_Reference.html) from your VPC. 
+ VPC endpoint policies are supported for Timestream for LiveAnalytics. By default, full access to Timestream for LiveAnalytics is allowed through the endpoint. For more information, see [Controlling access to services with VPC endpoints](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-endpoints-access.html) in the *Amazon VPC User Guide*.
+ Because of Timestream's architecture, access to both Write and Query actions requires the creation of two VPC interface endpoints, one for each SDK. Additionally, you must specify a cell endpoint (you will only be able to create an endpoint for the Timestream cell that you are mapped to). Detailed information can be found in the [create an interface VPC endpoint for Timestream for LiveAnalytics](VPCEndpoints.vpc-endpoint-create.md) section of this guide. 

Now that you understand how Timestream for LiveAnalytics works with VPC endpoints, [create an interface VPC endpoint for Timestream for LiveAnalytics](VPCEndpoints.vpc-endpoint-create.md).

# Creating an interface VPC endpoint for Timestream for LiveAnalytics
<a name="VPCEndpoints.vpc-endpoint-create"></a>

You can create an [interface VPC endpoint](https://docs.aws.amazon.com/vpc/latest/privatelink/vpce-interface.html) for the Timestream for LiveAnalytics service using either the Amazon VPC console or the AWS Command Line Interface (AWS CLI). To create a VPC endpoint for Timestream, complete the Timestream-specific steps described below. 

**Note**  
Before completing the steps below, ensure that you understand [specific considerations for Timestream VPC endpoints.](VPCEndpoints.vpc-endpoint-considerations.md)

## Constructing a VPC endpoint service name using your Timestream cell
<a name="VPCEndpoints.vpc-endpoint-create.vpc-endpoint-name"></a>

 Because of Timestream's unique architecture, separate VPC interface endpoints must be created for each SDK (Write and Query). Additionally, you must specify a Timestream cell endpoint (you will only be able to create an endpoint for the Timestream cell that you are mapped to). To use Interface VPC Endpoints to directly connect to Timestream from within your VPC, complete the steps below: 

1. First, find an available Timestream cell endpoint. To find an available cell endpoint, use the [`DescribeEndpoints` action](https://docs.aws.amazon.com/timestream/latest/developerguide/API_query_DescribeEndpoints.html) (available through both the Write and Query APIs) to list the cell endpoints available in your Timestream account. See the [example](#VPCEndpoints.vpc-endpoint-create.vpc-endpoint-name.example) for further details. 

1. Once you've selected a cell endpoint to use, create a VPC interface endpoint string for either the Timestream Write or Query API:
   + *For the Write API:*

     ```
     com.amazonaws.<region>.timestream.ingest-<cell>
     ```
   + *For the Query API:*

     ```
     com.amazonaws.<region>.timestream.query-<cell>
     ```

    where *<region>* is a [valid AWS region code](https://docs.aws.amazon.com/general/latest/gr/rande.html) and *<cell>* is one of the cell endpoint addresses (such as `cell1` or `cell2`) returned in the [Endpoints object](https://docs.aws.amazon.com/timestream/latest/developerguide/API_query_DescribeEndpoints.html#API_query_DescribeEndpoints_ResponseSyntax) by the [DescribeEndpoints action](https://docs.aws.amazon.com/timestream/latest/developerguide/API_query_DescribeEndpoints.html). See the [example](#VPCEndpoints.vpc-endpoint-create.vpc-endpoint-name.example) for further details. 

1. Now that you have constructed a VPC endpoint service name, [create an interface endpoint](https://docs.aws.amazon.com/vpc/latest/privatelink/vpce-interface.html). When asked to provide a VPC endpoint service name, use the VPC endpoint service name that you constructed in Step 2.

### Example: Constructing your VPC endpoint service name
<a name="VPCEndpoints.vpc-endpoint-create.vpc-endpoint-name.example"></a>

In the following example, the `DescribeEndpoints` action is executed in the AWS CLI using the Write API in the `us-west-2` region:

```
aws timestream-write describe-endpoints --region us-west-2
```

This command will return the following output:

```
{
    "Endpoints": [
        {
            "Address": "ingest-cell1.timestream.us-west-2.amazonaws.com",
            "CachePeriodInMinutes": 1440
        }
    ]
}
```

In this case, *cell1* is the *<cell>* , and *us-west-2* is the *<region>*. So, the resulting VPC endpoint service name will look like: 

```
com.amazonaws.us-west-2.timestream.ingest-cell1
```

Now that you've created an interface VPC endpoint for Timestream for LiveAnalytics, [create a VPC endpoint policy for Timestream for LiveAnalytics](VPCEndpoints.vpc-endpoint-policy.md).

# Creating a VPC endpoint policy for Timestream for LiveAnalytics
<a name="VPCEndpoints.vpc-endpoint-policy"></a>

You can attach an endpoint policy to your VPC endpoint that controls access to Timestream for LiveAnalytics. The policy specifies the following information:
+ The principal that can perform actions.
+ The actions that can be performed.
+ The resources on which actions can be performed.

For more information, see [Controlling access to services with VPC endpoints](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-endpoints-access.html) in the *Amazon VPC User Guide*. 

**Example: VPC endpoint policy for Timestream for LiveAnalytics actions**  
The following is an example of an endpoint policy for Timestream for LiveAnalytics. When attached to an endpoint, this policy grants access to the listed Timestream for LiveAnalytics actions (in this case, [https://docs.aws.amazon.com/timestream/latest/developerguide/API_ListDatabases.html](https://docs.aws.amazon.com/timestream/latest/developerguide/API_ListDatabases.html)) for all principals on all resources.

```
{
   "Statement":[
      {
         "Principal":"*",
         "Effect":"Allow",
         "Action":[
            "timestream:ListDatabases"
         ],
         "Resource":"*"
      }
   ]
}
```

# Security best practices for Amazon Timestream for LiveAnalytics
<a name="best-practices-security"></a>

Amazon Timestream for LiveAnalytics provides a number of security features to consider as you develop and implement your own security policies. The following best practices are general guidelines and don't represent a complete security solution. Because these best practices might not be appropriate or sufficient for your environment, treat them as helpful considerations rather than prescriptions. 

**Topics**
+ [Timestream for LiveAnalytics preventative security best practices](best-practices-security-preventative.md)

# Timestream for LiveAnalytics preventative security best practices
<a name="best-practices-security-preventative"></a>

The following best practices can help you anticipate and prevent security incidents in Timestream for LiveAnalytics.

**Encryption at rest**  
Timestream for LiveAnalytics encrypts at rest all user data stored in tables using encryption keys stored in [AWS Key Management Service (AWS KMS)](https://aws.amazon.com/kms/). This provides an additional layer of data protection by securing your data from unauthorized access to the underlying storage.  
Timestream for LiveAnalytics uses a single service default key (AWS owned CMK) for encrypting all of your tables. If this key doesn't exist, it is created for you. Service default keys can't be disabled. For more information, see [Timestream for LiveAnalytics Encryption at Rest](https://docs.aws.amazon.com/mcs/latest/devguide/EncryptionAtRest.html).

**Use IAM roles to authenticate access to Timestream for LiveAnalytics**  
For users, applications, and other AWS services to access Timestream for LiveAnalytics, they must include valid AWS credentials in their AWS API requests. You should not store AWS credentials directly in the application or EC2 instance. These are long-term credentials that are not automatically rotated, and therefore could have significant business impact if they are compromised. An IAM role enables you to obtain temporary access keys that can be used to access AWS services and resources.  
For more information, see [IAM Roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html).

**Use IAM policies for Timestream for LiveAnalytics base authorization**  
When granting permissions, you decide who is getting them, which Timestream for LiveAnalytics APIs they are getting permissions for, and the specific actions you want to allow on those resources. Implementing least privilege is key in reducing security risk and the impact that can result from errors or malicious intent.  
Attach permissions policies to IAM identities (that is, users, groups, and roles) and thereby grant permissions to perform operations on Timestream for LiveAnalytics resources.  
You can do this by using the following:  
+ [AWS managed (predefined) policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#aws-managed-policies)
+ [Customer managed policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_managed-vs-inline.html#customer-managed-policies)
+ [Tag-based authorization](security_iam_service-with-iam.md#security_iam_service-with-iam-tags)

**Consider client-side encryption**  
If you store sensitive or confidential data in Timestream for LiveAnalytics, you might want to encrypt that data as close as possible to its origin so that your data is protected throughout its lifecycle. Encrypting your sensitive data in transit and at rest helps ensure that your plaintext data isn't available to any third party.

# Working with other services
<a name="OtherServices"></a>

Amazon Timestream for LiveAnalytics integrates with a variety of AWS services and popular third-party tools. Currently, Timestream for LiveAnalytics supports integrations with the following: 

**Topics**
+ [Amazon DynamoDB](dynamodb.md)
+ [AWS Lambda](Lambda.md)
+ [AWS IoT Core](IOT-Core.md)
+ [Amazon Managed Service for Apache Flink](ApacheFlink.md)
+ [Amazon Kinesis](Kinesis.md)
+ [Amazon MQ](MQ.md)
+ [Amazon MSK](MSK.md)
+ [Amazon Quick](Quicksight.md)
+ [Amazon SageMaker AI](Sagemaker.md)
+ [Amazon SQS](SQS.md)
+ [Using DBeaver to work with Amazon Timestream](DBeaver.md)
+ [Grafana](Grafana.md)
+ [Using SquaredUp to work with Amazon Timestream](SquaredUp.md)
+ [Open source Telegraf](Telegraf.md)
+ [JDBC](JDBC.md)
+ [ODBC](ODBC.md)
+ [VPC endpoints (AWS PrivateLink)](vpc-interface-endpoints.md)

# Amazon DynamoDB
<a name="dynamodb"></a>

## Using EventBridge Pipes to send DynamoDB data to Timestream
<a name="DynamoDB-via-pipes"></a>

You can use EventBridge Pipes to send data from a DynamoDB stream to a Amazon Timestream for LiveAnalytics table.

Pipes are intended for point-to-point integrations between supported sources and targets, with support for advanced transformations and enrichment. Pipes reduce the need for specialized knowledge and integration code when developing event-driven architectures. To set up a pipe, you choose the source, add optional filtering, define optional enrichment, and choose the target for the event data.

![\[A source sends events to an EventBridge pipe, which filters and routes matching events to the target.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/pipes-overview_shared_architecture.png)


For more information on EventBridge Pipes, see [EventBridge Pipes](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes.html) in the *EventBridge User Guide*. For information on configuring a pipe to deliver events to a Amazon Timestream for LiveAnalytics table, see [EventBridge Pipes target specifics](https://docs.aws.amazon.com/eventbridge/latest/userguide/pipes-targets-specifics.html#pipes-targets-specifics-timestream).

# AWS Lambda
<a name="Lambda"></a>

 You can create Lambda functions that interact with Timestream for LiveAnalytics. For example, you can create a Lambda function that runs at regular intervals to execute a query on Timestream and send an SNS notification based on the query results satisfying one or more criteria. To learn more about Lambda, see the [AWS Lambda documentation](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html).

**Topics**
+ [Build AWS Lambda functions using Amazon Timestream for LiveAnalytics with Python](#Lambda.w-python)
+ [Build AWS Lambda functions using Amazon Timestream for LiveAnalytics with JavaScript](#Lambda.w-js)
+ [Build AWS Lambda functions using Amazon Timestream for LiveAnalytics with Go](#Lambda.w-go)
+ [Build AWS Lambda functions using Amazon Timestream for LiveAnalytics with C\$1](#Lambda.w-c-sharp)

## Build AWS Lambda functions using Amazon Timestream for LiveAnalytics with Python
<a name="Lambda.w-python"></a>

 To build AWS Lambda functions using Amazon Timestream for LiveAnalytics with Python, follow the steps below.

1.  Create an IAM role for Lambda to assume that will grant the required permissions to access the Timestream Service, as outlined in [Provide Timestream for LiveAnalytics access](accessing.md#getting-started.prereqs.iam-user).

1. Edit the trust relationship of the IAM role to add Lambda service. You can use the commands below to update an existing role so that AWS Lambda can assume it:

   1. Create the trust policy document:

      ```
      cat > Lambda-Role-Trust-Policy.json << EOF
      {
        "Version": "2012-10-17",		 	 	 
        "Statement": [
          {
            "Effect": "Allow",
            "Principal": {
              "Service": [
                "lambda.amazonaws.com"
              ]
            },
            "Action": "sts:AssumeRole"
          }
        ]
      }
      EOF
      ```

   1. Update the role from previous step with the trust document

      ```
      aws iam update-assume-role-policy --role-name <name_of_the_role_from_step_1> --policy-document file://Lambda-Role-Trust-Policy.json
      ```

Related references are at [TimestreamWrite](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/timestream-write.html) and [TimestreamQuery](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/timestream-query.html).

## Build AWS Lambda functions using Amazon Timestream for LiveAnalytics with JavaScript
<a name="Lambda.w-js"></a>

 To build AWS Lambda functions using Amazon Timestream for LiveAnalytics with JavaScript, follow the instructions outlined [here](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-package.html#nodejs-package-dependencies).

Related references are at [Timestream Write Client - AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-write/index.html) and [Timestream Query Client - AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-timestream-query/index.html).

## Build AWS Lambda functions using Amazon Timestream for LiveAnalytics with Go
<a name="Lambda.w-go"></a>

 To build AWS Lambda functions using Amazon Timestream for LiveAnalytics with Go, follow the instructions outlined [here](https://docs.aws.amazon.com/lambda/latest/dg/golang-package.html).

Related references are at [timestreamwrite](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/timestreamwrite) and [timestreamquery](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/timestreamquery).

## Build AWS Lambda functions using Amazon Timestream for LiveAnalytics with C\$1
<a name="Lambda.w-c-sharp"></a>

 To build AWS Lambda functions using Amazon Timestream for LiveAnalytics with C\$1, follow the instructions outlined [here](https://docs.aws.amazon.com/lambda/latest/dg/csharp-package.html).

Related references are at [Amazon.TimestreamWrite](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/TimestreamWrite/NTimestreamWrite.html) and [Amazon.TimestreamQuery](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/items/TimestreamQuery/NTimestreamQuery.html).

# AWS IoT Core
<a name="IOT-Core"></a>

 You can collect data from IoT devices using [AWS IoT Core](https://docs.aws.amazon.com/iot/latest/developerguide/iot-gs.html) and route the data to Amazon Timestream through IoT Core rule actions. AWS IoT rule actions specify what to do when a rule is triggered. You can define actions to send data to an Amazon Timestream table, an Amazon DynamoDB database, and invoke an AWS Lambda function. 

 The Timestream action in IoT Rules is used to insert data from incoming messages directly into Timestream. The action parses the results of the [IoT Core SQL](https://docs.aws.amazon.com/iot/latest/developerguide/iot-sql-reference.html) statement and stores data in Timestream. The names of the fields from returned SQL result set are used as the measure::name and the value of the field is the measure::value. 

 For example, consider the SQL statement and the sample message payload: 

```
SELECT temperature, humidity from 'iot/topic'
```

```
{
  "dataFormat": 5, 
  "rssi": -88,
  "temperature": 24.04,    
  "humidity": 43.605,    
  "pressure": 101082,    
  "accelerationX": 40,    
  "accelerationY": -20,    
  "accelerationZ": 1016,    
  "battery": 3007,    
  "txPower": 4,    
  "movementCounter": 219,    
  "device_id": 46216,
  "device_firmware_sku": 46216   
}
```

 If an IoT Core rule action for Timestream is created with the SQL statement above, two records will be added to Timestream with measure names temperature and humidity and measure values of 24.04 and 43.605, respectively. 

 You can modify the measure name of a record being added to Timestream by using the AS operator in the SELECT statement. The SQL statement below will create a record with the message name temp instead of temperature. 

 The data type of the measure are inferred from the data type of the value of the message payload. JSON data types such as integer, double, boolean, and string are mapped to Timestream data types of BIGINT, DOUBLE, BOOLEAN, and VARCHAR respectively. Data can also be forced to specific data types using the [cast()](https://docs.aws.amazon.com/iot/latest/developerguide/iot-sql-functions.html#iot-sql-function-cast) function. You can specify the timestamp of the measure. If the timestamp is left blank, the time that the entry was processed is used. 

You can refer to the [ Timestream rules action documentation ](https://docs.aws.amazon.com/iot/latest/developerguide/timestream-rule-action.html) for additional details

 To create an IoT Core rule action to store data in Timestream, follow the steps below: 

**Topics**
+ [Prerequisites](#prereqs)
+ [Using the console](#using-console)
+ [Using the CLI](#using-cli)
+ [Sample application](#sample-app)
+ [Video tutorial](#video-tutorial)

## Prerequisites
<a name="prereqs"></a>

1. Create a database in Amazon Timestream using the instructions described in [Create a database](console_timestream.md#console_timestream.db.using-console).

1. Create a table in Amazon Timestream using the instructions described in [Create a table](console_timestream.md#console_timestream.table.using-console).

## Using the console
<a name="using-console"></a>

1. Use the AWS Management Console for AWS IoT Core to create a rule by clicking on **Manage** > **Messsage routing** > **Rules** followed by **Create rule**.

1. Set the rule name to a name of your choice and the SQL to the text shown below

   ```
   SELECT temperature as temp, humidity from 'iot/topic' 
   ```

1. Select Timestream from the Action list

1. Specify the Timestream database, table, and dimension names along with the role to write data into Timestream. If the role does not exist, you can create one by clicking on Create Roles

1. To test the rule, follow the instructions shown [here](https://docs.aws.amazon.com/iot/latest/developerguide/iot-ddb-rule.html#test-db-rule).

## Using the CLI
<a name="using-cli"></a>

 If you haven't installed the AWS Command Line Interface (AWS CLI), do so from [here](https://aws.amazon.com/cli/). 

1. Save the following rule payload in a JSON file called timestream\$1rule.json. Replace *arn:aws:iam::123456789012:role/TimestreamRole* with your role arn which grants AWS IoT access to store data in Amazon Timestream

   ```
   { 
       "actions": [ 
               { 
                   "timestream": { 
                       "roleArn": "arn:aws:iam::123456789012:role/TimestreamRole", 
                       "tableName": "devices_metrics", 
                       "dimensions": [ 
                           { 
                               "name": "device_id", 
                               "value": "${clientId()}" 
                           }, 
                           { 
                               "name": "device_firmware_sku", 
                               "value": "My Static Metadata" 
                           } 
                       ], 
                       "databaseName": "record_devices" 
                   } 
               } 
       ], 
       "sql": "select * from 'iot/topic'", 
       "awsIotSqlVersion": "2016-03-23", 
       "ruleDisabled": false 
   }
   ```

1. Create a topic rule using the following command

   ```
   aws iot create-topic-rule --rule-name timestream_test --topic-rule-payload file://<path/to/timestream_rule.json> --region us-east-1 
   ```

1. Retrieve details of topic rule using the following command

   ```
   aws iot get-topic-rule --rule-name timestream_test 
   ```

1. Save the following message payload in a file called timestream\$1msg.json

   ```
   {
     "dataFormat": 5, 
     "rssi": -88,
     "temperature": 24.04,    
     "humidity": 43.605,    
     "pressure": 101082,    
     "accelerationX": 40,    
     "accelerationY": -20,    
     "accelerationZ": 1016,    
     "battery": 3007,    
     "txPower": 4,    
     "movementCounter": 219,    
     "device_id": 46216,
     "device_firmware_sku": 46216   
   }
   ```

1. Test the rule using the following command

   ```
   aws iot-data publish --topic 'iot/topic' --payload file://<path/to/timestream_msg.json>
   ```

## Sample application
<a name="sample-app"></a>

 To help you get started with using Timestream with AWS IoT Core, we've created a fully functional sample application that creates the necessary artifacts in AWS IoT Core and Timestream for creating a topic rule and a sample application for publishing a data to the topic. 

1.  Clone the GitHub repository for the [sample application](https://github.com/awslabs/amazon-timestream-tools/blob/master/integrations/iot_core) for AWS IoT Core integration following the instructions from [GitHub](https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/cloning-a-repository)

1. Follow the instructions in the [README](https://github.com/awslabs/amazon-timestream-tools/blob/master/integrations/iot_core) to use an AWS CloudFormation template to create the necessary artifacts in Amazon Timestream and AWS IoT Core and to publish sample messages to the topic.

## Video tutorial
<a name="video-tutorial"></a>

This [video](https://youtu.be/00Wersoz2Q4) explains how IoT Core works with Timestream.

# Amazon Managed Service for Apache Flink
<a name="ApacheFlink"></a>

You can use Apache Flink to transfer your time series data from Amazon Managed Service for Apache Flink, Amazon MSK, Apache Kafka, and other streaming technologies directly into Amazon Timestream for LiveAnalytics. We've created an Apache Flink sample data connector for Timestream. We've also created a sample application for sending data to Amazon Kinesis so that the data can flow from Kinesis to Managed Service for Apache Flink, and finally on to Amazon Timestream. All of these artifacts are available to you in GitHub. This [video tutorial ](https://youtu.be/64DSlBvN5lg) describes the setup.

**Note**  
 Java 11 is the recommended version for using the Managed Service for Apache Flink Application. If you have multiple Java versions, ensure that you export Java 11 to your JAVA\$1HOME environment variable. 

**Topics**
+ [Sample application](#ApacheFlink.sample-app)
+ [Video tutorial](#ApacheFlink.video-tutorial)

## Sample application
<a name="ApacheFlink.sample-app"></a>

To get started, follow the procedure below:

1. Create a database in Timestream with the name `kdaflink` following the instructions described in [Create a database](console_timestream.md#console_timestream.db.using-console).

1. Create a table in Timestream with the name `kinesisdata1` following the instructions described in [Create a table](console_timestream.md#console_timestream.table.using-console).

1. Create an Amazon Kinesis Data Stream with the name `TimestreamTestStream` following the instructions described in [Creating a Stream](https://docs.aws.amazon.com/streams/latest/dev/amazon-kinesis-streams.html#how-do-i-create-a-stream).

1. Clone the GitHub repository for the [Apache Flink data connector for Timestream](https://github.com/awslabs/amazon-timestream-tools/blob/master/integrations/flink_connector) following the instructions from [GitHub](https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/cloning-a-repository).

1.  To compile, run and use the sample application, follow the instructions in the [ Apache Flink sample data connector README](https://github.com/awslabs/amazon-timestream-tools/blob/master/integrations/flink_connector/README.md). 

1. Compile the Managed Service for Apache Flink application following the instructions for [Compiling the Application Code](https://docs.aws.amazon.com/managed-flink/latest/java/get-started-exercise.html#get-started-exercise-5.5).

1. Upload the Managed Service for Apache Flink application binary following the instructions to [Upload the Apache Flink Streaming Code](https://docs.aws.amazon.com/managed-flink/latest/java/get-started-exercise.html#get-started-exercise-6).

   1. After clicking on Create Application, click on the link of the IAM Role for the application.

   1. Attach the IAM policies for **AmazonKinesisReadOnlyAccess** and **AmazonTimestreamFullAccess**.
**Note**  
The above IAM policies are not restricted to specific resources and are unsuitable for production use. For a production system, consider using policies that restrict access to specific resources.

1. Clone the GitHub repository for the [ sample application writing data to Kinesis](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/tools/python/kinesis_ingestor) following the instructions from [GitHub](https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/cloning-a-repository).

1. Follow the instructions in the [README](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/kinesis_ingestor/README.md) to run the sample application for writing data to Kinesis.

1. Run one or more queries in Timestream to ensure that data is being sent from Kinesis to Managed Service for Apache Flink to Timestream following the instructions to [Create a table](console_timestream.md#console_timestream.table.using-console).

## Video tutorial
<a name="ApacheFlink.video-tutorial"></a>

This [video](https://youtu.be/64DSlBvN5lg) explains how to use Timestream with Managed Service for Apache Flink.

# Amazon Kinesis
<a name="Kinesis"></a>

## Using Amazon Managed Service for Apache Flink
<a name="kinesis-via-flink"></a>

You can send data from Kinesis Data Streams to Timestream for LiveAnalytics using the sample Timestream data connector for Managed Service for Apache Flink. Refer to [Amazon Managed Service for Apache Flink](ApacheFlink.md) for Apache Flink for more information.

## Using EventBridge Pipes to send Kinesis data to Timestream
<a name="Kinesis-via-pipes"></a>

You can use EventBridge Pipes to send data from a Kinesis stream to a Amazon Timestream for LiveAnalytics table.

Pipes are intended for point-to-point integrations between supported sources and targets, with support for advanced transformations and enrichment. Pipes reduce the need for specialized knowledge and integration code when developing event-driven architectures. To set up a pipe, you choose the source, add optional filtering, define optional enrichment, and choose the target for the event data.

![\[A source sends events to an EventBridge pipe, which filters and routes matching events to the target.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/pipes-overview_shared_architecture.png)


This integration enables you to leverage the power of Timestream's time-series data analysis capabilities, while simplifying your data ingestion pipeline.

Using EventBridge Pipes with Timestream offers the following benefits:
+ Real-time Data Ingestion: Stream data from Kinesis directly to Timestream for LiveAnalytics, enabling real-time analytics and monitoring.
+ Seamless Integration: Utilize EventBridge Pipes to manage the flow of data without the need for complex custom integrations.
+ Enhanced Filtering and Transformation: Filter or transform Kinesis records before they are stored in Timestream to meet your specific data processing requirements.
+ Scalability: Handle high-throughput data streams and ensure efficient data processing with built-in parallelism and batching capabilities.

### Configuration
<a name="Kinesis-via-pipes-config"></a>

To set up an EventBridge Pipe to stream data from Kinesis to Timestream, follow these steps:

1. Create a Kinesis stream

   Ensure you have an active Kinesis data stream from which you want to ingest data.

1. Create a Timestream database and table

   Set up your Timestream database and table where the data will be stored.

1. Configure the EventBridge Pipe:
   + Source: Select your Kinesis stream as the source.
   + Target: Choose Timestream as the target.
   + Batching Settings: Define batching window and batch size to optimize data processing and reduce latency.

**Important**  
When setting up a pipe, we recommend testing the correctness of all configurations by ingesting a few records. Please note that successful creation of a pipe does not guarantee that the pipeline is correct and data will flow without errors. There may be runtime errors, such as incorrect table, incorrect dynamic path parameter, or invalid Timestream record after applying mapping, that will be discovered when actual data flows through the pipe.

The following configurations determine the rate at which data is ingested:
+ BatchSize: The maximum size of the batch that will be sent to Timestream for LiveAnalytics. Range: 0 - 100. Recommendation is to keep this value as 100 to get maximum throughput.
+ MaximumBatchingWindowInSeconds: The maximum time to wait to fill the batchSize before the batch is sent to Timestream for LiveAnalytics target. Depending on the rate of incoming events, this configuration will decide the delay of ingestion, recommendation is to keep this value < 10s to keep sending the data to Timestream in near real-time.
+ ParallelizationFactor: The number of batches to process concurrently from each shard. Recommendation is to use the maximum value of 10 to get maximum throughput and near real-time ingestion.

  If your stream is read by multiple targets, use enhanced fan-out to provide a dedicated consumer to your pipe to achieve high throughput. For more information, see [Developing enhanced fan-out consumers with the Kinesis Data Streams API](https://docs.aws.amazon.com/streams/latest/dev/building-enhanced-consumers-api.html) in the *Kinesis Data Streams User Guide*.

**Note**  
The maximum throughput that can be achieved is bounded by [concurrent pipe executions](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-quota.html#eb-pipes-limits) per account.

The following configuration ensures prevention of data loss:
+ DeadLetterConfig: Recommendation is to always configure DeadLetterConfig to avoid any data loss for cases when events could not be ingested to Timestream for LiveAnalytics due to user errors.

Optimize your pipe's performance with the following configuration settings, which helps prevent records from causing slowdowns or blockages.
+ MaximumRecordAgeInSeconds: Records older than this will not be processed and will directly get moved to DLQ. We recommend setting this value to be no higher than the configured Memory store retention period of the target Timestream table.
+ MaximumRetryAttempts: The number of retry attempts for a record before the record is sent to DeadLetterQueue. Recommendation is to configure this at 10. This should be able to help address any transient issues and for persistent issues, the record will be moved to DeadLetterQueue and unblock the rest of the stream.
+ OnPartialBatchItemFailure: For sources that support partial batch processing, we recommend you to enable this and configure it as AUTOMATIC\$1BISECT for additional retry of failed records before dropping/sending to DLQ.

#### Configuration example
<a name="Kinesis-via-pipes-config-example"></a>

Here is an example of how to configure an EventBridge Pipe to stream data from a Kinesis stream to a Timestream table:

**Example IAM policy updates for Timestream**    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "timestream:WriteRecords"
            ],
            "Resource": [
                "arn:aws:timestream:us-east-1:123456789012:database/my-database/table/my-table"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "timestream:DescribeEndpoints"
            ],
            "Resource": "*"
        }
    ]
}
```

**Example Kinesis stream configuration**  <a name="kinesis-stream-config.example"></a>

```
{
  "Source": "arn:aws:kinesis:us-east-1:123456789012:stream/my-kinesis-stream",
  "SourceParameters": {
    "KinesisStreamParameters": {
        "BatchSize": 100,
        "DeadLetterConfig": {
            "Arn": "arn:aws:sqs:us-east-1:123456789012:my-sqs-queue"
        },
       "MaximumBatchingWindowInSeconds": 5,
        "MaximumRecordAgeInSeconds": 1800,
        "MaximumRetryAttempts": 10,
        "StartingPosition": "LATEST",
       "OnPartialBatchItemFailure": "AUTOMATIC_BISECT"
    }
  }
}
```

**Example Timestream target configuration**  <a name="kinesis-stream-config.example"></a>

```
{
    "Target": "arn:aws:timestream:us-east-1:123456789012:database/my-database/table/my-table",
    "TargetParameters": {
        "TimestreamParameters": {
            "DimensionMappings": [
                {
                    "DimensionName": "sensor_id",
                    "DimensionValue": "$.data.device_id",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "DimensionName": "sensor_type",
                    "DimensionValue": "$.data.sensor_type",
                    "DimensionValueType": "VARCHAR"
                },
                {
                    "DimensionName": "sensor_location",
                    "DimensionValue": "$.data.sensor_loc",
                    "DimensionValueType": "VARCHAR"
                }
            ],
            "MultiMeasureMappings": [
                {
                    "MultiMeasureName": "readings",
                    "MultiMeasureAttributeMappings": [
                        {
                            "MultiMeasureAttributeName": "temperature",
                            "MeasureValue": "$.data.temperature",
                            "MeasureValueType": "DOUBLE"
                        },
                        {
                            "MultiMeasureAttributeName": "humidity",
                            "MeasureValue": "$.data.humidity",
                            "MeasureValueType": "DOUBLE"
                        },
                        {
                            "MultiMeasureAttributeName": "pressure",
                            "MeasureValue": "$.data.pressure",
                            "MeasureValueType": "DOUBLE"
                        }
                    ]
                }
            ],
            "SingleMeasureMappings": [],
            "TimeFieldType": "TIMESTAMP_FORMAT",
            "TimestampFormat": "yyyy-MM-dd HH:mm:ss.SSS",
            "TimeValue": "$.data.time",
            "VersionValue": "$.approximateArrivalTimestamp"
        }
    }
}
```



### Event transformation
<a name="Kinesis-via-pipes-trans"></a>

EventBridge Pipes allow you to transform data before it reaches Timestream. You can define transformation rules to modify the incoming Kinesis records, such as changing field names.

Suppose your Kinesis stream contains temperature and humidity data. You can use an EventBridge transformation to rename these fields before inserting them into Timestream.

### Best practices
<a name="Kinesis-via-pipes-best"></a>

**Batching and Buffering**
+ Configure the batching window and size to balance between write latency and processing efficiency.
+ Use a batching window to accumulate enough data before processing, reducing the overhead of frequent small batches.

**Parallel Processing**

Utilize the **ParallelizationFactor** setting to increase concurrency, especially for high-throughput streams. This ensures that multiple batches from each shard can be processed simultaneously.

**Data Transformation**

Leverage the transformation capabilities of EventBridge Pipes to filter and enhance records before storing them in Timestream. This can help in aligning the data with your analytical requirements.

**Security**
+ Ensure that the IAM roles used for EventBridge Pipes have the necessary permissions to read from Kinesis and write to Timestream.
+ Use encryption and access control measures to secure data in transit and at rest.

### Debugging failures
<a name="Kinesis-via-pipes-debug"></a>
+ **Automatic Disabling of Pipes**

  Pipes will be automatically disabled in about 2 hours if the target does not exist or has permission issues
+ **Throttles**

  Pipes have the capability to automatically back off and retry until the throttles have reduced.
+ **Enabling Logs**

  We recommend you enable Logs at ERROR level and include execution data to get more insights into failed. Upon any failure, these logs will contain request/response sent/received from Timestream. This helps you understand the error associated and if needed reprocess the records after fixing it.

### Monitoring
<a name="Kinesis-via-pipes-monitor"></a>

We recommend you to set up alarms on the following to detect any issues with data flow:
+ Maximum Age of the Record in Source
  + `GetRecords.IteratorAgeMilliseconds`
+ Failure metrics in Pipes
  + `ExecutionFailed`
  + `TargetStageFailed`
+ Timestream Write API errors
  + `UserErrors`

For additional monitoring metrics, see [Monitoring EventBridge](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-monitoring.html#eb-metrics) in the *EventBridge User Guide*.

# Amazon MQ
<a name="MQ"></a>

## Using EventBridge Pipes to send Amazon MQ data to Timestream
<a name="MQ-via-pipes"></a>

You can use EventBridge Pipes to send data from a Amazon MQ broker to a Amazon Timestream for LiveAnalytics table.

Pipes are intended for point-to-point integrations between supported sources and targets, with support for advanced transformations and enrichment. Pipes reduce the need for specialized knowledge and integration code when developing event-driven architectures. To set up a pipe, you choose the source, add optional filtering, define optional enrichment, and choose the target for the event data.

![\[A source sends events to an EventBridge pipe, which filters and routes matching events to the target.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/pipes-overview_shared_architecture.png)


For more information on EventBridge Pipes, see [EventBridge Pipes](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes.html) in the *EventBridge User Guide*. For information on configuring a pipe to deliver events to a Amazon Timestream for LiveAnalytics table, see [EventBridge Pipes target specifics](https://docs.aws.amazon.com/eventbridge/latest/userguide/pipes-targets-specifics.html#pipes-targets-specifics-timestream).

# Amazon MSK
<a name="MSK"></a>

## Using Managed Service for Apache Flink to send Amazon MSK data to Timestream for LiveAnalytics
<a name="msk-aka"></a>

You can send data from Amazon MSK to Timestream by building a data connector similar to the sample Timestream data connector for Managed Service for Apache Flink. Refer to [Amazon Managed Service for Apache Flink](ApacheFlink.md) for more information.

## Using Kafka Connect to send Amazon MSK data to Timestream for LiveAnalytics
<a name="msk-kafka-connect"></a>

You can use Kafka Connect to ingest your time series data from Amazon MSK directly into Timestream for LiveAnalytics.

We've created a sample Kafka Sink Connector for Timestream. We've also created a sample Apache jMeter test plan for publishing data to a Kafka topic, so that the data can flow from the topic through the Timestream Kafka Sink Connector, to an Timestream for LiveAnalytics table. All of these artifacts are available on GitHub. 

**Note**  
Java 11 is the recommended version for using the Timestream Kafka Sink Connector. If you have multiple Java versions, ensure that you export Java 11 to your JAVA\$1HOME environment variable. 

### Creating a sample application
<a name="msk-kafka-connect-app"></a>

To get started, follow the procedure below.

1. In Timestream for LiveAnalytics, create a database with the name `kafkastream`. 

   See the procedure [Create a database](console_timestream.md#console_timestream.db.using-console) for detailed instructions.

1. In Timestream for LiveAnalytics, create a table with the name `purchase_history`.

   See the procedure [Create a table](console_timestream.md#console_timestream.table.using-console) for detailed instructions.

1. Follow the instructions shared in the to create the following: , and .
   + An Amazon MSK cluster
   + An Amazon EC2 instance that is configured as a Kafka producer client machine 
   + A Kafka topic

   See the [prerequisites](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/tools/java/kafka_ingestor#prerequisites) of the kafka\$1ingestor project for detailed instructions.

1. Clone the [Timestream Kafka Sink Connector](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/integrations/kafka_connector) repository. 

   See [Cloning a repository](https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/cloning-a-repository) on GitHub for detailed instructions.

1. Compile the plugin code.

    See [Connector - Build from source](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/integrations/kafka_connector#connector---build-from-source) on GitHub for detailed instructions.

1. Upload the following files to an S3 bucket: following the instructions described in .
   + The jar file (kafka-connector-timestream->VERSION<-jar-with-dependencies.jar) from the `/target` directory
   + The sample json schema file, `purchase_history.json`.

   See [Uploading objects](https://docs.aws.amazon.com/AmazonS3/latest/userguide/upload-objects.html) in the *Amazon S3 User Guide* for detailed instructions.

1. Create two VPC endpoints. These endpoints would be used by the MSK Connector to access the resources using AWS PrivateLink.
   + One to access the Amazon S3 bucket
   + One to access the Timestream for LiveAnalytics table.

   See [VPC Endpoints](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/integrations/kafka_connector#vpc-endpoints) for detailed instructions.

1. Create a custom plugin with the uploaded jar file.

   See [Plugins](https://docs.aws.amazon.com/msk/latest/developerguide/msk-connect-plugins.html) in the *Amazon MSK Developer Guide * for detailed instructions.

1. Create a custom worker configuration with the JSON content described in [Worker Configuration parameters](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/integrations/kafka_connector#worker-configuration-parameters). following the instructions described in 

   See [Creating a custom worker configuration](https://docs.aws.amazon.com/msk/latest/developerguide/msk-connect-workers.html#msk-connect-create-custom-worker-config) in the *Amazon MSK Developer Guide * for detailed instructions.

1. Create a service execution IAM role.

   See [IAM Service Role](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/integrations/kafka_connector#iam-service-role) for detailed instructions.

1. Create an Amazon MSK connector with the custom plugin, custom worker configuration, and service execution IAM role created in the previous steps and with the [Sample Connector Configuration](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/integrations/kafka_connector#sample-connector-configuration).

   See [Creating a connector](https://docs.aws.amazon.com/msk/latest/developerguide/msk-connect-connectors.html#mkc-create-connector-intro) in the *Amazon MSK Developer Guide * for detailed instructions.

   Make sure to update the values of the below configuration parameters with respective values. See [Connector Configuration parameters](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/integrations/kafka_connector#connector-configuration-parameters) for details.
   + `aws.region`
   + `timestream.schema.s3.bucket.name`
   + `timestream.ingestion.endpoint`

   The connector creation takes 5–10 minutes to complete. The pipeline is ready when its status changes to `Running`.

1. Publish a continuous stream of messages for writing data to the Kafka topic created.

   See [How to use it](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/tools/java/kafka_ingestor#how-to-use-it) for detailed instructions.

1. Run one or more queries to ensure that the data is being sent from Amazon MSK to MSK Connect to the Timestream for LiveAnalytics table. 

   See the procedure [Run a query](console_timestream.md#console_timestream.queries.using-console) for detailed instructions.

#### Additional resources
<a name="msk-kafka-connect-more-info"></a>

The blog, [Real-time serverless data ingestion from your Kafka clusters into Timestream for LiveAnalytics using Kafka Connect](https://aws.amazon.com/blogs/database/real-time-serverless-data-ingestion-from-your-kafka-clusters-into-amazon-timestream-using-kafka-connect/) explains setting up an end-to-end pipeline using the Timestream for LiveAnalytics Kafka Sink Connector, starting from a Kafka producer client machine that uses the Apache jMeter test plan to publish thousands of sample messages to a Kafka topic to verifying the ingested records in an Timestream for LiveAnalytics table.

# Amazon Quick
<a name="Quicksight"></a>

You can use Amazon Quick to analyze and publish data dashboards that contain your Amazon Timestream data. This section describes how you can create a new QuickSight data source connection, modify permissions, create new datasets, and perform an analysis. This [video tutorial ](https://youtu.be/TzW4HWl-L8s) describes how to work with Timestream and Quick. 

**Note**  
 All datasets in Quick are read-only. You can't make any changes to your actual data in Timestream by using Quick to remove the data source, dataset, or fields. 

**Topics**
+ [Accessing Amazon Timestream from QuickSight](#Quicksight.accessing)
+ [Create a new QuickSight data source connection for Timestream](#Quicksight.create-connection)
+ [Edit permissions for the QuickSight data source connection for Timestream](#Quicksight.permissions)
+ [Create a new QuickSight dataset for Timestream](#Quicksight.create-data)
+ [Create a new analysis for Timestream](#Quicksight.create-analysis)
+ [Video tutorial](#Quicksight.video-tutorial)

## Accessing Amazon Timestream from QuickSight
<a name="Quicksight.accessing"></a>

 Before you can proceed, Amazon QuickSight needs to be authorized to connect to Amazon Timestream. If connections are not enabled, you will receive an error when you try to connect. A QuickSight administrator can authorize connections to AWS resources. To authorize a connection from QuickSight to Timestream, follow the procedure at [Using Other AWS Services: Scoping Down Access](https://docs.aws.amazon.com/quicksight/latest/user/scoping-policies-for-access-to-aws-resources.html), choosing Amazon Timestream in step 5. 

## Create a new QuickSight data source connection for Timestream
<a name="Quicksight.create-connection"></a>

**Note**  
The connection between Amazon QuickSight and Amazon Timestream is encrypted in transit using SSL (TLS 1.2). You cannot create an unencrypted connection.

1. Ensure you have configured the appropriate permissions for Amazon QuickSight to access Amazon Timestream, as described in [Accessing Amazon Timestream from QuickSight](#Quicksight.accessing).

1. Begin by creating a new dataset. Choose **Datasets** from the navigation pane, then choose **New Dataset**. 

1. Select the Timestream data source card.

1. For **Data source name**, enter a name for your Timestream data source connection, for example `US Timestream Data`. 
**Note**  
Because you can create many datasets from a connection to Timestream, it's best to keep the name simple.

1. Choose **Validate connection** to check that you can successfully connect to Timestream.
**Note**  
 **Validate connection** only validates that you can connect. However, it doesn't validate a specific table or query. 

1. Choose **Create data source** to proceed.

1. For **Database**, choose **Select...** to view the list of available options. Choose the one you want to use. 

1. Choose **Select** to continue. 

1. Choose one of the following:
   + To import your data into QuickSight's in-memory engine (called SPICE), choose **Import to SPICE for quicker analytics**. 
   + To allow QuickSight to run a query against your data each time you refresh the dataset or use the analysis or dashboard, choose **Directly query your data**. 

1. Choose **Edit/Preview** and then **Save** to save your dataset and close it.

## Edit permissions for the QuickSight data source connection for Timestream
<a name="Quicksight.permissions"></a>

 The following procedure describes how to view, add, and revoke permissions for other QuickSight users so that they can access the same Timestream data source. The people need to be active users in QuickSight before you can add them. 

**Note**  
In QuickSight, data sources have two permissions levels: user and owner.  
Choose *user* to allow read access. 
Choose *owner* to allow that user to edit, share, or delete this QuickSight data source. 

1. Ensure you have configured the appropriate permissions for Amazon QuickSight to access Amazon Timestream, as described in [Accessing Amazon Timestream from QuickSight](#Quicksight.accessing).

1. Choose **Datasets** at left, then scroll down to find the data source card for your Timestream connection. For example `US Timestream Data`.

1. Choose the `Timestream` data source card.

1. Choose `Share data source`. A list of current permissions displays. 

1. (Optional) To edit permissions, you can choose `user` or `owner`. 

1. (Optional) To revoke permissions, choose `Revoke access`. People you revoke can't create new datasets from this data source. However, their existing datasets will still have access to this data source.

1. To add permissions, choose `Invite users`, then follow these steps to add a user:

   1. Add people to allow them to use the same data source.

   1. For each, choose the `Permission` that you want to apply.

1. When you are finished, choose `Close`.

## Create a new QuickSight dataset for Timestream
<a name="Quicksight.create-data"></a>

1. Ensure you have configured the appropriate permissions for Amazon QuickSight to access Amazon Timestream, as described in [Accessing Amazon Timestream from QuickSight](#Quicksight.accessing).

1. Choose **Datasets** at left, then scroll down to find the data source card for your Timestream connection. If you have many data sources, you can use the search bar at the top of the page to find it with a partial match on the name.

1. Choose the **Timestream** data source card. Then choose **Create data set**.

1. For **Database**, choose **Select** to view the list of available options. Choose the database that you want to use. 

1. For **Tables**, choose the table that you want to use.

1. Choose **Edit/Preview**.

1. (Optional) To add more data, choose **Add data** at top right. 

   1. Choose **Switch data source**, and choose a different data source. 

   1. Follow the UI prompts to finish adding data. 

   1. After adding new data to the same dataset, choose **Configure this join **(the two red dots). Set up a join for each additional table. 

   1. If you want to add calculated fields, choose **Add calculated field**. 

   1. To use Sagemaker, choose **Augment with SageMaker**. This option is only available in QuickSight Enterprise edition.

   1. Uncheck any fields you want to omit.

   1. Update any data types you want to change.

1. When you are done, choose **Save** to save and close the dataset. 

## Create a new analysis for Timestream
<a name="Quicksight.create-analysis"></a>

1. Ensure you have configured the appropriate permissions for Amazon QuickSight to access Amazon Timestream, as described in [Accessing Amazon Timestream from QuickSight](#Quicksight.accessing).

1. Choose **Analyses** at left.

1. Choose one of the following:
   + To create a new analysis, choose **New analysis** at right.
   + To add the Timestream dataset to an existing analysis, open the analysis you want to edit. Choose the pencil icon near at top left, then **Add data set**.

1. Start the first data visualization by choosing fields on the left. 

1. For more information, see [ Working with Analyses - Amazon QuickSight ](https://docs.aws.amazon.com/quicksight/latest/user/working-with-analyses.html)

## Video tutorial
<a name="Quicksight.video-tutorial"></a>

This [video](https://youtu.be/TzW4HWl-L8s) explains how Quick works with Timestream.

# Amazon SageMaker AI
<a name="Sagemaker"></a>

 You can use Amazon SageMaker Notebooks to integrate your machine learning models with Amazon Timestream. To help you get started, we have created a sample SageMaker Notebook that processes data from Timestream. The data is inserted into Timestream from a multi-threaded Python application continuously sending data. The source code for the sample SageMaker Notebook and the sample Python application are available in GitHub. 

1. Create a database and table following the instructions described in [Create a database](console_timestream.md#console_timestream.db.using-console) and [Create a table](console_timestream.md#console_timestream.table.using-console). 

1. Clone the GitHub repository for the [ multi-threaded Python sample application](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/tools/python/continuous-ingestor) following the instructions from [ GitHub](https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/cloning-a-repository).

1. Clone the GitHub repository for the [sample Timestream SageMaker Notebook](https://github.com/awslabs/amazon-timestream-tools/blob/master/integrations/sagemaker) following the instructions from [ GitHub](https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/cloning-a-repository). 

1. Run the application for continuously ingesting data into Timestream following the instructions in the [README](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/continuous-ingestor/README.md).

1. Follow the instructions to create an Amazon S3 bucket for Amazon SageMaker as described [here](https://docs.aws.amazon.com/sagemaker/latest/dg/gs-config-permissions.html).

1. Create an Amazon SageMaker instance with latest boto3 installed: In addition to the instructions described [here](https://docs.aws.amazon.com/sagemaker/latest/dg/gs-setup-working-env.html), follow the steps below: 

   1. On the **Create notebook** instance page, click on **Additional Configuration**

   1. Click on **Lifecycle configuration - *optional*** and select **Create a new lifecycle configuration**

   1. On the *Create lifecycle configuration* wizard box, do the following:

      1. Fill in a desired name to the configuration, e.g. `on-start`

      1. In Start Notebook script, copy-paste the script content from [ Github](https://github.com/aws-samples/amazon-sagemaker-notebook-instance-lifecycle-config-samples/blob/master/scripts/install-pip-package-single-environment/on-start.sh) 

      1. Replace `PACKAGE=scipy` with `PACKAGE=boto3` in the pasted script.

1. Click on **Create configuration**

1. Go to the IAM service in the AWS Management Console and find the newly created SageMaker execution role for the notebook instance.

1. Attach the IAM policy for `AmazonTimestreamFullAccess` to the execution role.
**Note**  
The `AmazonTimestreamFullAccess` IAM policy is not restricted to specific resources and is unsuitable for production use. For a production system, consider using policies that restrict access to specific resources.

1. When the status of the notebook instance is **InService**, choose **Open Jupyter** to launch a SageMaker Notebook for the instance

1.  Upload the files `timestreamquery.py` and `Timestream_SageMaker_Demo.ipynb` into the Notebook by selecting the **Upload** button

1. Choose `Timestream_SageMaker_Demo.ipynb`
**Note**  
If you see a pop up with **Kernel not found**, choose **conda\$1python3** and click **Set Kernel**.

1. Modify `DB_NAME`, `TABLE_NAME`, `bucket`, and `ENDPOINT` to match the database name, table name, S3 bucket name, and region for the training models.

1. Choose the **play** icon to run the individual cells

1. When you get to the cell `Leverage Timestream to find hosts with average CPU utilization across the fleet`, ensure that the output returns at least 2 host names.
**Note**  
If there are less than 2 host names in the output, you may need to rerun the sample Python application ingesting data into Timestream with a larger number of threads and host-scale. 

1. When you get to the cell `Train a Random Cut Forest (RCF) model using the CPU utilization history`, change the `train_instance_type` based on the resource requirements for your training job

1. When you get to the cell `Deploy the model for inference`, change the `instance_type` based on the resource requirements for your inference job
**Note**  
It may take a few minutes to train the model. When the training is complete, you will see the message **Completed - Training job completed** in the output of the cell.

1. Run the cell `Stop and delete the endpoint` to clean up resources. You can also stop and delete the instance from the SageMaker console

# Amazon SQS
<a name="SQS"></a>

## Using EventBridge Pipes to send Amazon SQS data to Timestream
<a name="SQS-via-pipes"></a>

You can use EventBridge Pipes to send data from a Amazon SQS queue to a Amazon Timestream for LiveAnalytics table.

Pipes are intended for point-to-point integrations between supported sources and targets, with support for advanced transformations and enrichment. Pipes reduce the need for specialized knowledge and integration code when developing event-driven architectures. To set up a pipe, you choose the source, add optional filtering, define optional enrichment, and choose the target for the event data.

![\[A source sends events to an EventBridge pipe, which filters and routes matching events to the target.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/pipes-overview_shared_architecture.png)


For more information on EventBridge Pipes, see [EventBridge Pipes](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes.html) in the *EventBridge User Guide*. For information on configuring a pipe to deliver events to a Amazon Timestream for LiveAnalytics table, see [EventBridge Pipes target specifics](https://docs.aws.amazon.com/eventbridge/latest/userguide/pipes-targets-specifics.html#pipes-targets-specifics-timestream).

# Using DBeaver to work with Amazon Timestream
<a name="DBeaver"></a>

[DBeaver](https://dbeaver.io/) is a free universal SQL client that can be used to manage any database that has a JDBC driver. It is widely used among developers and database administrators because of its robust data viewing, editing, and management capabilities.

Using DBeaver's cloud connectivity options, you can connect DBeaver to Amazon Timestream natively. DBeaver provides a comprehensive and intuitive interface to work with time series data directly from within a DBeaver application. Using your credentials, it also gives you full access to any queries that you could execute from another query interface. It even lets you create graphs for better understanding and visualization of query results.

## Setting up DBeaver to work with Timestream
<a name="DBeaver-setup"></a>

Take the following steps to set up DBeaver to work with Timestream:

1. [Download and install DBeaver](https://dbeaver.io/download/) on your local machine.

1. Launch DBeaver, navigate to the database selection area, choose **Timeseries** in the left pane, and then select the **Timestream** icon in the right pane:  
![\[DBeaver screenshot showing how to select Timestream in the database selection area.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/DBeaver-01.png)

1. In the **Timestream Connection Settings** window, enter all the information necessary to connect to your Amazon Timestream database. Please ensure that the user keys you enter have the permissions necessary to access your Timestream database. Also, be sure to keep the information and keys you input into DBeaver safe and private, as with any sensitive information.  
![\[DBeaver screenshot showing connection fields for Timestream.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/DBeaver-02.png)

1. Test the connection to ensure that everything is set up correctly:  
![\[DBeaver screenshot showing a successful connection test.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/DBeaver-03.png)

1. If the connection test is successful, you can now interact with your Amazon Timestream database just as you would with any other database in DBeaver. For example, you can navigate to the SQL editor or to the ER Diagram view to run queries:  
![\[DBeaver screenshot showing a Timestream query run from the SQL editor.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/DBeaver-04.png)

1. DBeaver also provides powerful data visualization tools. To use them, run your query, then select the graph icon to visualize the result set. The graphing tool can help you better understand data trends over time.

Pairing Amazon Timestream with DBeaver creates an effective environment for managing time series data. You can integrate it seamlessly into your existing workflow to enhance productivity and efficiency.

# Grafana
<a name="Grafana"></a>

 You can visualize your time series data and create alerts using Grafana. To help you get started with data visualization, we have created a sample dashboard in Grafana that visualizes data sent to Timestream from a Python application and a [video tutorial ](https://youtu.be/pilkz645cs4) that describes the setup. 

**Topics**
+ [Sample application](#Grafana.sample-app)
+ [Video tutorial](#Grafana.video-tutorial)

## Sample application
<a name="Grafana.sample-app"></a>

1.  Create a database and a table in Timestream following the instructions described in [Create a database](console_timestream.md#console_timestream.db.using-console) for more information. 
**Note**  
 The default database name and table name for the Grafana dashboard are set to grafanaDB and grafanaTable respectively. Use these names to minimize setup. 

1. Install [Python 3.7 ](https://www.python.org/downloads/)or higher.

1.  [Install and configure the Timestream Python SDK](getting-started.python.md).s

1.  Clone the GitHub repository for the [multi-thread Python application](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/tools/python/continuous-ingestor) continuously ingesting data into Timestream following the instructions from [GitHub](https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/cloning-a-repository).

1. Run the application for continuously ingesting data into Timestream following the instructions in the [README](https://github.com/awslabs/amazon-timestream-tools/blob/mainline/tools/python/continuous-ingestor/README.md). 

1. Complete [Learn how to create and use Amazon Managed Grafana resources](https://docs.aws.amazon.com/grafana/latest/userguide/getting-started-with-AMG.html) or complete [Install Grafana](https://grafana.com/docs/grafana/latest/installation/).

1. If installing Grafana instead of using Amazon Managed Grafana, complete [Installing Amazon Timestream on Grafana Cloud](https://grafana.com/grafana/plugins/grafana-timestream-datasource/?tab=installation/).

1. Open the Grafana dashboard using a browser of your choice. If you've locally installed Grafana, you can follow the instructions described in the Grafana documentation to [log in](https://grafana.com/docs/grafana/latest/getting-started/getting-started/#log-in-for-the-first-time).

1. After launching Grafana, go to Datasources, click on Add Datasource, search for Timestream, and select the Timestream datasource.

1. Configure the Auth Provider and the region and click Save and Test.

1. Set the default macros.

   1. Set \$1\$1\$1database to the name of your Timestream database (e.g. grafanaDB).

   1. Set \$1\$1\$1table to the name of your Timestream table (e.g. grafanaTable).

   1. Set \$1\$1\$1measure to the most commonly used measure from the table.

1. Click Save and Test.

1. Click on the Dashboards tab.

1. Click on Import to import the dashboard.

1. Double click the Sample Application Dashboard.

1. Click on the dashboard settings.

1. Select Variables.

1. Change dbName and tableName to match the names of the Timestream database and table.

1. Click Save.

1. Refresh the dashboard.

1. To create alerts, follow the instructions described in the Grafana documentation to [Configure Grafana-managed alert rules](https://grafana.com/docs/grafana/latest/alerting/alerting-rules/create-grafana-managed-rule/).

1. To troubleshoot alerts, follow the instructions described in the Grafana documentation for [Troubleshooting](https://grafana.com/docs/grafana/latest/troubleshooting/).

1. For additional information, see the [Grafana documentation](https://grafana.com/docs/).

## Video tutorial
<a name="Grafana.video-tutorial"></a>

This [video](https://youtu.be/pilkz645cs4) explains how Grafana works with Timestream.

# Using SquaredUp to work with Amazon Timestream
<a name="SquaredUp"></a>

[SquaredUp](https://SquaredUp.com/) is an observability platform that integrates with Amazon Timestream. You can use SquaredUp's intuitive dashboard designer to visualize, analyze, and monitor your time-series data. Dashboards can be shared publicly or privately, and notification channels can be created to alert you when the health state of a monitor changes.

## Using SquaredUp with Amazon Timestream
<a name="SquaredUp-using"></a>

1. [Sign up](https://app.squaredup.com/?signup=true) for [SquaredUp](https://squaredup.com/) and get started for free.

1. Add an [AWS data source](https://squaredup.com/cloud/pluginsetup-aws).

1. Create a dashboard tile that uses the [Timestream Query](https://squaredup.com/cloud/AWS-Timestream-Query) data stream.

1. Optionally, enable monitoring for the tile, create a notification channel, or share the dashboard publicly or privately.

1. Optionally create other tiles to see your Timestream data alongside data from your other monitoring and observability tools.

# Open source Telegraf
<a name="Telegraf"></a>

 You can use the Timestream for LiveAnalytics output plugin for Telegraf to write metrics into Timestream for LiveAnalytics directly from open source Telegraf.

 This section provides an explanation of how to install Telegraf with the Timestream for LiveAnalytics output plugin, how to run Telegraf with the Timestream for LiveAnalytics output plugin, and how open source Telegraf works with Timestream for LiveAnalytics.

**Topics**
+ [Installing Telegraf with the Timestream for LiveAnalytics output plugin](Telegraf.installing-output-plugin.md)
+ [Running Telegraf with the Timestream for LiveAnalytics output plugin](Telegraf.running-output-plugin.title.md)
+ [Mapping Telegraf/InfluxDB metrics to the Timestream for LiveAnalytics model](Telegraf.how-it-works.md)

# Installing Telegraf with the Timestream for LiveAnalytics output plugin
<a name="Telegraf.installing-output-plugin"></a>

As of version 1.16, the Timestream for LiveAnalytics output plugin is available in the official Telegraf release. To install the output plugin on most major operating systems, follow the steps outlined in the [InfluxData Telegraf Documentation](https://docs.influxdata.com/telegraf/v1.16/introduction/installation/). To install on the Amazon Linux 2 OS, follow the instructions below.

## Installing Telegraf with the Timestream for LiveAnalytics output plugin on Amazon Linux 2
<a name="w2aab7c44c35b9b5"></a>

 To install Telegraf with the Timestream Output Plugin on Amazon Linux 2, perform the following steps. 

1. Install Telegraf using the `yum` package manager.

   ```
   cat <<EOF | sudo tee /etc/yum.repos.d/influxdb.repo
   [influxdb]
   name = InfluxDB Repository - RHEL \$releasever
   baseurl = https://repos.influxdata.com/rhel/\$releasever/\$basearch/stable
   enabled = 1
   gpgcheck = 1
   gpgkey = https://repos.influxdata.com/influxdb.key
   EOF
   ```

1. Run the following command.

   ```
   sudo sed -i "s/\$releasever/$(rpm -E %{rhel})/g" /etc/yum.repos.d/influxdb.repo
   ```

1. Install and start Telegraf.

   ```
   sudo yum install telegraf
   sudo service telegraf start
   ```

# Running Telegraf with the Timestream for LiveAnalytics output plugin
<a name="Telegraf.running-output-plugin.title"></a>

You can follow the instructions below to run Telegraf with the Timestream for LiveAnalytics plugin.

1. Generate an example configuration using Telegraf.

   ```
   telegraf --section-filter agent:inputs:outputs --input-filter cpu:mem --output-filter timestream config > example.config
   ```

1. Create a database in Timestream [using the management console](console_timestream.md#console_timestream.db.using-console), [CLI](https://docs.aws.amazon.com/cli/latest/reference/timestream-write/create-database.html), or [SDKs](getting-started-sdks.md).

1. In the `example.config` file, add your database name by editing the following key under the `[[outputs.timestream]] ` section.

   ```
   database_name = "yourDatabaseNameHere"
   ```

1. By default, Telegraf will create a table. If you wish create a table manually, set `create_table_if_not_exists` to `false` and follow the instructions to create a table [using the management console](console_timestream.md#console_timestream.table.using-console), [CLI](https://docs.aws.amazon.com/cli/latest/reference/timestream-write/create-table.html), or [SDKs](getting-started-sdks.md).

1. In the *example.config* file, configure credentials under the `[[outputs.timestream]] ` section. The credentials should allow the following operations.

   ```
   timestream:DescribeEndpoints
   timestream:WriteRecords
   ```
**Note**  
If you leave `create_table_if_not_exists` set to `true`, include:  

   ```
   timestream:CreateTable
   ```
**Note**  
If you set `describe_database_on_start` to `true`, include the following.  

   ```
   timestream:DescribeDatabase
   ```

1. You can edit the rest of the configuration according to your preferences.

1. When you have finished editing the config file, run Telegraf with the following.

   ```
   ./telegraf --config example.config
   ```

1. Metrics should appear within a few seconds, depending on your agent configuration. You should also see the new tables, *cpu* and *mem*, in the Timestream console.

# Mapping Telegraf/InfluxDB metrics to the Timestream for LiveAnalytics model
<a name="Telegraf.how-it-works"></a>

 When writing data from Telegraf to Timestream for LiveAnalytics, the data is mapped as follows.
+ The timestamp is written as the time field.
+ Tags are written as dimensions.
+ Fields are written as measures.
+ Measurements are mostly written as table names (more on this below).

The Timestream for LiveAnalytics output plugin for Telegraf offers multiple options for organizing and storing data in Timestream for LiveAnalytics. This can be described with an example which begins with the data in line protocol format.

`weather,location=us-midwest,season=summer temperature=82,humidity=71 1465839830100400200 airquality,location=us-west no2=5,pm25=16 1465839830100400200`

The following describes the data.
+ The measurement names are `weather` and `airquality`.
+ The tags are `location` and `season`.
+ The fields are `temperature`, `humidity`, `no2`, and `pm25`.

**Topics**
+ [Storing the data in multiple tables](#Telegraf.how-it-works.multi-table-single-measure.title)
+ [Storing the data in a single table](#Telegraf.how-it-works.single-table-single-measure.title)

## Storing the data in multiple tables
<a name="Telegraf.how-it-works.multi-table-single-measure.title"></a>

You can choose to create a separate table per measurement and store each field in a separate row per table.

The configuration is `mapping_mode = "multi-table"`.
+ The Timestream for LiveAnalytics adapter will create two tables, namely, `weather` and `airquality`.
+ Each table row will contain a single field only.

The resulting Timestream for LiveAnalytics tables, `weather` and `airquality`, will look like this.


**`weather`**  

| time | location | season | measure\$1name | measure\$1value::bigint | 
| --- | --- | --- | --- | --- | 
|  2016-06-13 17:43:50  |  us-midwest  |  summer  |  temperature  |  82  | 
|  2016-06-13 17:43:50  |  us-midwest  |  summer  |  humidity  |  71  | 


**`airquality`**  

| time | location | measure\$1name | measure\$1value::bigint | 
| --- | --- | --- | --- | 
|  2016-06-13 17:43:50  |  us-midwest  |  no2   |  5  | 
|  2016-06-13 17:43:50  |  us-midwest  |  pm25   |  16  | 

## Storing the data in a single table
<a name="Telegraf.how-it-works.single-table-single-measure.title"></a>

You can choose to store all the measurements in a single table and store each field in a separate table row.

The configuration is `mapping_mode = "single-table"`. There are two addition configurations when using `single-table`, `single_table_name` and `single_table_dimension_name_for_telegraf_measurement_name`.
+ The Timestream for LiveAnalytics output plugin will create a single table with name *<single\$1table\$1name>* which includes a *<single\$1table\$1dimension\$1name\$1for\$1telegraf\$1measurement\$1name>* column.
+ The table may contain multiple fields in a single table row.

The resulting Timestream for LiveAnalytics table will look like this.


**`weather`**  

| time | location | season | *<single\$1table\$1dimension\$1name\$1 for\$1telegraf\$1measurement\$1name>* | measure\$1name | measure\$1value::bigint | 
| --- | --- | --- | --- | --- | --- | 
|  2016-06-13 17:43:50  |  us-midwest  |  summer  |  weather  |  temperature  |  82  | 
|  2016-06-13 17:43:50  |  us-midwest  |  summer  |  weather  |  humidity  |  71  | 
|  2016-06-13 17:43:50  |  us-midwest  |  summer  |  airquality  |  no2  |  5  | 
|  2016-06-13 17:43:50  |  us-midwest  |  summer  |  weather  |  pm25  |  16  | 

# JDBC
<a name="JDBC"></a>

 You can use a Java Database Connectivity (JDBC) connection to connect Timestream for LiveAnalytics to your business intelligence tools and other applications, such as [SQL Workbench](https://www.sql-workbench.eu/). The Timestream for LiveAnalytics JDBC driver currently supports SSO with Okta and Microsoft Azure AD. 

**Topics**
+ [Configuring the JDBC driver for Timestream for LiveAnalytics](JDBC.configuring.md)
+ [Connection properties](JDBC.connection-properties.md)
+ [JDBC URL examples](JDBC.url-examples.md)
+ [Setting up Timestream for LiveAnalytics JDBC single sign-on authentication with Okta](JDBC.SSOwithOkta.md)
+ [Setting up Timestream for LiveAnalytics JDBC single sign-on authentication with Microsoft Azure AD](JDBC.withAzureAD.md)

# Configuring the JDBC driver for Timestream for LiveAnalytics
<a name="JDBC.configuring"></a>

Follow the steps below to configure the JDBC driver. 

**Topics**
+ [Timestream for LiveAnalytics JDBC driver JARs](#w2aab7c44c37b7b7)
+ [Timestream for LiveAnalytics JDBC driver class and URL format](#w2aab7c44c37b7b9)
+ [Sample application](#w2aab7c44c37b7c11)

## Timestream for LiveAnalytics JDBC driver JARs
<a name="w2aab7c44c37b7b7"></a>

 You can obtain the Timestream for LiveAnalytics JDBC driver via direct download or by adding the driver as a Maven dependency. 
+  *As a direct download:*. To directly download the Timestream for LiveAnalytics JDBC driver, complete the following steps:

  1. Navigate to [ https://github.com/awslabs/amazon-timestream-driver-jdbc/releases ](https://github.com/awslabs/amazon-timestream-driver-jdbc/releases) 

  1. You can use `amazon-timestream-jdbc-1.0.1-shaded.jar` directly with your business intelligence tools and applications

  1. Download `amazon-timestream-jdbc-1.0.1-javadoc.jar` to a directory of your choice.

  1. In the directory where you have downloaded `amazon-timestream-jdbc-1.0.1-javadoc.jar`, run the following command to extract the Javadoc HTML files: 

     ```
     jar -xvf amazon-timestream-jdbc-1.0.1-javadoc.jar
     ```
+  *As a Maven dependency:* To add the Timestream for LiveAnalytics JDBC driver as a Maven dependency, complete the following steps:

  1. Navigate to and open your application's `pom.xml` file in an editor of your choice.

  1. Add the JDBC driver as a dependency into your application's `pom.xml` file:

     ```
     <!-- https://mvnrepository.com/artifact/software.amazon.timestream/amazon-timestream-jdbc -->
     <dependency>
         <groupId>software.amazon.timestream</groupId>
         <artifactId>amazon-timestream-jdbc</artifactId>
         <version>1.0.1</version>
     </dependency>
     ```

## Timestream for LiveAnalytics JDBC driver class and URL format
<a name="w2aab7c44c37b7b9"></a>

 The driver class for Timestream for LiveAnalytics JDBC driver is: 

```
software.amazon.timestream.jdbc.TimestreamDriver
```

 The Timestream JDBC driver requires the following JDBC URL format: 

```
jdbc:timestream:
```

 To specify database properties through the JDBC URL, use the following URL format: 

```
jdbc:timestream://
```

## Sample application
<a name="w2aab7c44c37b7c11"></a>

To help you get started with using Timestream for LiveAnalytics with JDBC, we've created a fully functional sample application in GitHub.

1. Create a database with sample data following the instructions described [here](getting-started.db-w-sample-data.md#getting-started.db-w-sample-data.using-console).

1. Clone the GitHub repository for the [sample application for JDBC](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/integrations/jdbc) following the instructions from [GitHub](https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/cloning-a-repository).

1. Follow the instructions in the [README](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/integrations/jdbc/README.md) to get started with the sample application.

# Connection properties
<a name="JDBC.connection-properties"></a>

 The Timestream for LiveAnalytics JDBC driver supports the following options: 

**Topics**
+ [Basic authentication options](#JDBC.connection-properties.basic-auth)
+ [Standard client info option](#JDBC.connection-properties.standard-client)
+ [Driver configuration option](#JDBC.connection-properties.driver-config)
+ [SDK option](#JDBC.connection-properties.sdk-options)
+ [Endpoint configuration option](#JDBC.connection-properties.endpoint-config)
+ [Credential provider options](#JDBC.connection-properties.cred-providers)
+ [SAML-based authentication options for Okta](#JDBC.connection-properties.okta)
+ [SAML-based authentication options for Azure AD](#JDBC.connection-properties.azure-ad)

**Note**  
 If none of the properties are provided, the Timestream for LiveAnalytics JDBC driver will use the default credentials chain to load the credentials. 

**Note**  
 All property keys are case-sensitive. 

## Basic authentication options
<a name="JDBC.connection-properties.basic-auth"></a>

The following table describes the available Basic Authentication options.


| Option | Description | Default | 
| --- | --- | --- | 
|  AccessKeyId  |  The AWS user access key id.  |  NONE  | 
|  SecretAccessKey  |  The AWS user secret access key.  |  NONE  | 
|  SessionToken  |  The temporary session token required to access a database with multi-factor authentication (MFA) enabled.  |  NONE  | 

## Standard client info option
<a name="JDBC.connection-properties.standard-client"></a>

The following table describes the Standard Client Info Option.


| Option | Description | Default | 
| --- | --- | --- | 
|  ApplicationName  |  The name of the application currently utilizing the connection. `ApplicationName` is used for debugging purposes and will not be communicated to the Timestream for LiveAnalytics service.  |  The application name detected by the driver.  | 

## Driver configuration option
<a name="JDBC.connection-properties.driver-config"></a>

The following table describes the Driver Configuration Option.


| Option | Description | Default | 
| --- | --- | --- | 
|  EnableMetaDataPreparedStatement  |  Enables Timestream for LiveAnalytics JDBC driver to return metadata for `PreparedStatements`, but this will incur an additional cost with Timestream for LiveAnalytics when retrieving the metadata.  |  FALSE  | 
|  Region  |  The database's region.  |  us-east-1  | 

## SDK option
<a name="JDBC.connection-properties.sdk-options"></a>

The following table describes the SDK Option.


| Option | Description | Default | 
| --- | --- | --- | 
|  RequestTimeout  |  The time in milliseconds the AWS SDK will wait for a query request before timing out. Non-positive value disables request timeout.  |  0  | 
|  SocketTimeout  |  The time in milliseconds the AWS SDK will wait for data to be transferred over an open connection before timing out. Value must be non-negative. A value of `0` disables socket timeout.  |  50000  | 
|  MaxRetryCountClient  |  The maximum number of retry attempts for retryable errors with 5XX error codes in the SDK. The value must be non-negative.  |  NONE  | 
|  MaxConnections  |  The maximum number of allowed concurrently opened HTTP connections to the Timestream for LiveAnalytics service. The value must be positive.  |  50  | 

## Endpoint configuration option
<a name="JDBC.connection-properties.endpoint-config"></a>

The following table describes the Endpoint Configuration Option.


| Option | Description | Default | 
| --- | --- | --- | 
|  Endpoint  |  The endpoint for the Timestream for LiveAnalytics service.  |  NONE  | 

## Credential provider options
<a name="JDBC.connection-properties.cred-providers"></a>

The following table describes the available Credential Provider options.


| Option | Description | Default | 
| --- | --- | --- | 
|  AwsCredentialsProviderClass  |  One of `PropertiesFileCredentialsProvider` or `InstanceProfileCredentialsProvider` to use for authentication.  |  NONE  | 
|  CustomCredentialsFilePath  |  The path to a properties file containing AWS security credentials `accessKey` and `secretKey`. This is only required if `AwsCredentialsProviderClass` is specified as `PropertiesFileCredentialsProvider` .  |  NONE  | 

## SAML-based authentication options for Okta
<a name="JDBC.connection-properties.okta"></a>

The following table describes the available SAML-based authentication options for Okta.


| Option | Description | Default | 
| --- | --- | --- | 
|  IdpName  |  The Identity Provider (Idp) name to use for SAML-based authentication. One of `Okta` or `AzureAD`.  |  NONE  | 
|  IdpHost  |  The host name of the specified Idp.  |  NONE  | 
|  IdpUserName  |  The user name for the specified Idp account.  |  NONE  | 
|  IdpPassword  |  The password for the specified Idp account.  |  NONE  | 
|  OktaApplicationID  |  The unique Okta-provided ID associated with the Timestream for LiveAnalytics application. `AppId` can be found in the `entityID` field provided in the application metadata. Consider the following example: `entityID = http://www.okta.com//IdpAppID`  |  NONE  | 
|  RoleARN  |  The Amazon Resource Name (ARN) of the role that the caller is assuming.  |  NONE  | 
|  IdpARN  |  The Amazon Resource Name (ARN) of the SAML provider in IAM that describes the Idp.  |  NONE  | 

## SAML-based authentication options for Azure AD
<a name="JDBC.connection-properties.azure-ad"></a>

The following table describes the available SAML-based authentication options for Azure AD.


| Option | Description | Default | 
| --- | --- | --- | 
|  IdpName  |  The Identity Provider (Idp) name to use for SAML-based authentication. One of `Okta` or `AzureAD` .  |  NONE  | 
|  IdpHost  |  The host name of the specified Idp.  |  NONE  | 
|  IdpUserName  |  The user name for the specified Idp account.  |  NONE  | 
|  IdpPassword  |  The password for the specified Idp account.  |  NONE  | 
|  AADApplicationID  |  The unique id of the registered application on Azure AD.  |  NONE  | 
|  AADClientSecret  |  The client secret associated with the registered application on Azure AD used to authorize fetching tokens.  |  NONE  | 
|  AADTenant  |  The Azure AD Tenant ID.  |  NONE  | 
|  IdpARN  |  The Amazon Resource Name (ARN) of the SAML provider in IAM that describes the Idp.  |  NONE  | 

# JDBC URL examples
<a name="JDBC.url-examples"></a>

 This section describes how to create a JDBC connection URL, and provides examples. To specify the [optional connection properties](JDBC.connection-properties.md), use the following URL format:

```
jdbc:timestream://PropertyName1=value1;PropertyName2=value2... 
```

**Note**  
All connection properties are optional. All property keys are case-sensitive.

Below are some examples of JDBC connection URLs.

*Example with basic authentication options and region:*  

```
jdbc:timestream://AccessKeyId=<myAccessKeyId>;SecretAccessKey=<mySecretAccessKey>;SessionToken=<mySessionToken>;Region=us-east-1
```

*Example with client info, region and SDK options:*  

```
jdbc:timestream://ApplicationName=MyApp;Region=us-east-1;MaxRetryCountClient=10;MaxConnections=5000;RequestTimeout=20000
```

*Connect using the default credential provider chain with AWS credential set in environment variables:*  

```
jdbc:timestream
```

*Connect using the default credential provider chain with AWS credential set in the connection URL:*  

```
jdbc:timestream://AccessKeyId=<myAccessKeyId>;SecretAccessKey=<mySecretAccessKey>;SessionToken=<mySessionToken>
```

*Connect using the PropertiesFileCredentialsProvider as the authentication method:*  

```
jdbc:timestream://AwsCredentialsProviderClass=PropertiesFileCredentialsProvider;CustomCredentialsFilePath=<path to properties file>
```

*Connect using the InstanceProfileCredentialsProvider as the authentication method:*  

```
jdbc:timestream://AwsCredentialsProviderClass=InstanceProfileCredentialsProvider
```

*Connect using the Okta credentials as the authentication method:*  

```
jdbc:timestream://IdpName=Okta;IdpHost=<host>;IdpUserName=<name>;IdpPassword=<password>;OktaApplicationID=<id>;RoleARN=<roleARN>;IdpARN=<IdpARN>
```

*Connect using the Azure AD credentials as the authentication method:*  

```
jdbc:timestream://IdpName=AzureAD;IdpUserName=<name>;IdpPassword=<password>;AADApplicationID=<id>;AADClientSecret=<secret>;AADTenant=<tenantID>;IdpARN=<IdpARN>
```

*Connect with a specific endpoint:*  

```
jdbc:timestream://Endpoint=abc.us-east-1.amazonaws.com;Region=us-east-1
```

# Setting up Timestream for LiveAnalytics JDBC single sign-on authentication with Okta
<a name="JDBC.SSOwithOkta"></a>

 Timestream for LiveAnalytics supports Timestream for LiveAnalytics JDBC single sign-on authentication with Okta. To use Timestream for LiveAnalytics JDBC single sign-on authentication with Okta, complete each of the sections listed below. 

**Topics**
+ [Prerequisites](aws-sso-with-okta-prerequisites.md)
+ [AWS account federation in Okta](aws-account-federation-in-okta.md)
+ [Setting up Okta for SAML](aws-setting-up-okta-for-saml.md)

# Prerequisites
<a name="aws-sso-with-okta-prerequisites"></a>

Ensure that you have met the following prerequisites before using the Timestream for LiveAnalytics JDBC single sign-on authentication with Okta:
+ [Admin permissions in AWS to create the identity provider and the roles](security-iam.md).
+  An Okta account (Go to [https://www.okta.com/login/](https://www.okta.com/login/) to create an account).
+ [Access to Amazon Timestream for LiveAnalytics](accessing.md).

Now that you have completed the Prerequisites, you may proceed to [AWS account federation in Okta](aws-account-federation-in-okta.md).

# AWS account federation in Okta
<a name="aws-account-federation-in-okta"></a>

The Timestream for LiveAnalytics JDBC driver supports AWS Account Federation in Okta. To set up AWS Account Federation in Okta, complete the following steps:

1. Sign in to the Okta Admin dashboard using the following URL:

   ```
   https://<company-domain-name>-admin.okta.com/admin/apps/active 
   ```
**Note**  
 Replace **<company-domain-name>** with your domain name. 

1. Upon successful sign-in, choose** Add Application** and search for **AWS Account Federation**.

1. Choose **Add**

1. Change the Login URL to the appropriate URL.

1. Choose **Next**

1. Choose **SAML 2.0** As the **Sign-On** method

1. Choose **Identity Provider metadata** to open the metadata XML file. Save the file locally.

1. Leave all other configuration options blank.

1. Choose **Done**

Now that you have completed AWS Account Federation in Okta, you may proceed to [Setting up Okta for SAML](aws-setting-up-okta-for-saml.md).

# Setting up Okta for SAML
<a name="aws-setting-up-okta-for-saml"></a>

1. Choose the **Sign On** tab. Choose the **View**.

1. Choose the **Setup Instructions** button in the **Settings** section.

**Finding the Okta metadata document**

1. To find the document, go to:

   ```
   https://<domain>-admin.okta.com/admin/apps/active
   ```
**Note**  
 <domain> is your unique domain name for your Okta account. 

1. Choose the **AWS Account Federation** application

1. Choose the **Sign On** tab

# Setting up Timestream for LiveAnalytics JDBC single sign-on authentication with Microsoft Azure AD
<a name="JDBC.withAzureAD"></a>

 Timestream for LiveAnalytics supports Timestream for LiveAnalytics JDBC single sign-on authentication with Microsoft Azure AD. To use Timestream for LiveAnalytics JDBC single sign-on authentication with Microsoft Azure AD, complete each of the sections listed below. 

**Topics**
+ [Prerequisites](JDBC.withAzureAD.prereqs.md)
+ [Setting up Azure AD](JDBC.withAzureAD.setUp.md)
+ [Setting up IAM Identity Provider and roles in AWS](JDBC.withAzureAD.IAM.md)

# Prerequisites
<a name="JDBC.withAzureAD.prereqs"></a>

Ensure that you have met the following prerequisites before using the Timestream for LiveAnalytics JDBC single sign-on authentication with Microsoft Azure AD:
+ [Admin permissions in AWS to create the identity provider and the roles](security-iam.md).
+ An Azure Active Directory account (Go to [ https://azure.microsoft.com/en-ca/services/active-directory/](https://azure.microsoft.com/en-ca/services/active-directory/) to create an account)
+ [Access to Amazon Timestream for LiveAnalytics](accessing.md).

# Setting up Azure AD
<a name="JDBC.withAzureAD.setUp"></a>

1. Sign in to Azure Portal

1. Choose **Azure Active Directory** in the list of Azure services. This will redirect to the Default Directory page.

1. Choose **Enterprise Applications** under the **Manage** section on the sidebar

1. Choose **\$1 New application**.

1. Find and select **Amazon Web Services**.

1. Choose **Single Sign-On** under the **Manage** section in the sidebar

1. Choose **SAML** as the single sign-on method

1. In the Basic SAML Configuration section, enter the following URL for both the Identifier and the Reply URL:

   ```
   https://signin.aws.amazon.com/saml
   ```

1. Choose **Save**

1. Download the Federation Metadata XML in the SAML Signing Certificate section. This will be used when creating the IAM Identity Provider later

1. Return to the Default Directory page and choose **App registrations** under **Manage**.

1. Choose **Timestream for LiveAnalytics** from the **All Applications** section. The page will be redirected to the application's Overview page
**Note**  
Note the Application (client) ID and the Directory (tenant) ID. These values are required for when creating a connection.

1. Choose **Certificates and Secrets**

1. Under **Client secrets**, create a new client secret with **\$1 New client secret**.
**Note**  
Note the generated client secret, as this is required when creating a connection to Timestream for LiveAnalytics.

1. On the sidebar under **Manage**, select **API permissions**

1. In the **Configured permissions**, use **Add a permission** to grant Azure AD permission to sign in to Timestream for LiveAnalytics. Choose **Microsoft Graph** on the Request API permissions page.

1. Choose **Delegated permissions** and select the **User.Read **permission

1. Choose **Add permissions**

1. Choose **Grant admin consent for Default Directory**

# Setting up IAM Identity Provider and roles in AWS
<a name="JDBC.withAzureAD.IAM"></a>

 Complete each section below to set up IAM for Timestream for LiveAnalytics JDBC single sign-on authentication with Microsoft Azure AD: 

**Topics**
+ [Create a SAML Identity Provider](#JDBC.withAzureAD.IAM.SAML)
+ [Create an IAM role](#JDBC.withAzureAD.IAM.roleForIAM)
+ [Create an IAM policy](#JDBC.withAzureAD.IAM.policyForIAM)
+ [Provisioning](#JDBC.withAzureAD.IAM.provisioning)

## Create a SAML Identity Provider
<a name="JDBC.withAzureAD.IAM.SAML"></a>

To create a SAML Identity Provider for the Timestream for LiveAnalytics JDBC single sign-on authentication with Microsoft Azure AD, complete the following steps:

1. Sign in to the AWS Management Console

1. Choose **Services** and select **IAM** under Security, Identity, & Compliance

1. Choose **Identity providers** under Access management

1. Choose **Create Provider** and choose **SAML** as the provider type. Enter the **Provider Name**. This example will use AzureADProvider.

1. Upload the previously downloaded Federation Metadata XML file

1. Choose **Next**, then choose **Create**.

1. Upon completion, the page will be redirected back to the Identity providers page

## Create an IAM role
<a name="JDBC.withAzureAD.IAM.roleForIAM"></a>

To create an IAM role for the Timestream for LiveAnalytics JDBC single sign-on authentication with Microsoft Azure AD, complete the following steps:

1. On the sidebar select **Roles** under Access management

1. Choose Create role

1. Choose **SAML 2.0 federation** as the trusted entity

1. Choose the **Azure AD provider**

1. Choose **Allow programmatic and AWS Management Console access**

1. Choose **Next: Permissions**

1. Attach permissions policies or continue to Next:Tags

1. Add optional tags or continue to Next:Review

1. Enter a Role name. This example will use AzureSAMLRole

1. Provide a role description

1. Choose **Create Role** to complete

## Create an IAM policy
<a name="JDBC.withAzureAD.IAM.policyForIAM"></a>

To create an IAM policy for the Timestream for LiveAnalytics JDBC single sign-on authentication with Microsoft Azure AD complete the following steps:

1. On the sidebar, choose **Policies** under Access management

1. Choose **Create policy** and select the **JSON** tab

1. Add the following policy

------
#### [ JSON ]

****  

   ```
   {
   "Version":"2012-10-17",		 	 	 
   "Statement": [
       {
             "Effect": "Allow",
             "Action": [
                    "iam:ListRoles",
                    "iam:ListAccountAliases"
              ],
              "Resource": "*"
         }
   ]
   }
   ```

------

1. Choose **Create policy**

1. Enter a policy name. This example will use TimestreamAccessPolicy.

1. Choose **Create Policy**

1. On the sidebar, choose **Roles** under Access management. 

1.  Choose the previously created **Azure AD role** and choose **Attach policies** under Permissions.

1. Select the previously created access policy.

## Provisioning
<a name="JDBC.withAzureAD.IAM.provisioning"></a>

To provision the identity provider for Timestream for LiveAnalytics JDBC single sign-on authentication with Microsoft Azure AD, complete the following steps:

1. Go back to Azure Portal

1. Choose **Azure Active Directory** in the list of Azure services. This will redirect to the Default Directory page

1. Choose **Enterprise Applications** under the Manage section on the sidebar

1. Choose **Provisioning**

1. Choose **Automatic mode** for the Provisioning Method

1. Under Admin Credentials, enter your **AwsAccessKeyID** for clientsecret, and **SecretAccessKey** for Secret Token

1. Set the **Provisioning Status** to **On**

1. Choose **save**. This allows Azure AD to load the necessary IAM Roles

1. Once the Current cycle status is completed, choose **Users and groups** on the sidebar

1. Choose **\$1 Add user**

1. Choose the Azure AD user to provide access to Timestream for LiveAnalytics

1. Choose the IAM Azure AD role and the corresponding Azure Identity Provider created in AWS

1. Choose **Assign**

# ODBC
<a name="ODBC"></a>

The open-source [ODBC driver](https://github.com/awslabs/amazon-timestream-odbc-driver/tree/main) for Amazon Timestream for LiveAnalytics provides an SQL-relational interface to Timestream for LiveAnalytics for developers and enables connectivity from business intelligence (BI) tools such as Power BI Desktop and Microsoft Excel. The Timestream for LiveAnalytics ODBC driver is currently available on [Windows, macOS and Linux](https://github.com/awslabs/amazon-timestream-odbc-driver/releases), and also supports SSO with Okta and Microsoft Azure Active Directory (AD).

For more information, see [Amazon Timestream for LiveAnalytics ODBC driver documentation on GitHub](https://github.com/awslabs/amazon-timestream-odbc-driver/blob/main/docs/markdown/index.md).

**Topics**
+ [Setting up the Timestream for LiveAnalytics ODBC driver](ODBC-setup.md)
+ [Connection string syntax and options for the ODBC driver](ODBC-connecting.md)
+ [Connection string examples for the Timestream for LiveAnalytics ODBC driver](ODBC-connecting-examples.md)
+ [Troubleshooting connection with the ODBC driver](ODBC-connecting-troubleshooting.md)

# Setting up the Timestream for LiveAnalytics ODBC driver
<a name="ODBC-setup"></a>

## Set up access to Timestream for LiveAnalytics in your AWS account
<a name="ODBC-setup-access"></a>

If you haven't already set up your AWS account to work with Timestream for LiveAnalytics, follow the insructions in [Accessing Timestream for LiveAnalytics](accessing.md).

## Install the ODBC driver on your system
<a name="ODBC-setup-download"></a>

Download the appropriate Timestream ODBC driver installer for your system from the [ODBC GitHub repository](https://github.com/awslabs/amazon-timestream-odbc-driver/releases), and follow the installation instructions that apply to your system:.
+ [Windows installation guide](https://github.com/awslabs/amazon-timestream-odbc-driver/blob/main/docs/markdown/setup/windows-installation-guide.md)
+ [MacOS installation guide](https://github.com/awslabs/amazon-timestream-odbc-driver/blob/main/docs/markdown/setup/macOS-installation-guide.md)
+ [Linux installation guide](https://github.com/awslabs/amazon-timestream-odbc-driver/blob/main/docs/markdown/setup/linux-installation-guide.md)

## Set up a data source name (DSN) for the ODBC driver
<a name="ODBC-setup-dsn"></a>

Follow the instructions in the DSN configuration guide for your system:
+ [Windows DSN configuration](https://github.com/awslabs/amazon-timestream-odbc-driver/blob/main/docs/markdown/setup/windows-dsn-configuration.md)
+ [MacOS DSN configuration](https://github.com/awslabs/amazon-timestream-odbc-driver/blob/main/docs/markdown/setup/macOS-dsn-configuration.md)
+ [Linux DSN configuration](https://github.com/awslabs/amazon-timestream-odbc-driver/blob/main/docs/markdown/setup/linux-dsn-configuration.md)

## Set up your business intelligence (BI) application to work with the ODBC driver
<a name="ODBC-setup-bi-apps"></a>

Here are instructions for setting several common BI applications to work with the ODBC driver:
+ [Setting up Microsoft Power BI.](https://github.com/awslabs/amazon-timestream-odbc-driver/blob/main/docs/markdown/setup/microsoft-power-bi.md)
+ [Setting up Microsoft Excel](https://github.com/awslabs/amazon-timestream-odbc-driver/blob/main/docs/markdown/setup/microsoft-excel.md)
+ [Setting up Tableau](https://github.com/awslabs/amazon-timestream-odbc-driver/blob/main/docs/markdown/setup/tableau.md)

For other applications

# Connection string syntax and options for the ODBC driver
<a name="ODBC-connecting"></a>

The syntax for specifying connection-string options for the ODBC driver is as follows:

```
DRIVER={Amazon Timestream ODBC Driver};(option)=(value);
```

Available options are as follows:

**Driver connection options**
+ **`Driver`**   *(required)*   –   The driver being used with ODBC.

  The default is Amazon Timestream.
+ **`DSN`**   –   The data source name (DSN) to use for configuring the connection.

  The default is `NONE`.
+ **`Auth`**   –   The authentication mode. This must be one of the following:
  + `AWS_PROFILE` – Use the default credential chain.
  + `IAM` – Use AWS IAM credentials.
  + `AAD` – Use the Azure Active Directory (AD) identity provider.
  + `OKTA` – Use the Okta identity provider.

  The default is `AWS_PROFILE`.

**Endpoint configuration options**
+ **`EndpointOverride`**   –   The endpoint override for the Timestream for LiveAnalytics service. This is an advanced option that overrides the region. For example:

  ```
  query-cell2.timestream.us-east-1.amazonaws.com
  ```
+ **`Region`**   –   The signing region for the Timestream for LiveAnalytics service endpoint.

  The default is `us-east-1`.

**Credentials provider option**
+ **`ProfileName`**   –   The profile name in the AWS config file.

  The default is `NONE`.

**AWS IAM authentication options**
+ **`UID`** or **`AccessKeyId`**   –   The AWS user access key id. If both `UID` and `AccessKeyId` are provided in the connection string, the `UID` value will be used unless it is empty.

  The default is `NONE`.
+ **`PWD`** or **`SecretKey`**   –   The AWS user secret access key. If both `PWD` and `SecretKey` are provided in the connection string, the `PWD` value with will be used unless it's empty.

  The default is `NONE`.
+ **`SessionToken`**   –   The temporary session token required to access a database with multi-factor authentication (MFA) enabled. Do not include a trailing ` = ` in the input.

  The default is `NONE`.

**SAML-based authentication options for Okta**
+ **`IdPHost`**   –   The hostname of the specified IdP.

  The default is `NONE`.
+ **`UID`** or **`IdPUserName`**   –   The user name for the specified IdP account. If both `UID` and `IdPUserName` are provided in the connection string, the `UID` value will be used unless it's empty.

  The default is `NONE`.
+ **`PWD`** or **`IdPPassword`**   –   The password for the specified IdP account. If both `PWD` and `IdPPassword` are provided in the connection string, the `PWD` value will be used unless it's empty.

  The default is `NONE`.
+ **`OktaApplicationID`**   –   The unique Okta-provided ID associated with the Timestream for LiveAnalytics application. A place to find the application ID (AppId) is in the `entityID` field provided in the application metadata. An example is:

  ```
  entityID="http://www.okta.com//(IdPAppID)
  ```

  The default is `NONE`.
+ **`RoleARN`**   –   The Amazon Resource Name (ARN) of the role that the caller is assuming.

  The default is `NONE`.
+ **`IdPARN`**   –   The Amazon Resource Name (ARN) of the SAML provider in IAM that describes the IdP.

  The default is `NONE`.

**SAML-based authentication options for Azure Active Directory**
+ **`UID`** or **`IdPUserName`**   –   The user name for the specified IdP account..

  The default is `NONE`.
+ **`PWD`** or **`IdPPassword`**   –   The password for the specified IdP account.

  The default is `NONE`.
+ **`AADApplicationID`**   –   The unique id of the registered application on Azure AD.

  The default is `NONE`.
+ **`AADClientSecret`**   –   The client secret associated with the registered application on Azure AD used to authorize fetching tokens.

  The default is `NONE`.
+ **`AADTenant`**   –   The Azure AD Tenant ID.

  The default is `NONE`.
+ **`RoleARN`**   –   The Amazon Resource Name (ARN) of the role that the caller is assuming.

  The default is `NONE`.
+ **`IdPARN`**   –   The Amazon Resource Name (ARN) of the SAML provider in IAM that describes the IdP.

  The default is `NONE`.

**AWS SDK (advanced) Options**
+ **`RequestTimeout`**   –   The time in milliseconds that the AWS SDK waits for a query request before timing out. Any non-positive value disables the request timeout.

  The default is `3000`.
+ **`ConnectionTimeout`**   –   The time in milliseconds that the AWS SDK waits for data to be transferred over an open connection before timing out. A value of 0 disables the connection timeout. This value must not be negative.

  The default is `1000`.
+ **`MaxRetryCountClient`**   –   The maximum number of retry attempts for retryable errors with 5xx error codes in the SDK. The value must not be negative.

  The default is `0`.
+ **`MaxConnections`**   –   The maximum number of allowed concurrently open HTTP connections to the Timestream service. The value must be positive.

  The default is `25`.

**ODBC driver logging Options**
+ **`LogLevel`**   –   The log level for driver logging. Must be one of:
  + **0**   (OFF).
  + **1**   (ERROR).
  + **2**   (WARNING).
  + **3**   (INFO).
  + **4**   (DEBUG).

  The default is `1` (ERROR).

  **Warning:** personal information could be logged by the driver when using the DEBUG logging mode.
+ **`LogOutput`**   –   Folder in which to store the log file.

  The default is:
  + **Windows:** `%USERPROFILE%`, or if not available, `%HOMEDRIVE%%HOMEPATH%`.
  + **macOS and Linux:** `$HOME`, or if not available, the field `pw_dir` from the function `getpwuid(getuid())` return value.

**SDK logging options**

The AWS SDK log level is separate from the Timestream for LiveAnalytics ODBC driver log level. Setting one does not affect the other.

The SDK Log Level is set using the environment variable `TS_AWS_LOG_LEVEL`. Valid values are:
+ `OFF`
+ `ERROR`
+ `WARN`
+ `INFO`
+ `DEBUG`
+ `TRACE`
+ `FATAL`

If `TS_AWS_LOG_LEVEL` is not set, the SDK log level is set to the default, which is `WARN`.

## Connecting through a proxy
<a name="ODBC-connecting-proxy"></a>

The ODBC driver supports connecting to Amazon Timestream for LiveAnalytics through a proxy. To use this feature, configure the following environment variables based on your proxy setting:
+ **`TS_PROXY_HOST`**   –   the proxy host.
+ **`TS_PROXY_PORT`**   –   The proxy port number.
+ **`TS_PROXY_SCHEME`**   –   The proxy scheme, either `http` or `https`.
+ **`TS_PROXY_USER`**   –   The user name for proxy authentication.
+ **`TS_PROXY_PASSWORD`**   –   The user password for proxy authentication.
+ **`TS_PROXY_SSL_CERT_PATH`**   –   The SSL Certificate file to use for connecting to an HTTPS proxy.
+ **`TS_PROXY_SSL_CERT_TYPE`**   –   The type of the proxy client SSL certificate.
+ **`TS_PROXY_SSL_KEY_PATH`**   –   The private key file to use for connecting to an HTTPS proxy.
+ **`TS_PROXY_SSL_KEY_TYPE`**   –   The type of the private key file used to connect to an HTTPS proxy.
+ **`TS_PROXY_SSL_KEY_PASSWORD`**   –   The passphrase to the private key file used to connect to an HTTPS proxy.

# Connection string examples for the Timestream for LiveAnalytics ODBC driver
<a name="ODBC-connecting-examples"></a>

## Example of connecting to the ODBC driver with IAM credentials
<a name="ODBC-connecting-examples-iam"></a>

```
Driver={Amazon Timestream ODBC Driver};Auth=IAM;AccessKeyId=(your access key ID);secretKey=(your secret key);SessionToken=(your session token);Region=us-east-2;
```

## Example of connecting to the ODBC driver with a profile
<a name="ODBC-connecting-examples-profile"></a>

```
Driver={Amazon Timestream ODBC Driver};ProfileName=(the profile name);region=us-west-2;
```

The driver will attempt to connect using the credentials provided in `~/.aws/credentials`, or if a file is specified in the environment variable `AWS_SHARED_CREDENTIALS_FILE`, using the credentials in that file.

## Example of connecting to the ODBC driver with Okta
<a name="ODBC-connecting-examples-okta"></a>

```
driver={Amazon Timestream ODBC Driver};auth=okta;region=us-west-2;idPHost=(your host at Okta);idPUsername=(your user name);idPPassword=(your password);OktaApplicationID=(your Okta AppId);roleARN=(your role ARN);idPARN=(your Idp ARN);
```

## Example of connecting to the ODBC driver with Azure Active Directory (AAD)
<a name="ODBC-connecting-examples-aad"></a>

```
driver={Amazon Timestream ODBC Driver};auth=aad;region=us-west-2;idPUsername=(your user name);idPPassword=(your password);aadApplicationID=(your AAD AppId);aadClientSecret=(your AAD client secret);aadTenant=(your AAD tenant);roleARN=(your role ARN);idPARN=(your idP ARN);
```

## Example of connecting to the ODBC driver with a specified endpoint and a log level of 2 (WARNING)
<a name="ODBC-connecting-examples-okta"></a>

```
Driver={Amazon Timestream ODBC Driver};Auth=IAM;AccessKeyId=(your access key ID);secretKey=(your secret key);EndpointOverride=ingest.timestream.us-west-2.amazonaws.com;Region=us-east-2;LogLevel=2;
```

# Troubleshooting connection with the ODBC driver
<a name="ODBC-connecting-troubleshooting"></a>

**Note**  
When the username and password are already specified in the DSN, there is no need to specify them again when the ODBC driver manager asks for them.

An error code of `01S02` with a message, `Re-writing (connection string option) (have you specified it several times?` occurs when a connection string option is passed more than once in the connection string. Specifying an option more than once raises an error. When making a connection with a DSN and a connection string, if a connection option is already specified in the DSN, do not specify it again in the connection string.

# VPC endpoints (AWS PrivateLink)
<a name="vpc-interface-endpoints"></a>

You can establish a private connection between your VPC and Amazon Timestream for LiveAnalytics by creating an *interface VPC endpoint*. For more information, see [VPC endpoints (AWS PrivateLink)](VPCEndpoints.md). 

# Best practices
<a name="best-practices"></a>

 To fully realize the benefits of the Amazon Timestream for LiveAnalytics, follow the best practices described below.

**Note**  
When running proof-of-concept applications, consider the amount of data your application will accumulate over a few months or years while evaluating the performance and scale of Timestream for LiveAnalytics. As your data grows over time, you'll notice that the performance of Timestream for LiveAnalytics remains mostly unchanged because its serverless architecture can leverage massive amounts of parallelism for processing larger data volumes and automatically scale to match needs of your application.

**Topics**
+ [Data modeling](data-modeling.md)
+ [Security](security-bp.md)
+ [Configuring Amazon Timestream for LiveAnalytics](configuration.md)
+ [Writes](data-ingest.md)
+ [Queries](queries-bp.md)
+ [Scheduled queries](scheduledqueries-bp.md)
+ [Client applications and supported integrations](client-integrations.md)
+ [General](general.md)

# Data modeling
<a name="data-modeling"></a>

Amazon Timestream for LiveAnalytics is designed to collect, store, and analyze time series data from applications and devices emitting a sequence of data with a timestamp. For optimal performance, the data being sent to Timestream for LiveAnalytics must have temporal characteristics and time must be a quintessential component of the data.

Timestream for LiveAnalytics provides you the flexibility to model your data in different ways to suit your application's requirements. In this section, we cover several of these patterns and provide guidelines for you to optimize your costs and performance. Familiarize yourself with key [Amazon Timestream for LiveAnalytics concepts](concepts.md) such as dimensions and measures. In this section, you will learn more about the following when deciding whether to create a single table or multiple tables to store data:
+ Which data to put in the same table vs. when you want to separate data across multiple tables and databases.
+ How to choose between Timestream for LiveAnalytics multi-measure records compared to single-measure records, and the benefits of modeling using multi-measure records especially when your application is tracking multiple measurements at the same time instant.
+ Which attributes to model as dimensions or as measures.
+ How to effectively use the measure name attributes to optimize your query latency.

**Topics**
+ [Single table vs. multiple tables](#data-modeling-singleVmultitable)
+ [Multi-measure records vs. single-measure records](#data-modeling-multiVsinglerecords)
+ [Dimensions and measures](#data-modeling-dimensionsmeasures)
+ [Using measure name with multi-measure records](#data-modeling-measurenamemulti)
+ [Recommendations for partitioning multi-measure records](#data-modeling-multi-measure-partitioning)

## Single table vs. multiple tables
<a name="data-modeling-singleVmultitable"></a>

As you are modeling your data in application, another important aspect is how to model the data into tables and databases. Databases and tables in Timestream for LiveAnalytics are abstractions for access control, specifying KMS keys, retention periods, and so on. Timestream for LiveAnalytics automatically partitions your data and is designed to scale resources to match the ingestion, storage, and query load and requirements for your applications.

A table in Timestream for LiveAnalytics can scale to petabytes of data stored and tens of gigabytes per second of data writes. Queries can process hundreds of terabytes per hour. Queries in Timestream for LiveAnalytics can span multiple tables and databases, providing joins and unions to provide seamless access to your data across multiple tables and databases. So scale of data or request volumes are usually not the primary concern when deciding how to organize your data in Timestream for LiveAnalytics. Below are some important considerations when deciding which data to co-locate in the same table compared to in different tables, or tables in different databases.
+ Data retention policies (memory store retention, magnetic store retention, etc.) are supported at the granularity of a table. Therefore, data that requires different retention policies needs to be in different tables.
+ AWS KMS keys that are used to encrypt your data are configured at the database level. Therefore, different encryption key requirements imply the data will need to be in different databases.
+ Timestream for LiveAnalytics supports resource-based access control at the granularity of tables and databases. Consider your access control requirements when deciding which data you write to the same table vs. different tables.
+ Be aware of the [limits](https://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html) on the number of dimensions, measure names, and multi-measure attribute names when deciding which data is stored in which table.
+ Consider your query workload and access patterns when deciding how you organize your data, as the query latency and ease of writing your queries will be dependent on that.
  + If you store data that you frequently query in the same table, that will generally ease the way you write your queries so that you can often avoid having to write joins, unions, or common table expressions. This also usually results in lower query latency. You can use predicates on dimensions and measure names to filter the data that is relevant to the queries.

    For instance, consider a case where you store data from devices located in six continents. If your queries frequently access data from across continents to get a global aggregated view, then storing data from these continents in the same table will result in easier to write queries. On the other hand, if you store data on different tables, you still can combine the data in the same query, however, you will need to write a query to union the data from across tables.
  + Timestream for LiveAnalytics uses adaptive partitioning and indexing on your data so queries only get charged for data that is relevant to your queries. For instance, if you have a table storing data from a million devices across six continents, if your query has predicates of the form `WHERE device_id = 'abcdef'` or `WHERE continent = 'North America'`, then queries are only charged for data for the device or for the continent.
  + Wherever possible, if you use measure name to separate out data in the same table that is not emitted at the same time or not frequently queried, then using predicates such as `WHERE measure_name = 'cpu'` in your query, not only do you get the metering benefits, Timestream for LiveAnalytics can also effectively eliminate partitions that do not have the measure name used in your query predicate. This enables you to store related data with different measure names in the same table without impacting query latency or costs, and avoids spreading the data into multiple tables. The measure name is essentially used to partition the data and prune partitions irrelevant to the query.

## Multi-measure records vs. single-measure records
<a name="data-modeling-multiVsinglerecords"></a>

Timestream for LiveAnalytics allows you to write data with multiple measures per record (multi-measure) or single measure per record (single-measure).

**Multi-measure records**

In many use cases, a device or an application you are tracking may emit multiple metrics or events at the same timestamp. In such cases, you can store all the metrics emitted at the same timestamp in the same multi-measure record. That is, all the measures stored in the same multi-measure record appear as different columns in the same row of data.

Consider, for instance, that your application is emitting metrics such as cpu, memory, and disk\$1iops from a device measured at the same time instant. The following is an example of such a table where multiple metrics emitted at the same time instant are stored in the same row. You will that see two hosts are emitting the metrics once every second.


| Hostname | measure\$1name | Time | cpu | Memory | disk\$1iops | 
| --- | --- | --- | --- | --- | --- | 
| host-24Gju | metrics | 2021-12-01 19:00:00 | 35 | 54.9 | 38.2 | 
| host-24Gju | metrics | 2021-12-01 19:00:01 | 36 | 58 | 39 | 
| host-28Gju | metrics | 2021-12-01 19:00:00 | 15 | 55 | 92 | 
| host-28Gju | metrics | 2021-12-01 19:00:01 | 16 | 50 | 40 | 

**Single-measure records**

The single-measure records are suitable when your devices emit different metrics at different time periods, or you are using custom processing logic that emits metrics/events at different time periods (for instance, when a device's reading/state changes). Because every measure has a unique timestamp, the measures can be stored in their own records in Timestream for LiveAnalytics. For instance, consider an IoT sensor, which tracks soil temperature and moisture, that emits a record only when it detects a change from the previous reported entry. The following example provides an example of such data being emitted using single measure records.


| device\$1id | measure\$1name | Time | measure\$1value::double | measure\$1value::bigint | 
| --- | --- | --- | --- | --- | 
| sensor-sea478 | temperature |  2021-12-01 19:22:32 | 35 | NULL | 
| sensor-sea478 | temperature |  2021-12-01 18:07:51 | 36 | NULL | 
| sensor-sea478 | moisture |  2021-12-01 19:05:30 | NULL | 21 | 
| sensor-sea478 | moisture |  2021-12-01 19:00:01 | NULL | 23 | 

**Comparing single-measure and multi-measure records**

Timestream for LiveAnalytics provides you the flexibility to model your data as single-measure or multi-measure records depending on your application's requirements and characteristics. A single table can store both single-measure and multi-measure records if your application requirements so desire. In general, when your application is emitting multiple measures/events at the same time instant, then modeling the data as multi-measure records is usually recommended for performant data access and cost-effective data storage.

For instance, if you consider a [DevOps use case tracking metrics and events](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/tools/python/perf-scale-workload) from hundreds of thousands of servers, each server periodically emits 20 metrics and 5 events, where the events and metrics are emitted at the same time instant. That data can be modeled either using single-measure records or using multi-measure records (see the [open-sourced data generator](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/tools/python/perf-scale-workload) for the resulting schema). For this use case, modeling the data using multi-measure records compared to single-measure records results in:
+ *Ingestion metering* - Multi-measure records results in about *40 percent lower ingestion* bytes written. 
+ *Ingestion batching* - Multi-measure records result in bigger batches of data being sent, which implies the clients need fewer threads and fewer CPU to process the ingestion.
+ *Storage metering* - Multi-measure records result in about *8X lower storage*, resulting in significant storage savings for both memory and magnetic store.
+ *Query latency* - Multi-measure records results in lower query latency for most query types when compared to single-measure records.
+ *Query metered bytes* - For queries scanning less than 10 MB data, both single-measure and multi-measure records are comparable. For queries accessing a single measure and scanning > 10 MB data, single measure records usually results in lower bytes metered. For queries referencing three or more measures, multi-measure records result in lower bytes metered.
+ *Ease of expressing multi-measure queries* - When your queries reference multiple measures, modeling your data with multi-measure records results in easier to write and more compact queries. 

The previous factors will vary depending on how many metrics you are tracking, how many dimensions your data has, etc. While the preceding example provides some concrete data for one example, we see across many application scenarios and use cases where if your application emits multiple measures at the same instant, storing data as multi-measure records is more effective. Moreover, multi-measure records provide you the flexibility of data types and storing multiple other values as context (for example, storing request IDs, and additional timestamps, which is discussed later).

Note that a multi-measure record can also model sparse measures such as the previous example for single-measure records: you can use the `measure_name` to store the name of the measure and use a generic multi-measure attribute name, such as `value_double` to store `DOUBLE` measures, `value_bigint` to store `BIGINT` measures, `value_timestamp` to store additional `TIMESTAMP` values, and so on.

## Dimensions and measures
<a name="data-modeling-dimensionsmeasures"></a>

A table in Timestream for LiveAnalytics allows you to store *dimensions* (identifying attributes of the device/data you are storing) and *measures* (the metrics/values you are tracking); see [Amazon Timestream for LiveAnalytics concepts](concepts.md) for more details. As you are modeling your application on Timestream for LiveAnalytics, how you map your data into dimensions and measures impacts your ingestion and query latency. The following are guidelines on how to model your data as dimensions and measures that you can apply to your use case.

**Choosing dimensions**

Data that identifies the source that is sending the time series data is a natural fit for dimensions, which are attributes that don't change over time. For instance, if you have a server emitting metrics, then the attributes identifying the server, such as hostname, Region, rack, and Availability Zone, are candidates for dimensions. Similarly, for an IoT device with multiple sensors reporting time series data, attributes such as device ID and sensor ID are candidates for dimensions.

If you are writing data as multi-measure records, dimensions and multi-measure attributes appear as columns in the table when you do a `DESCRIBE` or run a `SELECT` statement on the table. Therefore, when writing your queries, you can freely use the dimensions and measures in the same query. However, as you construct your write record to ingest data, keep the following in mind as you choose which attributes are specified as dimensions and which ones are measure values:
+ The dimension names, dimension values, measure name, and timestamp uniquely identify the time series data. Timestream for LiveAnalytics uses this unique identifier to automatically de-duplicate data. That is, if Timestream for LiveAnalytics receives two data points with the same values of dimension names, dimension values, measure name, and timestamp, and the values have the same version number, then Timestream for LiveAnalytics de-duplicates. If the new write request has a lower version than the data already existing in Timestream for LiveAnalytics, the write request is rejected. If the new write request has a higher version, then the new value overwrites the old value. Therefore, how you choose your dimension values will impact this de-duplication behavior.
+ Dimension names and values cannot be updated, but measure value can be. Therefore, any data that might need updates is better modeled as measure values. For instance, if you have a machine on the factory floor whose color can change, you can model the color as a measure value, unless you also want to use the color as an identifying attribute that is needed for de-duplication. That is, measure values can be used to store attributes that only slowly change over time.

Note that a table in Timestream for LiveAnalytics does not limit the number of unique combinations of dimension names and values. For instance, you can have billions of such unique value combinations stored in a table. However, as you will see with the following examples, careful choice of dimensions and measures can significantly optimize your request latency, especially for queries.

**Unique IDs in dimensions**

If your application scenario requires you to store a unique identifier for every data point (for example, a request ID, a transaction ID, or a correlation ID), modeling the ID attribute as a measure value will result in significantly better query latency. When modeling your data with multi-measure records, the ID appears in the same row in context with your other dimensions and time series data, so your queries can continue to use them effectively. For instance, considering a [DevOps use case](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/tools/python/perf-scale-workload) where every data point emitted by a server has a unique request ID attribute, modeling the request ID as a measure value results in up to 4x lower query latency across different query types, as opposed to modeling the unique request ID as a dimension.

You can use the similar analogy for attributes that are not entirely unique for every data point, but have hundreds of thousands or millions of unique values. You can model those attributes both as dimensions or measure values. You would want to model it as a dimension if the values are necessary for de-duplication on the write path as discussed earlier or you often use it as a predicate (for example, in the `WHERE` clause with an equality predicate on a value of that attribute such as `device_id = 'abcde'` where your application is tracking millions of devices) in your queries. 

**Richness of data types with multi-measure records**

Multi-measure records provide you the flexibility to effectively model your data. Data that you store in a multi-measure record appear as columns in the table similar to dimensions, thus providing the same ease of querying for dimension and measure values. You saw some of these patterns in the examples discussed earlier. Below you will find additional patterns to effectively use multi-measure records to meet your application's use cases.

Multi-measure records support attributes of data types `DOUBLE`, `BIGINT`, `VARCHAR`, `BOOLEAN`, and `TIMESTAMP`. Therefore, they naturally fit different types of attributes:
+ *Location information*: For instance, if you want to track a location (expressed as latitude and longitude), then modeling it as a multi-measure attribute will result in lower query latency compared to storing them as `VARCHAR` dimensions, especially when you have predicates on the latitudes and longitudes. 
+ *Multiple timestamps in a record*: If your application scenario requires you to track multiple timestamps for a time series record, you can model them as additional attributes in the multi-measure record. This pattern can be used to store data with future timestamps or past timestamps. Note that every record will still use the timestamp in the time column to partition, index, and uniquely identify a record.

In particular, if you have numeric data or timestamps on which you have predicates in the query, modeling those attributes as multi-measure attributes as opposed to dimensions will result in lower query latency. This is because when you model such data using the rich data types supported in multi-measure records, you can express the predicates using native data types instead of casting values from `VARCHAR` to another data type if you modeled such data as dimensions.

## Using measure name with multi-measure records
<a name="data-modeling-measurenamemulti"></a>

Tables in Timestream for LiveAnalytics support a special attribute (or column) called *measure name*. You specify a value for this attribute for every record you write to Timestream for LiveAnalytics. For single-measure records, it is natural to use the name of your metric (such as CPU or memory for server metrics, or temperature or pressure for sensor metrics). When using multi-measure records, attributes in a multi-measure record are named and these names become column names in the table. Therefore, cpu, memory, temperature, and pressure can become multi-measure attribute names. A natural question is how to effectively use the measure name.

Timestream for LiveAnalytics uses the values in the measure name attribute to partition and index the data. Therefore, if a table has multiple different measure names, and if the queries use those values as query predicates, then Timestream for LiveAnalytics can use its custom partitioning and indexing to prune out data that is not relevant to queries. For instance, if your table has `cpu` and `memory` measure names, and your query has a predicate `WHERE measure_name = 'cpu'`, Timestream for LiveAnalytics can effectively prune data for measure names not relevant to the query, for example, rows with measure name memory in this example. This pruning applies even when using measure names with multi-measure records. You can use the measure name attribute effectively as a partitioning attribute for a table. Measure name along with dimension names and values, and time are used to partition the data in a Timestream for LiveAnalytics table. Be aware of the [limits](https://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html) on the number of unique measure names allowed in a Timestream for LiveAnalytics table. Also note that a measure name is associated with a measure value data type as well. For example, a single measure name can only be associated with one type of measure value. That type can be one of `DOUBLE`, `BIGINT`, `BOOLEAN`, `VARCHAR`, or `MULTI`. Multi-measure records stored with a measure name will have the data type of `MULTI`. Since a single multi-measure record can store multiple metrics with different data types (`DOUBLE`, `BIGINT`, `VARCHAR`, `BOOLEAN`, and `TIMESTAMP`), you can associate data of different types in a multi-measure record. 

The following sections describe a few different examples of how the measure name attribute can be effectively used to group together different types of data in the same table. 

**IoT sensors reporting quality and value**

Consider you have an application monitoring data from IoT sensors. Each sensor tracks different measures, such as temperature and pressure. In addition to the actual values, the sensors also report the quality of the measurements, which is a measure of how accurate the reading is, and a unit for the measurement. Since quality, unit, and value are emitted together, they can be modeled as multi-measure records, as shown in the example data below where `device_id` is a dimension, and `quality`, `value`, and `unit` are multi-measure attributes:


| device\$1id | measure\$1name | Time | Quality | Value | Unit | 
| --- | --- | --- | --- | --- | --- | 
| sensor-sea478 | temperature | 2021-12-01 19:22:32 | 92 | 35 | c | 
| sensor-sea478 | temperature | 2021-12-01 18:07:51 | 93 | 34 | c | 
| sensor-sea478 | pressure | 2021-12-01 19:05:30 | 98 | 31 | psi | 
| sensor-sea478 | pressure | 2021-12-01 19:00:01 | 24 | 132 | psi | 

This approach allows you to combine the benefits of multi-measure records along with partitioning and pruning data using the values of measure name. If queries reference a single measure, such as temperature, then you can include a `measure_name` predicate in the query. The following is an example of such a query, which also projects the unit for measurements whose quality is above 90.

```
SELECT device_id, time, value AS temperature, unit
FROM db.table
WHERE time > ago(1h)
    AND measure_name = 'temperature'
    AND quality > 90
```

Using the `measure_name` predicate on the query enables Timestream for LiveAnalytics to effectively prune partitions and data that is not relevant to the query, thus improving your query latency.

It is also possible to have all of the metrics stored in the same multi-measure record if all the metrics are emitted at the same timestamp and/or multiple metrics are queried together in the same query. For instance, you can construct a multi-measure record with attributes such as temperature\$1quality, temperature\$1value, temperature\$1unit, pressure\$1quality, pressure\$1value, and pressure\$1unit. Many of the points discussed earlier about modeling data using single-measure vs. multi-measure records apply in your decision of how to model the data. Consider your query access patterns and how your data is generated to choose a model that optimizes your cost, ingestion and query latency, and ease of writing your queries.

**Different types of metrics in the same table**

Another use case where you can combine multi-measure records with measure name values is to model different types of data that are independently emitted from the same device. Consider the DevOps monitoring use case where servers are emitting two types of data: regularly emitted metrics and irregular events. An example of this approach is the schema discussed in the [data generator modeling a DevOps use case](https://github.com/awslabs/amazon-timestream-tools/tree/mainline/tools/python/perf-scale-workload). In this case, you can store the different types of data emitted from the same server in the same table by using different measure names. For instance, all the metrics that are emitted at the same time instant are stored with measure name metrics. All the events that are emitted at a different time instant from the metrics are stored with measure name events. The measure schema for the table (for example, output of `SHOW MEASURES` query) is:


| measure\$1name | data\$1type | Dimensions | 
| --- | --- | --- | 
| events | multi | [\$1"data\$1type":"varchar","dimension\$1name":"availability\$1zone"\$1,\$1"data\$1type":"varchar","dimension\$1name":"microservice\$1name"\$1,\$1"data\$1type":"varchar","dimension\$1name":"instance\$1name"\$1,\$1"data\$1type":"varchar","dimension\$1name":"process\$1name"\$1,\$1"data\$1type":"varchar","dimension\$1name":"jdk\$1version"\$1,\$1"data\$1type":"varchar","dimension\$1name":"cell"\$1,\$1"data\$1type":"varchar","dimension\$1name":"region"\$1,\$1"data\$1type":"varchar","dimension\$1name":"silo"\$1] | 
| metrics | multi | [\$1"data\$1type":"varchar","dimension\$1name":"availability\$1zone"\$1,\$1"data\$1type":"varchar","dimension\$1name":"microservice\$1name"\$1,\$1"data\$1type":"varchar","dimension\$1name":"instance\$1name"\$1,\$1"data\$1type":"varchar","dimension\$1name":"os\$1version"\$1,\$1"data\$1type":"varchar","dimension\$1name":"cell"\$1,\$1"data\$1type":"varchar","dimension\$1name":"region"\$1,\$1"data\$1type":"varchar","dimension\$1name":"silo"\$1,\$1"data\$1type":"varchar","dimension\$1name":"instance\$1type"\$1] | 

In this case, you can see that the events and metrics also have different sets of dimensions, where events have different dimensions `jdk_version` and `process_name` while metrics have dimensions `instance_type` and `os_version`.

Using different measure names allow you to write queries with predicates such as `WHERE measure_name = 'metrics'` to get only the metrics. Also having all the data emitted from the same instance in the same table implies you can also write a simpler query with the `instance_name` predicate to get all data for that instance. For instance, a predicate of the form `WHERE instance_name = 'instance-1234'` without a `measure_name` predicate will return all data for a specific server instance.

## Recommendations for partitioning multi-measure records
<a name="data-modeling-multi-measure-partitioning"></a>

**Important**  
**This section is deprecated\$1**  
These recommendations are out of date. Partitioning is now better controlled using [customer-defined partition keys](customer-defined-partition-keys.md). 

We have seen that there is a growing number of workloads in the time series ecosystem that require ingesting and storing massive amounts of data while simultaneously needing low latency query responses when accessing data by a high cardinality set of dimension values.

Because of such characteristics, recommendations in this section will be useful for customer workloads that have the following:
+ Adopted or want to adopt multi-measure records.
+ Expect to have a high volume of data coming into the system that will be stored for long periods.
+ Require low latency response times for their main access (query) patterns.
+ Know that the most important queries patterns involve a filtering condition of some sort in the predicate. This filtering condition is based around a high cardinality dimension. For example, consider events or aggregations by UserId, DeviceId, ServerID, host-name, and so forth.

In these cases, a single name for all the multi-measure measures will not help since our engine uses multi-measure names to partition the data and having a single value limits the partition advantage that you get. The partitioning for these records is mainly based on two dimensions. Let’s say time is on the x-axis and a hash of dimension names and the `measure_name` is on the y-axis. The `measure_name` in these cases works almost like a partitioning key.

Our recommendation is as follows:
+ When modeling your data for use cases like the one we mentioned, use a `measure_name` that is a direct derivative of your main query access pattern. For example:
  + Your use case requires tracking application performance and QoE from the end user point of view. This could also be tracking measurements for a single server or IoT device.
  + If you are querying and filtering by UserId, then you need, at ingestion time, to find the best way to associate `measure_name` to UserId.
  + Since a multi-measure table can only hold 8,192 different measure names, whatever formula is adopted should not generate more that 8,192 different values.
+ One approach that we have applied with success for string values is to apply a hashing algorithm to the string value. Then perform the modulo operation with the absolute value of the hash result and 8,192.

  ```
  measure_name = getMeasureName(UserId)
  int getMeasureName(value) {
      hash_value =  abs(hash(value))
      return hash_value % 8192
  }
  ```
+ We also added `abs()` to remove the sign eliminating the possibility for values to range from -8,192 to 8,192. This should be performed prior to the modulo operation.
+ By using this method your queries can run on a fraction of the time that would take to run on an unpartitioned data model.
+ When querying the data, make sure that you include a filtering condition in the predicate that uses the newly derived value of the `measure_name`. For example:
  + 

    ```
    SELECT * FROM your_database.your_table 
    WHERE host_name = 'Host-1235' time BETWEEN '2022-09-01' 
        AND '2022-09-18' 
        AND measure_name = (SELECT cast(abs(from_big_endian_64(xxhash64(CAST('HOST-1235' AS varbinary))))%8192 AS varchar))
    ```
  + This will minimize the total number of partitions scanned to get you data that will translate in faster queries over time.

Keep in mind that if you want to obtain the benefits from this partition schema, the hash needs to be calculated on the client side and passed to Timestream for LiveAnalytics as a static value to the query engine. The preceding example provides a way to validate that the generated hash can be resolved by the engine when needed.


| time | host\$1name | location | server\$1type | cpu\$1usage | available\$1memory | cpu\$1temp | 
| --- | --- | --- | --- | --- | --- | --- | 
|  2022-09-07 21:48:44 .000000000  |  host-1235  |  us-east1  |  5.8xl  |  55  |  16.2  |  78  | 
|  R2022-09-07 21:48:44 .000000000  |  host-3587  |  us-west1  |  5.8xl  |  62  |  18.1  |  81  | 
|  2022-09-07 21:48:45.000000000  |  host-258743  |  eu-central  |  5.8xl  |  88  |  9.4  |  91  | 
|  2022-09-07 21:48:45 .000000000  |  host-35654  |  us-east2  |  5.8xl  |  29  |  24  |  54  | 
|  R2022-09-07 21:48:45 .000000000  |  host-254  |  us-west1  |  5.8xl  |  44  |  32  |  48  | 

To generate the associated `measure_name` following our recommendation, there are two paths that depend on your ingestion pattern.

1. *For batch ingestion of historical data*—You can add the transformation to your write code if you will use your own code for the batch process.

   Building on top of the preceding example.

   ```
           List<String> hosts = new ArrayList<>();
   
           hosts.add("host-1235");
           hosts.add("host-3587");
           hosts.add("host-258743");
           hosts.add("host-35654");
           hosts.add("host-254");
   
           for (String h: hosts){
               ByteBuffer buf2 = ByteBuffer.wrap(h.getBytes());
               partition = abs(hasher.hash(buf2, 0L)) % 8192;
               System.out.println(h + " - " + partition);
   
           }
   ```

   Output

   ```
   host-1235 - 6445
   host-3587 - 6399
   host-258743 - 640
   host-35654 - 2093
   host-254 - 7051
   ```

   Resulting dataset    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/data-modeling.html)

1. *For real-time ingestion*—You need to generate the `measure_name` in-flight as data is coming in.

In both cases, we recommend you test your hash generating algorithm at both ends (ingestion and querying) to make sure you are getting the same results.

Here are some code examples to generate the hashed value based on `host_name`.

**Example Python**  

```
>>> import xxhash
>>> from bitstring import BitArray
>>> b=xxhash.xxh64('HOST-ID-1235').digest()
>>> BitArray(b).int % 8192
### 3195
```

**Example Go**  

```
package main

import (
    "bytes"
    "fmt"
    "github.com/cespare/xxhash"
)

func main() {
    buf := bytes.NewBufferString("HOST-ID-1235")
    x := xxhash.New()
    x.Write(buf.Bytes())
    // convert unsigned integer to signed integer before taking mod
    fmt.Printf("%f\n", abs(int64(x.Sum64())) % 8192)
}

func abs(x int64) int64 {
    if (x < 0) {
        return -x
    }
    return x
}
```

**Example Java**  

```
import java.nio.ByteBuffer;

import net.jpountz.xxhash.XXHash64;

public class test {
    public static void main(String[] args) {
        XXHash64 hasher = net.jpountz.xxhash.XXHashFactory.fastestInstance().hash64();

        String host = "HOST-ID-1235";
        ByteBuffer buf = ByteBuffer.wrap(host.getBytes());

        Long result = Math.abs(hasher.hash(buf, 0L));
        Long partition = result % 8192;

        System.out.println(result);
        System.out.println(partition);
    }
}
```

**Example dependency in Maven**  

```
        <dependency>
            <groupId>net.jpountz.lz4</groupId>
            <artifactId>lz4</artifactId>
            <version>1.3.0</version>
        </dependency>
```

# Security
<a name="security-bp"></a>
+ For continuous access to Timestream for LiveAnalytics, ensure that encryption keys are secured and are not revoked or made inaccessible.
+ Monitor API access logs from AWS CloudTrail. Audit and revoke any anomalous access pattern from unauthorized users. 
+ Follow additional guidelines described in [Security best practices for Amazon Timestream for LiveAnalytics](best-practices-security.md).

# Configuring Amazon Timestream for LiveAnalytics
<a name="configuration"></a>

Configure the data retention period for the memory store and the magnetic store to match the data processing, storage, query performance, and cost requirements.
+ Set the data retention of the memory store to match your application's requirements for processing late-arriving data. Late-arriving data is incoming data with a timestamp earlier than the current time. It is emitted from resources that batch events for a time period before sending the data to Timestream for LiveAnalytics, and also from resources with intermittent connectivity e.g. an IoT sensor that is online intermittently.
+ If you expect late-arriving data to occasionally arrive with timestamps earlier than the memory store retention, you should enable magnetic store writes for your table. Once you set the EnableMagneticStoreWrites in MagneticStoreWritesProperties for a table, the table will accept data with timestamp earlier than your memory store retention but within your magnetic store retention period.
+ Consider the characteristics of queries that you plan to run on Timestream for LiveAnalytics such as the types of queries, frequency, time range, and performance requirements. This is because the memory store and magnetic store are optimized for different scenarios. The memory store is optimized for fast point-in-time queries that process small amounts of recent data sent to Timestream for LiveAnalytics. The magnetic store is optimized for fast analytical queries that process medium to large volumes of data sent to Timestream for LiveAnalytics.
+ Your data retention period should also be influenced by the cost requirements of your system.

  For example, consider a scenario where the late-arriving data threshold for your application is 2 hours and your applications send many queries that process a day's-worth, week's-worth, or month's-worth of data. In that case, you may want to configure a smaller retention period for the memory store (2-3 hours) and allow more data to flow to the magnetic store given the magnetic store is optimized for fast analytical queries.

Understand the impact of increasing or decreasing the data retention period of the memory store and the magnetic store of an existing table.
+ When you decrease the retention period of the memory store, the data is moved from the memory store to the magnetic store, and this data transfer is permanent. Timestream for LiveAnalytics does not retrieve data from the magnetic store to populate the memory store. When you decrease the retention period of the magnetic store, the data is deleted from the system, and the data deletion is permanent.
+ When you increase the retention period of the memory store or the magnetic store, the change takes effect for data being sent to Timestream for LiveAnalytics from that point onwards. Timestream for LiveAnalytics does not retrieve data from the magnetic store to populate the memory store. For example, if the retention period of the memory store was initially set to 2 hours and then increased to 24 hours, it will take 22 hours for the memory store to contain 24 hours worth of data.

# Writes
<a name="data-ingest"></a>
+ Ensure that the timestamp of the incoming data is not earlier than data retention configured for the memory store and no later than the future ingestion period defined in [QuotasDefault quotas](ts-limits.md). Sending data with a timestamp outside these bounds will result in the data being rejected by Timestream for LiveAnalytics unless you enable magnetic store writes for your table. If you enable magnetic store writes, ensure that the timestamp for incoming data is not earlier than data retention configured for the magnetic store.
+ If you expect late arriving data, turn on magnetic store writes for your table. This will allow ingestion for data with timestamps that fall outside your memory store retention period but still within your magnetic store retention period. You can set this by updating the `EnableMagneticStoreWrites` flag in the `MagneticStoreWritesProperties` for your table. This property is false by default. Note that writes to the magnetic store will not be immediately available to query. They will be available within 6 hours.
+ Target high throughput workloads to the memory store by ensuring the timestamps of the ingested data fall within the memory store retention bounds. Writes to the magnetic store are limited to a max number of active magnetic store partitions that can receive concurrent ingestion for a database. You can see this `ActiveMagneticStorePartitions` metric in CloudWatch. To reduce active magnetic store partitions, aim to reduce the number of series and duration of time you ingest into concurrently for magnetic store ingestion.
+ While sending data to Timestream for LiveAnalytics, batch multiple records in a single request to optimize data ingestion performance.
  + It is beneficial to batch together records from the same time series and records with the same measure name.
  + Batch as many records as possible in a single request as long as the requests are within the service limits defined in [QuotasDefault quotas](ts-limits.md).
  + Use common attributes where possible to reduce data transfer and ingestion costs. For more information, see [ WriteRecords API](https://docs.aws.amazon.com/timestream/latest/developerguide/API_WriteRecords.html).
+ If you encounter partial client-side failures while writing data to Timestream for LiveAnalytics, you can resend the batch of records that failed ingestion after you've addressed the rejection cause.
+ Data ordered by timestamps has better write performance.
+ Amazon Timestream for LiveAnalytics is designed to automatically scale to the needs of your application. When Timestream for LiveAnalytics notices spikes in write requests from your application, your application may experience some level of initial memory store throttling. If your application experiences memory store throttling, continue sending data to Timestream for LiveAnalytics at the same (or increased) rate to enable Timestream for LiveAnalytics to automatically scale to satisfy the needs of your application. If you see magnetic store throttling, you should decrease your rate of magnetic store ingestion until your number of `ActiveMagneticStorePartitions` falls.

# Batch load
<a name="batch-load-bp"></a>

Best practices for batch load are described in [Batch load best practices](batch-load-best-practices.md).

# Queries
<a name="queries-bp"></a>

Following are suggested best practices for queries with Amazon Timestream for LiveAnalytics.
+ Include only the measure and dimension names essential to query. Adding extraneous columns will increase data scans, which impacts the performance of queries.
+ Before deploying your query in production, we recommend that you review query insights to make sure that the spatial and temporal pruning is optimal. For more information, see [Using query insights to optimize queries in Amazon Timestream](using-query-insights.md).
+ Where possible, push the data computation to Timestream for LiveAnalytics using the built-in aggregates and scalar functions in the SELECT clause and WHERE clause as applicable to improve query performance and reduce cost. See [SELECTUNLOAD](supported-sql-constructs.SELECT.md) and [Aggregate functions](aggregate-functions.md).
+ Where possible, use approximate functions. E.g., use APPROX\$1DISTINCT instead of COUNT(DISTINCT column\$1name) to optimize query performance and reduce the query cost. See [Aggregate functions](aggregate-functions.md).
+ Use a CASE expression to perform complex aggregations instead of selecting from the same table multiple times. See [The CASE statement](conditional-expressions.CASE.md).
+ Where possible, include a time range in the WHERE clause of your query. This optimizes query performance and costs. For example, if you only need the last one hour of data in your dataset, then include a time predicate such as time > ago(1h). See [SELECTUNLOAD](supported-sql-constructs.SELECT.md) and [Interval and duration](date-time-functions.md#date-time-functions-interval-duration).
+ When a query accesses a subset of measures in a table, always include the measure names in the WHERE clause of the query.
+ Where possible, use the equality operator when comparing dimensions and measures in the WHERE clause of a query. An equality predicate on dimensions and measure names allows for improved query performance and reduced query costs.
+ Wherever possible, avoid using functions in the WHERE clause to optimize for cost.
+ Refrain from using LIKE clause multiple times. Rather, use regular expressions when you are filtering for multiple values on a string column. See [Regular expression functions](regex-functions.md).
+ Only use the necessary columns in the GROUP BY clause of a query.
+ If the query result needs to be in a specific order, explicitly specify that order in the ORDER BY clause of the outermost query. If your query result does not require ordering, avoid using an ORDER BY clause to improve query performance.
+ Use a LIMIT clause if you only need the first N rows in your query.
+ If you are using an ORDER BY clause to look at the top or bottom N values, use a LIMIT clause to reduce the query costs.
+ Use the pagination token from the returned response to retrieve the query results. For more information, see [Query](API_query_Query.html).
+ If you've started running a query and realize that the query will not return the results you're looking for, cancel the query to save cost. For more information, see [CancelQuery](API_query_CancelQuery.html).
+ If your application experiences throttling, continue sending data to Amazon Timestream for LiveAnalytics at the same rate to enable Amazon Timestream for LiveAnalytics to auto-scale to the satisfy the query throughput needs of your application.
+ If the query concurrency requirements of your applications exceed the default limits of Timestream for LiveAnalytics, contact Support for limit increases.

# Scheduled queries
<a name="scheduledqueries-bp"></a>

Scheduled queries help you optimize your dashboards by pre-computing some fleet-wide aggregate statistics. So a natural question to ask is how do you take your use case and identify which results to pre-compute and how to use these results stored in a derived table to create your dashboard. The first step in this process is to identify which panels to pre-compute. Below are some high-level guidelines:
+ Consider the bytes scanned by the queries that are used to populate the panels, the frequency of dashboard reload, and number of concurrent users who would load these dashboards. You should start with the dashboards loaded most frequently and scanning significant amounts of data. The first two dashboards in the [aggregate dashboard](https://docs.aws.amazon.com/timestream/latest/developerguide/scheduledqueries-example1.html) example as well as the aggregate dashboard in the [drill down](https://docs.aws.amazon.com/timestream/latest/developerguide/scheduledqueries-example2.html) example are good examples of such dashboards. 
+ Consider which computations are being [repeatedly used](https://docs.aws.amazon.com/timestream/latest/developerguide/cheduledqueries-example3.html). While it is possible to create a scheduled query for every panel and every variable value used in the panel, you can significantly optimize your costs and the number of scheduled queries by looking for avenues to use one computation to pre-compute the data necessary for multiple panels. 
+ Consider the frequency of your scheduled queries to refresh the materialized results in the derived table. You would want to analyze how frequently a dashboard is refreshed vs. the time window that is queried in a dashboard vs. the time binning used in the pre-computation as well as the panels in the dashboards. For instance, if a dashboard that is plotting hourly aggregates for the past few days is only refreshed once in a few hours, you might want to configure your scheduled queries to only refresh once every 30 mins or an hour. On the other hand, if you have a dashboard that plots per minute aggregates and is refreshed every minute or so, you would want your scheduled queries to refresh the results every minute or few minutes.
+ Consider which query patterns can be further optimized (both from a query cost and query latency perspective) using scheduled queries. For instance, when computing the unique dimension values frequently used as variables in dashboards, or returning the last data point emitted from a sensor or the first data point emitted from a sensor after a certain date, etc. Some of these [example patterns](https://docs.aws.amazon.com/timestream/latest/developerguide/scheduledqueries-patterns.html) are discussed in this guide.

The preceding considerations will have a significant impact on your savings when you move your dashboard to query the derived tables, the freshness of data in your dashboards, and the cost incurred by the scheduled queries.

# Client applications and supported integrations
<a name="client-integrations"></a>

Run your client application from the same Region as Timestream for LiveAnalytics to reduce network latencies and data transfer costs. For more information about working with other services, see [Working with other services](OtherServices.md). The following are some other helpful links.
+  [ Best Practices for AWS Development with the AWS SDK for Java](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/best-practices.html)
+  [ Best practices for working with AWS Lambda functions](https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html)
+ [ Best Practices for Amazon Managed Service for Apache Flink](https://docs.aws.amazon.com/kinesisanalytics/latest/dev/best-practices.html)
+ [ Best practices for creating dashboards in Grafana](https://grafana.com/docs/grafana/latest/best-practices/best-practices-for-creating-dashboards/)

# General
<a name="general"></a>
+ Ensure that you follow the [The AWS Well-Architected Framework](https://wa.aws.amazon.com/index.en.html) when using Timestream for LiveAnalytics. This whitepaper provides guidance around best practices in operational excellence, security, reliability, performance efficiency, and cost optimization. 

# Metering and cost optimization
<a name="metering-and-pricing"></a>

With Amazon Timestream for LiveAnalytics, you pay only for what you use. Timestream for LiveAnalytics meters separately for writes, data stored, and data scanned by queries. The price of each metering dimension is specified on the [pricing page](https://aws.amazon.com/timestream/pricing/). You can estimate your monthly bill using the [Amazon Timestream for LiveAnalytics Pricing Calculator](samples/Amazon_Timestream_Pricing_Calculator.zip).

This section describes how metering works for writes, storage and queries in Timestream for LiveAnalytics. Example scenarios and calculations are also provided. In addition, a list of best practices for cost optimization is included. You can select a topic below: 

**Topics**
+ [Writes](metering-and-pricing.writes.md)
+ [Storage](metering-and-pricing.storage.md)
+ [Queries](metering-and-pricing.queries.md)
+ [Cost optimization](metering-and-pricing.cost-optimization.md)
+ [Monitoring with Amazon CloudWatch](monitoring-cloudwatch.md)

# Writes
<a name="metering-and-pricing.writes"></a>

 The write size of each time series event is calculated as the sum of the size of the timestamp and one or more dimension names, dimension values, measure names, and measure values. The size of the timestamp is 8 bytes. The size of dimension names, dimension values, and measure names are the length of the UTF-8 encoded bytes of the string representing each dimension name, dimension value, and measure name. The size of the measure value depends on the data type. It is 1 byte for the boolean data type, 8 bytes for bigint and double, and the length of the UTF-8 encoded bytes for strings. Each write is counted in units of 1 KiB. 

Two example calculations are provided below:

**Topics**
+ [Calculating the write size of a time series event](#metering-and-pricing.writes.write-size-one-event)
+ [Calculating the number of writes](#metering-and-pricing.writes.write-size-multiple-events)

## Calculating the write size of a time series event
<a name="metering-and-pricing.writes.write-size-one-event"></a>

Consider a time series event representing the CPU utilization of an EC2 instance as shown below:


| Time | region | az | vpc | Hostname | measure\$1name | measure\$1value::double | 
| --- | --- | --- | --- | --- | --- | --- | 
|  1602983435238563000  |  us-east-1  |  1d  |  vpc-1a2b3c4d  |  host-24Gju  |  cpu\$1utilization  |  35.0  | 

The write size of the time series event can be calculated as:
+ time = 8 bytes
+ first dimension = 15 bytes (`region`\$1`us-east-1`)
+ second dimension = 4 bytes (`az`\$1`1d`)
+ third dimension = 15 bytes (`vpc`\$1`vpc-1a2b3c4d`)
+ fourth dimension = 18 bytes (`hostname`\$1`host-24Gju`)
+ name of the measure = 15 bytes (`cpu_utilization`)
+ value of the measure = 8 bytes

**Write size of the time series event = 83 bytes**

## Calculating the number of writes
<a name="metering-and-pricing.writes.write-size-multiple-events"></a>

Now consider 100 EC2 instances, similar to the instance described in [Calculating the write size of a time series event](#metering-and-pricing.writes.write-size-one-event), emitting metrics every 5 seconds. The total monthly writes for the EC2 instances will vary based on how many time series events exist per write and if common attributes are being used while batching time series events. An example of calculating total monthly writes is provided for each of the following scenarios:

**Topics**
+ [One time series event per write](#metering-and-pricing.writes.write-size-multiple-events.one-event-per-write)
+ [Batching time series events in a write](#metering-and-pricing.writes.write-size-multiple-events.batching-events)
+ [Batching time series events and using common attributes in a write](#metering-and-pricing.writes.write-size-multiple-events.batching-events-and-using-common-attrbs)

### One time series event per write
<a name="metering-and-pricing.writes.write-size-multiple-events.one-event-per-write"></a>

If each write contains only one time series event, the total monthly writes are calculated as:
+ 100 time series events = 100 writes every 5 seconds
+ x 12 writes/minute = 1,200 writes
+ x 60 minutes/hour = 72,000 writes
+ x 24 hours/day = 1,728,000 writes
+ x 30 days/month = 51,840,000 writes

**Total monthly writes = 51,840,000**

### Batching time series events in a write
<a name="metering-and-pricing.writes.write-size-multiple-events.batching-events"></a>

Given each write is measured in units of 1 KB, a write can contain a batch of 12 time series events (998 bytes) and the total monthly writes are calculated as:
+ 100 time series events = 9 writes (12 time series events per write) every 5 seconds
+ x 12 writes/minute = 108 writes
+ x 60 minutes/hour = 6,480 writes
+ x 24 hours/day = 155,520 writes
+ x 30 days/month = 4,665,600 writes

**Total monthly writes = 4,665,600**

### Batching time series events and using common attributes in a write
<a name="metering-and-pricing.writes.write-size-multiple-events.batching-events-and-using-common-attrbs"></a>

If the region, az, vpc, and measure name are common across 100 EC2 instances, the common values can be specified just once per write and are referred to as common attributes. In this case, the size of common attributes is 52 bytes, and the size of the time series events is 27 bytes. Given each write is measured in units of 1 KiB, a write can contain 36 time series events and common attributes, and the total monthly writes are calculated as:
+ 100 time series events = 3 writes (36 time series events per write) every 5 seconds
+ x 12 writes/minute = 36 writes
+ x 60 minutes/hour = 2,160 writes
+ x 24 hours/day = 51,840 writes
+ x 30 days/month = 1,555,200 writes

**Total monthly writes = 1,555,200**

**Note**  
Due to usage of batching, common attributes and rounding of the writes to units of 1KB, the storage size of the time series events may be different than write size.

# Storage
<a name="metering-and-pricing.storage"></a>

 The storage size of each time series event in the memory store and the magnetic store is calculated as the sum of the size of the timestamp, dimension names, dimension values, measure names, and measure values. The size of the timestamp is 8 bytes. The size of dimension names, dimension values, and measure names are the length of the UTF-8 encoded bytes of each string representing the dimension name, dimension value, and measure name. The size of the measure value depends on the data type. It is 1 byte for boolean data types, 8 bytes for bigint and double, and the length of the UTF-8 encoded bytes for strings. Each measure is stored as a separate record in Amazon Timestream for LiveAnalytics, i.e. if your time series event has four measures, there will be four records for that time series event in storage. 

Considering the example of the time series event representing the CPU utilization of an EC2 instance (see [Calculating the write size of a time series event](metering-and-pricing.writes.md#metering-and-pricing.writes.write-size-one-event)), the storage size of the time series event is calculated as:
+ time = 8 bytes
+ first dimension = 15 bytes (`region`\$1`us-east-1`)
+ second dimension = 4 bytes (`az`\$1`1d`)
+ third dimension = 15 bytes (`vpc`\$1`vpc-1a2b3c4d`)
+ fourth dimension = 18 bytes (`hostname`\$1`host-24Gju`)
+ name of the measure = 15 bytes (`cpu_utilization`)
+ value of the measure = 8 bytes

**Storage size of the time series event = 83 bytes**

**Note**  
The memory store is metered in GB-hour and the magnetic store is metered in GB-month.

# Queries
<a name="metering-and-pricing.queries"></a>

Queries are charged based on the duration of [Timestream compute units (TCUs)](tcu.md) used by your application in TCU-hours as specified on the [Amazon Timestream pricing](https://aws.amazon.com/timestream/pricing/) page. Amazon Timestream for LiveAnalytics' query engine prunes irrelevant data while processing a query. Queries with projections and predicates including time ranges, measure names, and/or dimension names enable the query processing engine to prune a significant amount of data and help with lowering query costs.

# Cost optimization
<a name="metering-and-pricing.cost-optimization"></a>

To optimize the cost of writes, storage, and queries, use the following best practices with Amazon Timestream for LiveAnalytics:
+ Batch multiple time series events per write to reduce the number of write requests.
+ Consider using Multi-measure records, which allows you to write multiple time-series measures in a single write request and stores your data in a more compact manner. This reduces the number of write requests as well as data storage cost and query cost. 
+ Use common attributes with batching to batch more time series events per write to further reduce the number of write requests.
+ Set the data retention of the memory store to match your application's requirements for processing late-arriving data. Late-arriving data is incoming data with a timestamp earlier than the current time and outside the memory store retention period.
+ Set the data retention of the magnetic store to match your long term data storage requirements.
+ While writing queries, include only the measure and dimension names essential to query. Adding extraneous columns will increase data scans and therefore will also increase the query cost. We recommend that you review [query insights](using-query-insights.md) to assess the pruning efficiency of the included dimensions and measures.
+ Where possible, include a time range in the WHERE clause of your query. For example, if you only need the last one hour of data in your dataset, include a time predicate such as `time > ago(1h)`.
+ When a query accesses a subset of measures in a table, always include the measure names in the WHERE clause of the query.
+ If you've started running a query and realize that the query will not return the results you're looking for, cancel the query to save on cost.

# Monitoring with Amazon CloudWatch
<a name="monitoring-cloudwatch"></a>

You can monitor Timestream for LiveAnalytics using Amazon CloudWatch, which collects and processes raw data from Timestream for LiveAnalytics into readable, near-real-time metrics. It records these statistics for two weeks so that you can access historical information and gain a better perspective on how your web application or service is performing. By default, Timestream for LiveAnalytics metric data is automatically sent to CloudWatch in 1-minute or 15-minute periods. For more information, see [What Is Amazon CloudWatch?](https://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/WhatIsCloudWatch.html) in the *Amazon CloudWatch User Guide*.

**Topics**
+ [How do I use Timestream for LiveAnalytics metrics?](#how-to-use-metrics)
+ [Timestream for LiveAnalytics metrics and dimensions](metrics-dimensions.md)
+ [Creating CloudWatch alarms to monitor Timestream for LiveAnalytics](creating-alarms.md)

## How do I use Timestream for LiveAnalytics metrics?
<a name="how-to-use-metrics"></a>

The metrics reported by Timestream for LiveAnalytics provide information that you can analyze in different ways. The following list shows some common uses for the metrics. These are suggestions to get you started, not a comprehensive list.


****  

|  How can I?  |  Relevant metrics  | 
| --- | --- | 
|  How can I determine if any system errors occurred?  |  You can monitor `SystemErrors` to determine whether any requests resulted in a server error code. Typically, this metric should be equal to zero. If it isn't, you might want to investigate.  | 
|  How can I monitor the amount of data in the memory store?  |  You can monitor `MemoryCumulativeBytesMetered` over the specified time period, to monitor the amount of data stored in memory store in bytes. This metric is emitted every hour and you can track the bytes stored at an account as well as at database granularity. The memory store is metered in GB-hour (the cost of storing 1GB of data for one hour). So multiplying the hourly value of `MemoryCumulativeBytesMetered` with GB-hour pricing in your Region will give you the cost incurred per hour. Dimensions: Operation (storage), DatabaseName, Metric name  | 
|  How can I monitor the amount of data in the magnetic store?  |   You can monitor `MagneticCumulativeBytesMetered` over the specified time period, to monitor the amount of data stored in magnetic store in bytes. This metric is emitted every hour and you can track the bytes stored at an account as well as at database granularity. The memory store is metered in GB-month (the cost of storing 1GB of data for one month). So multiplying the hourly value of `MagneticCumulativeBytesMetered` with GB-month pricing in your Region will give you the cost incurred per hour. For example, if the value of `MagneticCumulativeBytesMetered` is 107374182400 bytes (100GB), then the hourly charge of 1GB of data in magnetic store = (0.03) (us-east-1 pricing) / (30.4\$124). Multiplying this value with the `MagneticCumulativeBytesMetered` in GB will give \$1\$10.004 for that hour. Dimensions: Operation (Storage), DatabaseName, Metric name  | 
|  How can I monitor the data scanned by queries?  |   You can monitor `CumulativeBytesMetered` over the specified time period, to monitor the data scanned by queries (in bytes) sent to Timestream for LiveAnalytics. This metric is emitted after the query execution and you can track the data scanned at account and database granularity. You can calculate the query cost for a particular period by multiplying the value of the metric with per GB scanned pricing in your Region. The bytes scanned by scheduled queries are accounted for in this metric. Dimensions: Operation (Query), DatabaseName, Metric name  | 
|  How can I monitor the data scanned by scheduled queries?  |   You can monitor `CumulativeBytesMetered` over the specified time period, to monitor the data scanned by scheduled queries (in bytes) executed by Timestream for LiveAnalytics. This metric is emitted after the query execution and you can track the data scanned at account and database granularity. You can calculate the query cost for a particular period by multiplying the value of the metric with per GB scanned pricing in your Region.  The bytes metered are also accounted for in the query `CumulativeBytesMetered`.  Dimensions: Operation (TriggeredScheduledQuery), DatabaseName, Metric name  | 
|  How can I monitor the number of records ingested?  |  You can monitor `NumberOfRecords` over the specified time period to monitor the number of records ingested. You can track the bytes stored at an account as well as at database granularity. You can also use this metric to monitor the writes made by Scheduled Queries when query results are written into a separate table. When using the `WriteRecords` API, the metric is emitted for each `WriteRecords` request, with the CloudWatch Operation dimension being `WriteRecords`. When using the `BatchLoad` or `ScheduledQuery` APIs, the metric is emitted at intervals determined by the service until the task completes. The CloudWatch Operation dimension for this metric is either `BatchLoad` or `ScheduledQuery`, depending on which API is used. Dimensions: Operation (WriteRecords, BatchLoad, or ScheduledQuery), DatabaseName, Metric name  | 
|  How can I monitor the cost of records ingested?  |  You can monitor `CumulativeBytesMetered` to monitor the number of bytes ingested that accrue cost. You can track the bytes stored at an account as well as at database granularity. Ingested records are metered in cumulative bytes. Multiplying the value of `CumulativeBytesMetered` by Writes pricing in your Region gives you the ingestion cost incurred. When using the `WriteRecords` API, this metric is emitted for each `WriteRecords` request, with the CloudWatch Operation dimension being `WriteRecords`. When using the `BatchLoad` or `ScheduledQuery` API, the metric is emitted at intervals determined by the service until the task completes. The CloudWatch Operation dimension for this metric is `BatchLoad` or `ScheduledQuery` depending on which API is used.. Dimensions: Operation (WriteRecords, BatchLoad, or ScheduledQuery), DatabaseName, Metric name  | 
| How can I monitor the Timestream Compute Units (TCUs) used in my account? |  You can monitor `QueryTCU` over the desired time period, to monitor the compute units provisioned in your account. This metric is emitted every 15-minutes. Units: `Count` Valid Statistics: Minimum, Maximum Metric: `ResourceCount` Dimensions: `Service: Timestream`, `Namespace:AWS/Usage`, `Resource: QueryTCU`, `Type: Resource`, `Class: OnDemand`  | 
| How can I monitor the number of provisioned Timestream Compute Units (TCUs) used in my account? |  Provisioned TCU is available only in the Asia Pacific (Mumbai) region. You can monitor `QueryTCU` to monitor the number of provisioned TCUs used for query workload in the account. This metric is emitted every minute for the during active query workload from the account. Units: `Count` Valid Statistics: Minimum, Maximum Metric: `ResourceCount` Dimensions: `Service: Timestream`, `Namespace: AWS/Usage`, `Resource: ProvisionedQueryTCU`, `Class: None`  | 
| How can I monitor the provisioned Timestream Compute Units (TCUs) used in my account? |  Provisioned TCU is available only in the Asia Pacific (Mumbai) region. You can monitor `QueryTCU` over the specified time period, to monitor the compute units consumed for query workload in the account. This metric is emitted with maximum and minimum compute units for every minute during active query workload from the account. Units: `Count` Valid Statistics: Minimum, Maximum Metric: `ResourceCount` Dimensions: `Service: Timestream`, `Namespace: AWS/Usage`, `Resource: QueryTCU`, `Class: Provisioned`  | 

# Timestream for LiveAnalytics metrics and dimensions
<a name="metrics-dimensions"></a>

When you interact with Timestream for LiveAnalytics, it sends the following metrics and dimensions to Amazon CloudWatch. All metrics are aggregated and reported every minute. You can use the following procedures to view the metrics for Timestream for LiveAnalytics.

**To view metrics using the CloudWatch console**

Metrics are grouped first by the service namespace, and then by the various dimension combinations within each namespace.

1. Open the CloudWatch console at [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/).

1. If necessary, change the Region. On the navigation bar, choose the Region where your AWS resources reside. For more information, see [AWS Service Endpoints](http://docs.aws.amazon.com/general/latest/gr/rande.html).

1. In the navigation pane, choose **Metrics**.

1. Under the **All metrics** tab, choose `AWS/Timestream for LiveAnalytics.`

**To view metrics using the AWS CLI**
+ At a command prompt, use the following command.

  ```
  1. aws cloudwatch list-metrics --namespace "AWS/Timestream"
  ```

## Dimensions for Timestream for LiveAnalytics metrics
<a name="mcs-metric-dimensions"></a>

The metrics for Timestream for LiveAnalytics are qualified by the values for the account, table name, or operation. You can use the CloudWatch console to retrieve Timestream for LiveAnalytics data along any of the dimensions in the following table:


|  Dimension  |  Description  | 
| --- | --- | 
|  DatabaseName  |  This dimension limits the data to a specific Timestream for LiveAnalytics database. This value can be any database in the current Region and the current AWS account   | 
|  Operation  |  This dimension limits the data to one of the Timestream for LiveAnalytics operations, such as `Storage`, `WriteRecords`, `BatchLoad`, or `ScheduledQuery`. See the Timestream for LiveAnalytics Query API Reference for a list of available values.  | 
|  TableName  |  This dimension limits the data to a specific table in a Timestream for LiveAnalyticss database.   | 

**Important**  
`CumulativeBytesMetered`, `UserErrors` and `SystemErrors` metrics only have the `Operation` dimension. `SuccessfulRequestLatency` metrics always have `Operation` dimension, but may also have the `DatabaseName` and `TableName` dimensions too, depending on the value of `Operation`. This is because Timestream for LiveAnalytics table-level operations have `DatabaseName` and `TableName` as dimensions, but account level operations do not.

## Timestream for LiveAnalytics metrics
<a name="mcs-metrics"></a>

**Note**  
Amazon CloudWatch aggregates all the following Timestream for LiveAnalytics metrics at one-minute intervals.


**General metrics**  

| Metric | Description | 
| --- | --- | 
|  `SuccessfulRequestLatency`  |  The successful requests to Timestream for LiveAnalytics during the specified time period. SuccessfulRequestLatency can provide two different kinds of information: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/metrics-dimensions.html) SuccessfulRequestLatency reflects activity only within Timestream for LiveAnalytics and does not take into account network latency or client-side activity.  Units: `Milliseconds` [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/metrics-dimensions.html) Valid Statistics: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/metrics-dimensions.html)  | 


**Writing and storage metrics**  

| Metric | Description | 
| --- | --- | 
|  `MagneticStoreRejectedRecordCount`  |  The number of magnetic store written records that were rejected asynchronously. This can happen if the new record has a version that is less than the current version or the new record has version equal to the current version but has different data.  Units: `Count` [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/metrics-dimensions.html) Valid Statistics: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/metrics-dimensions.html)  | 
|  `MagneticStoreRejectedUploadUserFailures`  |  The number of magnetic store rejected record reports that were not uploaded due to user errors. This can be due to IAM permissions not configured correctly or a deleted S3 bucket.  Units: `Count` [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/metrics-dimensions.html) Valid Statistics: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/metrics-dimensions.html)  | 
|  `MagneticStoreRejectedUploadSystemFailures`  |  The number of magnetic store rejected record reports that were not uploaded due to system errors.   Units: `Count` [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/metrics-dimensions.html) Valid Statistics: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/metrics-dimensions.html)  | 
|  `ActiveMagneticStorePartitions`  |  The number of magnetic store partitions actively ingesting data at a given time.  Units: `Count` [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/metrics-dimensions.html) Valid Statistics: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/metrics-dimensions.html)  | 
|  `MagneticStorePendingRecordsLatency`  |  The oldest write to a magnetic store that is not available for query. Records written to the magnetic store will be available for querying within 6 hours.   Units: `Milliseconds` [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/metrics-dimensions.html) Valid Statistics: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/metrics-dimensions.html)  | 
|  `MemoryCumulativeBytesMetered`  |  The amount of data stored in memory store, in bytes  Units: `Bytes`  Dimensions: `Operation` Valid Statistics: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/metrics-dimensions.html)  | 
|  `MagneticCumulativeBytesMetered`  |  The amount of data stored in magnetic store, in bytes  Units: `Bytes`  Dimensions: `Operation` Valid Statistics: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/metrics-dimensions.html)  | 
|  `CumulativeBytesMetered`  |  The amount of data metered by ingestion to Timestream for LiveAnalytics, in bytes.  Units: `Bytes` Dimensions: `Operation` Valid Statistics: `Sum`  | 
|  `NumberOfRecords`  |  The number of records ingested into Timestream for LiveAnalytics.  Units: `Count` Dimensions: `Operation` Valid Statistics: `Sum`  | 


**Query metrics**  

| Metric | Description | 
| --- | --- | 
|  `CumulativeBytesMetered`  |  The amount of data scanned by queries sent to Timestream for LiveAnalytics, in bytes.   Units: `Bytes`  Dimensions: `Operation` Valid Statistics: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/metrics-dimensions.html)  | 
| ResourceCount |  The Timestream Compute Units (TCUs) consumed for query workload in the account. This metric is emitted with maximum and minimum compute units for every minute during active query workload from the account. Units: `Count` Valid Statistics: Minimum, Maximum Dimensions: `Service: Timestream`, `Resource: QueryTCU`, `Type: Resource`, `Class: OnDemand`  | 


**Error metrics**  

| Metric | Description | 
| --- | --- | 
|  `SystemErrors`  |  The requests to Timestream for LiveAnalytics that generate a SystemError during the specified time period. A SystemError usually indicates an internal service error.   Units: `Count`  Dimensions: `Operation` Valid Statistics: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/metrics-dimensions.html)  | 
|  `UserErrors`  |  Requests to Timestream for LiveAnalytics that generate an InvalidRequest error during the specified time period. An InvalidRequest usually indicates a client-side error, such as an invalid combination of parameters, an attempt to update a nonexistent table, or an incorrect request signature. UserErrors represents the aggregate of invalid requests for the current AWS Region and the current AWS account.   Units: `Count`  Dimensions: `Operation` Valid Statistics: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/metrics-dimensions.html)  | 

**Important**  
Not all statistics, such as `Average` or `Sum`, are applicable for every metric. However, all of these values are available through the Timestream for LiveAnalytics console, or by using the CloudWatch console, AWS CLI, or AWS SDKs for all metrics. 

# Creating CloudWatch alarms to monitor Timestream for LiveAnalytics
<a name="creating-alarms"></a>

You can create an Amazon CloudWatch alarm for Timestream for LiveAnalytics that sends an Amazon Simple Notification Service (Amazon SNS) message when the alarm changes state. An alarm watches a single metric over a time period that you specify. It performs one or more actions based on the value of the metric relative to a given threshold over a number of time periods. The action is a notification sent to an Amazon SNS topic or Auto Scaling policy.

Alarms invoke actions for sustained state changes only. CloudWatch alarms do not invoke actions simply because they are in a particular state. The state must have changed and been maintained for a specified number of periods.

For more information about creating CloudWatch alarms, see [Using Amazon CloudWatch Alarms](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html) in the *Amazon CloudWatch User Guide*.

# Troubleshooting
<a name="Troubleshooting"></a>

This section contains information on troubleshooting Timestream for LiveAnalytics. 

**Topics**
+ [Handling WriteRecords throttles](troubleshoot-writethrottles.md)
+ [Handling rejected records](troubleshoot-rejectedrecords.md)
+ [Troubleshooting UNLOAD from Timestream for LiveAnalytics](troubleshoot-export-unload.md)
+ [Timestream for LiveAnalytics specific error codes](APITimestreamSpecificErrors.md)

# Handling WriteRecords throttles
<a name="troubleshoot-writethrottles"></a>

Your memory store write requests to Timestream may be throttled as Timestream scales to adapt to the data ingestion needs of your application. If your applications encounter throttling exceptions, you must continue to send data at the same (or higher) throughput to allow Timestream to automatically scale to your application's needs. 

Your magnetic store write requests to Timestream may be throttled if the maximum limit of magnetic store partitions receiving ingestion. You will see a throttle message directing you to check the `ActiveMagneticStorePartitions` Cloudwatch metric for this database. This throttle may take up to 6 hours to resolve. To avoid this throttle, you should use the memory store for any high throughput ingestion workload. For magnetic store ingestion, you can target ingesting into fewer partitions by limiting how many series and the time duration that you ingest into

For more information about data ingestion best practices, see [Writes](data-ingest.md).

# Handling rejected records
<a name="troubleshoot-rejectedrecords"></a>

If Timestream rejects records, you will receive a `RejectedRecordsException` with details about the rejection. Please refer to [Handling write failure](https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.write.html#code-samples.write.rejectedRecordException) for more information on how to extract this information from the WriteRecords response.

 All rejections will be included in this response **with the exception of updates to the magnetic store where the new record's version is less than or equal to the existing record's version**. In this case, Timestream will not update the existing record that has the higher version. Timestream will reject the new record with lower or equal version and write these errors asynchronously to your S3 bucket. In order to receive these asynchronous error reports, you should set the `MagneticStoreRejectedDataLocation` property in `MagneticStoreWriteProperties` on your table. 

# Troubleshooting UNLOAD from Timestream for LiveAnalytics
<a name="troubleshoot-export-unload"></a>

Following is guidance for troubleshooting related to the UNLOAD command.

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/troubleshoot-export-unload.html)

# Timestream for LiveAnalytics specific error codes
<a name="APITimestreamSpecificErrors"></a>

This section contains the specific error codes for Timestream for LiveAnalytics. 

## Timestream for LiveAnalytics write API errors
<a name="APITimestreamSpecificErrors.write"></a>

****InternalServerException****  
 HTTP Status Code: 500

**ThrottlingException**  
 HTTP Status Code: 429

**ValidationException**  
 HTTP Status Code: 400

**ConflictException**  
 HTTP Status Code: 409

**AccessDeniedException**  
You do not have sufficient access to perform this action.  
 HTTP Status Code: 403

**ServiceQuotaExceededException**  
 HTTP Status Code: 402

**ResourceNotFoundException**  
 HTTP Status Code: 404

**RejectedRecordsException**  
 HTTP Status Code: 419

**InvalidEndpointException**  
 HTTP Status Code: 421

## Timestream for LiveAnalytics query API errors
<a name="APITimestreamSpecificErrors.query"></a>

**ValidationException**  
 HTTP Status Code: 400

**QueryExecutionException**  
 HTTP Status Code: 400

**ConflictException**  
 HTTP Status Code: 409

**ThrottlingException**  
 HTTP Status Code: 429

**InternalServerException**  
 HTTP Status Code: 500

**InvalidEndpointException**  
 HTTP Status Code: 421

# Quotas
<a name="ts-limits"></a>

This topic describes current quotas, also referred to as limits, within Amazon Timestream for LiveAnalytics. Each quota applies on a per-Region basis unless otherwise specified.

**Topics**
+ [Default quotas](#ts-limits.default)
+ [Service limits](#system-limits)
+ [Supported data types](#limits.datatypes)
+ [Batch load](#limits.batch-load)
+ [Naming constraints](#limits.naming)
+ [Reserved keywords](#limits.reserved)
+ [System identifiers](#limits.system_identifier)
+ [UNLOAD](#limits.export-unload)

## Default quotas
<a name="ts-limits.default"></a>

The following table contains the Timestream for LiveAnalytics quotas and the default values.


| displayName | Description | defaultValue | 
| --- | --- | --- | 
|  Databases per account  |  The maximum number of databases you can create per AWS account.  |  500  | 
|  Tables per account  |  The maximum number of tables you can create per AWS account.  |  50000  | 
|  Request rate for CRUD APIs  |  The maximum number of Create/Update/Delete requests allowed per second per account, in the current Region.  |  1  | 
|  Request rate for other APIs  |  The maximum number of List/Describe/Prepare/ExecuteScheduledQueryAPI requests allowed per second per account, in the current Region.  |  5  | 
|  Scheduled queries per account  |  The maximum number of scheduled queries you can create per AWS account.  |  10000  | 
|  Maximum count of active magnetic store partitions  |  The maximum number of active magnetic store partitions per database. A partition might remain active for up to six hours after receiving ingestion.  |  250  | 

## Service limits
<a name="system-limits"></a>

The following table contains the Timestream for LiveAnalytics service limits and the default values. To edit data retention for a table from the console, see [Edit a table](https://docs.aws.amazon.com/timestream/latest/developerguide/console_timestream.html#console_timestream.edit-table.using-console).


| displayName | Description | defaultValue | 
| --- | --- | --- | 
|  Future ingestion period in minutes  |  The maximum lead time (in minutes) for your time series data compared to the current system time. For example, if the future ingestion period is 15 minutes, then Timestream for LiveAnalytics will accept data that is up to 15 minutes ahead of the current system time.  |  15  | 
|  Minimum retention period for memory store in hours  |  The minimum duration (in hours) for which data must be retained in the memory store per table.  |  1  | 
|  Maximum retention period for memory store in hours  |  The maximum duration (in hours) for which data can be retained in the memory store per table.  |  8766  | 
|  Minimum retention period for magnetic store in days  |  The minimum duration (in days) for which data must be retained in the magnetic store per table.  |  1  | 
|  Maximum retention period for magnetic store in days  |  The maximum duration (in days) for which data can be retained in the magnetic store. This value is equivalent to 200 years.  |  73000  | 
|  Default retention period for magnetic store in days  |  The default value (in days) for which data is retained in the magnetic store per table. This value is equivalent to 200 years.  |  73000  | 
|  Default retention period for memory store in hours  |  The default duration (in hours) for which data is retained in the memory store.  |  6  | 
|  Dimensions per table  |  The maximum number of dimensions per table.  |  128  | 
|  Measure names per table  |  The maximum number of unique measure names per table.  |  8192  | 
|  Dimension name dimension value pair size per series  |  The maximum size of dimension name and dimension value pair per series.  |  2 Kilobytes  | 
|  Maximum record size  |  The maximum size of a record.  |  2 Kilobytes  | 
|  Records per WriteRecords API request  |  The maximum number of records in a WriteRecords API request.  |  100  | 
|  Dimension name length  |  The maximum number of bytes for a Dimension name.  |  60 bytes  | 
|  Measure name length  |  The maximum number of bytes for a Measure name.  |  256 bytes  | 
|  Database name length  |  The maximum number of bytes for a Database name.  |  256 bytes  | 
|  Table name length  |  The maximum number of bytes for a Table name.  |  256 bytes  | 
|  QueryString length in KiB  |  The maximum length (in KiB) of a query string in UTF-8 encoded characters for a query.  |  256  | 
|  Execution duration for queries in hours  |  The maximum execution duration (in hours) for a query. Queries that take longer will timeout.  |  1  | 
| Query Insights | The maximum number of Query API requests allowed with query insights enabled per second per account, in the current Region. | 1 | 
|  Metadata size for query result  |  The maximum metadata size for a query result.  |  100 Kilobytes  | 
|  Data size for query result  |  The maximum data size for a query result.  |  5 Gigabytes  | 
|  Measures per multi-measure record  |  The maximum number of measures per multi-measure record.  |  256  | 
|  Measure value size per multi-measure record  |  The maximum size of measure values per multi-measure record.  |  2048  | 
|  Unique measures across multi-measure records per table  |  The unique measures in all the multi-measure records defined in a single table.  |  1024  | 
| Timestream Compute Units (TCUs) per account | The default maximum TCUs per account. | 200 | 
| Maximum Provisioned Timestream Compute Units (TCUs) per account. Provisioned TCU is available only in the Asia Pacific (Mumbai) region.  | The maximum number of TCUs you can provision in your account. | 1000 | 
| maxQueryTCU | The maximum query TCUs you can set for your account. | 1000 | 

## Supported data types
<a name="limits.datatypes"></a>

The following table describes the supported data types for measure and dimension values.


| Description | Timestream for LiveAnalytics value | 
| --- | --- | 
|  Supported data types for measure values.  |   Big int, double, string, boolean, MULTI, Timestamp   | 
|  Supported data types for dimension values.  |   String   | 

## Batch load
<a name="limits.batch-load"></a>

The current quotas, also referred to as limits, within batch load are as follows.


| Description | Timestream for LiveAnalytics value | 
| --- | --- | 
|  Max batch load task size  |  Max batch load task size cannot exceed 100 GB.  | 
|  Files quantity  |  A batch load task cannot have more than 100 files.  | 
|  Maximum file size  |  Maximum file size in a batch load task cannot exceed 5 GB.  | 
|  CSV file row size  |  A row in a CSV file cannot exceed 16 MB. This is a hard limit which cannot be increased.  | 
|  Active batch load tasks  |  A table cannot have more than 5 active batch load tasks and an account cannot have more than 10 active batch load tasks. Timestream for LiveAnalytics will throttle new batch load tasks until more resources are available.  | 

## Naming constraints
<a name="limits.naming"></a>

The following table describes naming constraints.


| Description | Timestream for LiveAnalytics value | 
| --- | --- | 
|  The maximum length of a dimension name.  |   60 bytes   | 
|  The maximum length of a measure name.  |   256 bytes   | 
|  The maximum length of a table name or database name.  |   256 bytes   | 
|  Table and Database Name  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html)  Table and database names are compared using UTF-8 binary representation. This means that comparison for ASCII characters is case sensitive.   | 
|  Measure Name  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html)  Table and database names are compared using UTF-8 binary representation. This means that comparison for ASCII characters is case sensitive.   | 
|  Dimension Name  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html)  Dimension and measure names are compared using UTF-8 binary representation. This means that comparison for ASCII characters is case sensitive.   | 
| All Column Names | Column names can not be duplicated. Since multi-measure records represent dimensions and measures as columns, the name for a dimension can not be the same as the name for a measure. Names are case sensitive. | 

## Reserved keywords
<a name="limits.reserved"></a>

 All of the following are reserved keywords: 
+ ALTER 
+ AND 
+ AS 
+ BETWEEN 
+ BY 
+ CASE 
+ CAST 
+ CONSTRAINT 
+ CREATE 
+ CROSS 
+ CUBE 
+ CURRENT\$1DATE
+ CURRENT\$1TIME 
+ CURRENT\$1TIMESTAMP 
+ CURRENT\$1USER 
+ DEALLOCATE 
+ DELETE 
+ DESCRIBE 
+ DISTINCT 
+ DROP
+ ELSE 
+ END 
+ ESCAPE 
+ EXCEPT 
+ EXECUTE 
+ EXISTS 
+ EXTRACT 
+ FALSE 
+ FOR 
+ FROM 
+ FULL 
+ GROUP
+ GROUPING 
+ HAVING 
+ IN 
+ INNER 
+ INSERT 
+ INTERSECT 
+ INTO 
+ IS 
+ JOIN 
+ LEFT 
+ LIKE
+ LOCALTIME 
+ LOCALTIMESTAMP 
+ NATURAL 
+ NORMALIZE 
+ NOT 
+ NULL 
+ ON 
+ OR 
+ ORDER 
+ OUTER 
+ PREPARE
+ RECURSIVE 
+ RIGHT 
+ ROLLUP 
+ SELECT 
+ TABLE 
+ THEN 
+ TRUE 
+ UESCAPE 
+ UNION 
+ UNNEST 
+ USING 
+ VALUES
+ WHEN 
+ WHERE 
+ WITH

## System identifiers
<a name="limits.system_identifier"></a>

 We reserve column names "measure\$1value", "ts\$1non\$1existent\$1col" and "time" to be Timestream for LiveAnalytics system identifiers. Additionally, column names may not start with "ts\$1" or "measure\$1name". System identifiers are case sensitive. Identifiers compared using UTF-8 binary representation. This means that comparison for identifiers is case sensitive. 

**Note**  
System identifiers may not be used for dimension or measure names. We recommend you do not use system identifiers for database or table names.

## UNLOAD
<a name="limits.export-unload"></a>

For limits related to the `UNLOAD` command, see [Using UNLOAD to export query results to S3 from Timestream](https://docs.aws.amazon.com/timestream/latest/developerguide/export-unload.html).

# Query language reference
<a name="reference"></a>

**Note**  
This query language reference includes the following third-party documentation from the [Trino Software Foundation](https://trino.io/foundation.html) (formerly Presto Software Foundation), which is licensed under the Apache License, Version 2.0. You may not use this file except in compliance with this license. To get a copy of the Apache License, Version 2.0, see the [Apache website](http://www.apache.org/licenses/LICENSE-2.0).

Timestream for LiveAnalytics supports a rich query language for working with your data. You can see the available data types, operators, functions and constructs below.

You can also get started right away with Timestream's query language in the [Sample queries](sample-queries.md) section.

**Topics**
+ [Supported data types](supported-data-types.md)
+ [Built-in time series functionality](timeseries-specific-constructs.md)
+ [SQL support](supported-sql-constructs.md)
+ [Logical operators](logical-operators.md)
+ [Comparison operators](comparison-operators.md)
+ [Comparison functions](comparison-functions.md)
+ [Conditional expressions](conditional-expressions.md)
+ [Conversion functions](conversion-functions.md)
+ [Mathematical operators](mathematical-operators.md)
+ [Mathematical functions](mathematical-functions.md)
+ [String operators](string-operators.md)
+ [String functions](string-functions.md)
+ [Array operators](array-operators.md)
+ [Array functions](array-functions.md)
+ [Bitwise functions](bitwise-functions.md)
+ [Regular expression functions](regex-functions.md)
+ [Date / time operators](date-time-operators.md)
+ [Date / time functions](date-time-functions.md)
+ [Aggregate functions](aggregate-functions.md)
+ [Window functions](window-functions.md)
+ [Sample queries](sample-queries.md)

# Supported data types
<a name="supported-data-types"></a>

Timestream for LiveAnalytics's query language supports the following data types.

**Note**  
Data types supported for writes are described in [Data types](https://docs.aws.amazon.com/timestream/latest/developerguide/writes.html#writes.data-types).


| Data type | Description | 
| --- | --- | 
|  `int`  |  Represents a 32-bit integer.  | 
|  `bigint`  |  Represents a 64-bit signed integer.  | 
|  `boolean`  |  One of the two truth values of logic, `True` and `False`.  | 
|  `double`  |  Represents a 64-bit variable-precision data type. Implements [IEEE Standard 754 for Binary Floating-Point Arithmetic](https://standards.ieee.org/standard/754-2019.html).  The query language is for reading data. There are functions for `Infinity` and `NaN` double values which can be used in queries. But you cannot write those values to Timestream.   | 
|  `varchar`  |  Variable length character data with a maximum size of 2KB.  | 
|  `array[T,...]`  |  Contains one or more elements of a specified data type *T*, where *T* can be any of the data types supported in Timestream.  | 
|   `row(T,...)`   |  Contains one or more named fields of data type *T*. The fields may be of any data type supported by Timestream, and are accessed with the dot field reference operator: <pre>.</pre>  | 
|  `date`  |  Represents a date in the form `YYYY-MM-DD`. where *YYYY* is the year, *MM* is the month, and *DD* is the day, respectively. The supported range is from `1970-01-01` to `2262-04-11`.   *Example:*  <pre>1971-02-03</pre>  | 
|  `time`  |  Represents the time of day in [UTC](https://en.wikipedia.org/wiki/Coordinated_Universal_Time). The `time` datatype is represented in the form `HH.MM.SS.sssssssss.` Supports nanosecond precision.   *Example:*  <pre>17:02:07.496000000</pre>  | 
|  `timestamp`  |  Represents an instance in time using nanosecond precision time in UTC. `YYYY-MM-DD hh:mm:ss.sssssssss` Query supports timestamps in the range `1677-09-21 00:12:44.000000000` to `2262-04-11 23:47:16.854775807`.  | 
|  `interval`  |  Represents an interval of time as a string literal `Xt`, composed of two parts, *X* and *t*.  *X* is an numeric value greater than or equal to `0`, and *t* is a unit of time like second or hour. The unit is not pluralized. The unit of time *t* is must be one of the following string literals:  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/supported-data-types.html)  *Examples:*  <pre>17s</pre> <pre>12second</pre> <pre>21hour</pre> <pre>2d</pre>  | 
|  `timeseries[row(timestamp, T,...)]`  |  Represents the values of a measure recorded over a time interval as an `array` composed of `row` objects. Each `row` contains a `timestamp` and one or more measure values of data type *T*, where *T* can be any one of `bigint`, `boolean`, `double`, or `varchar`. Rows are assorted in ascending order by `timestamp`. The *timeseries* datatype represents the values of a measure over time.  | 
|  `unknown`  |  Represents null data.  | 

# Built-in time series functionality
<a name="timeseries-specific-constructs"></a>

Timestream for LiveAnalytics provides built-in time series functionality that treat time series data as a first class concept.

Built-in time series functionality can be divided into two categories: views and functions.

You can read about each construct below.

**Topics**
+ [Timeseries views](timeseries-specific-constructs.views.md)
+ [Time series functions](timeseries-specific-constructs.functions.md)

# Timeseries views
<a name="timeseries-specific-constructs.views"></a>

Timestream for LiveAnalytics supports the following functions for transforming your data to the `timeseries` data type:

**Topics**
+ [CREATE\$1TIME\$1SERIES](#timeseries-specific-constructs.views.CREATE_TIME_SERIES)
+ [UNNEST](#timeseries-specific-constructs.views.UNNEST)

## CREATE\$1TIME\$1SERIES
<a name="timeseries-specific-constructs.views.CREATE_TIME_SERIES"></a>

 **CREATE\$1TIME\$1SERIES** is an aggregation function that takes all the raw measurements of a time series (time and measure values) and returns a timeseries data type. The syntax of this function is as follows: 

```
CREATE_TIME_SERIES(time, measure_value::<data_type>)
```

 where `<data_type>` is the data type of the measure value and can be one of bigint, boolean, double, or varchar. The second parameter cannot be null.

Consider the CPU utilization of EC2 instances stored in a table named **metrics** as shown below:


| Time | region | az | vpc | instance\$1id | measure\$1name | measure\$1value::double | 
| --- | --- | --- | --- | --- | --- | --- | 
|  2019-12-04 19:00:00.000000000  |  us-east-1  |  us-east-1d  |  vpc-1a2b3c4d  |  i-1234567890abcdef0  |  cpu\$1utilization  |  35.0  | 
|  2019-12-04 19:00:01.000000000  |  us-east-1  |  us-east-1d  |  vpc-1a2b3c4d  |  i-1234567890abcdef0  |  cpu\$1utilization  |  38.2  | 
|  2019-12-04 19:00:02.000000000  |  us-east-1  |  us-east-1d  |  vpc-1a2b3c4d  |  i-1234567890abcdef0  |  cpu\$1utilization  |  45.3  | 
|  2019-12-04 19:00:00.000000000  |  us-east-1  |  us-east-1d  |  vpc-1a2b3c4d  |  i-1234567890abcdef1  |  cpu\$1utilization  |  54.1  | 
|  2019-12-04 19:00:01.000000000  |  us-east-1  |  us-east-1d  |  vpc-1a2b3c4d  |  i-1234567890abcdef1  |  cpu\$1utilization  |  42.5  | 
|  2019-12-04 19:00:02.000000000  |  us-east-1  |  us-east-1d  |  vpc-1a2b3c4d  |  i-1234567890abcdef1  |  cpu\$1utilization  |  33.7  | 

Running the query:

```
SELECT region, az, vpc, instance_id, CREATE_TIME_SERIES(time, measure_value::double) as cpu_utilization FROM metrics
    WHERE measure_name=’cpu_utilization’
    GROUP BY region, az, vpc, instance_id
```

will return all series that have `cpu_utilization` as a measure value. In this case, we have two series: 


| region | az | vpc | instance\$1id | cpu\$1utilization | 
| --- | --- | --- | --- | --- | 
|  us-east-1  |  us-east-1d  |  vpc-1a2b3c4d  |  i-1234567890abcdef0  |  [\$1time: 2019-12-04 19:00:00.000000000, measure\$1value::double: 35.0\$1, \$1time: 2019-12-04 19:00:01.000000000, measure\$1value::double: 38.2\$1, \$1time: 2019-12-04 19:00:02.000000000, measure\$1value::double: 45.3\$1]  | 
|  us-east-1  |  us-east-1d  |  vpc-1a2b3c4d  |  i-1234567890abcdef1  |  [\$1time: 2019-12-04 19:00:00.000000000, measure\$1value::double: 35.1\$1, \$1time: 2019-12-04 19:00:01.000000000, measure\$1value::double: 38.5\$1, \$1time: 2019-12-04 19:00:02.000000000, measure\$1value::double: 45.7\$1]  | 

## UNNEST
<a name="timeseries-specific-constructs.views.UNNEST"></a>

 `UNNEST` is a table function that enables you to transform `timeseries` data into the flat model. The syntax is as follows: 

 `UNNEST` transforms a `timeseries` into two columns, namely, `time` and `value`. You can also use aliases with UNNEST as shown below: 

```
UNNEST(timeseries) AS <alias_name> (time_alias, value_alias)
```

where `<alias_name>` is the alias for the flat table, `time_alias` is the alias for the `time` column and `value_alias` is the alias for the `value` column.

For example, consider the scenario where some of the EC2 instances in your fleet are configured to emit metrics at a 5 second interval, others emit metrics at a 15 second interval, and you need the average metrics for all instances at a 10 second granularity for the past 6 hours. To get this data, you transform your metrics to the time series model using **CREATE\$1TIME\$1SERIES**. You can then use **INTERPOLATE\$1LINEAR** to get the missing values at 10 second granularity. Next, you transform the data back to the flat model using **UNNEST**, and then use **AVG** to get the average metrics across all instances.

```
WITH interpolated_timeseries AS (
    SELECT region, az, vpc, instance_id,
        INTERPOLATE_LINEAR(
            CREATE_TIME_SERIES(time, measure_value::double),
                SEQUENCE(ago(6h), now(), 10s)) AS interpolated_cpu_utilization
    FROM timestreamdb.metrics 
    WHERE measure_name= ‘cpu_utilization’ AND time >= ago(6h)
    GROUP BY region, az, vpc, instance_id
)
SELECT region, az, vpc, instance_id, avg(t.cpu_util)
FROM interpolated_timeseries
CROSS JOIN UNNEST(interpolated_cpu_utilization) AS t (time, cpu_util)
GROUP BY region, az, vpc, instance_id
```

 The query above demonstrates the use of **UNNEST** with an alias. Below is an example of the same query without using an alias for **UNNEST**: 

```
WITH interpolated_timeseries AS (
    SELECT region, az, vpc, instance_id,
        INTERPOLATE_LINEAR(
            CREATE_TIME_SERIES(time, measure_value::double),
                SEQUENCE(ago(6h), now(), 10s)) AS interpolated_cpu_utilization
    FROM timestreamdb.metrics 
    WHERE measure_name= ‘cpu_utilization’ AND time >= ago(6h)
    GROUP BY region, az, vpc, instance_id
)
SELECT region, az, vpc, instance_id, avg(value)
FROM interpolated_timeseries
CROSS JOIN UNNEST(interpolated_cpu_utilization)
GROUP BY region, az, vpc, instance_id
```

# Time series functions
<a name="timeseries-specific-constructs.functions"></a>

Amazon Timestream for LiveAnalytics supports timeseries functions, such as derivatives, integrals, and correlations, as well as others, to derive deeper insights from your time series data. This section provides usage information for each of these functions, as well as sample queries. Select a topic below to learn more. 

**Topics**
+ [Interpolation functions](timeseries-specific-constructs.functions.interpolation.md)
+ [Derivatives functions](timeseries-specific-constructs.functions.derivatives.md)
+ [Integral functions](timeseries-specific-constructs.functions.integrals.md)
+ [Correlation functions](timeseries-specific-constructs.functions.correlation.md)
+ [Filter and reduce functions](timeseries-specific-constructs.functions.filter-reduce.md)

# Interpolation functions
<a name="timeseries-specific-constructs.functions.interpolation"></a>

If your time series data is missing values for events at certain points in time, you can estimate the values of those missing events using interpolation. Amazon Timestream supports four variants of interpolation: linear interpolation, cubic spline interpolation, last observation carried forward (locf) interpolation, and constant interpolation. This section provides usage information for the Timestream for LiveAnalytics interpolation functions, as well as sample queries. 



## Usage information
<a name="w2aab7c59c13c13c11b7"></a>


| Function | Output data type | Description | 
| --- | --- | --- | 
|  `interpolate_linear(timeseries, array[timestamp])`  |  timeseries  |  Fills in missing data using [linear interpolation](https://wikipedia.org/wiki/Linear_interpolation).  | 
|  `interpolate_linear(timeseries, timestamp)`  |  double  |  Fills in missing data using [linear interpolation](https://wikipedia.org/wiki/Linear_interpolation).  | 
|  `interpolate_spline_cubic(timeseries, array[timestamp])`  |  timeseries  |  Fills in missing data using [cubic spline interpolation](https://wikiversity.org/wiki/Cubic_Spline_Interpolation#:~:text=Cubic%20spline%20interpolation%20is%20a,Lagrange%20polynomial%20and%20Newton%20polynomial.).  | 
|  `interpolate_spline_cubic(timeseries, timestamp)`  |  double  |  Fills in missing data using [cubic spline interpolation](https://wikiversity.org/wiki/Cubic_Spline_Interpolation#:~:text=Cubic%20spline%20interpolation%20is%20a,Lagrange%20polynomial%20and%20Newton%20polynomial.).  | 
|  `interpolate_locf(timeseries, array[timestamp])`  |  timeseries  |  Fills in missing data using the last sampled value.  | 
|  `interpolate_locf(timeseries, timestamp)`  |  double  |  Fills in missing data using the last sampled value.  | 
|  `interpolate_fill(timeseries, array[timestamp], double)`  |  timeseries  |  Fills in missing data using a constant value.  | 
|  `interpolate_fill(timeseries, timestamp, double)`  |  double  |  Fills in missing data using a constant value.  | 

## Query examples
<a name="w2aab7c59c13c13c11b9"></a>

**Example**  
Find the average CPU utilization binned at 30 second intervals for a specific EC2 host over the past 2 hours, filling in the missing values using linear interpolation:  

```
WITH binned_timeseries AS (
SELECT hostname, BIN(time, 30s) AS binned_timestamp, ROUND(AVG(measure_value::double), 2) AS avg_cpu_utilization
FROM "sampleDB".DevOps
WHERE measure_name = 'cpu_utilization'
    AND hostname = 'host-Hovjv'
    AND time > ago(2h)
GROUP BY hostname, BIN(time, 30s)
), interpolated_timeseries AS (
SELECT hostname,
    INTERPOLATE_LINEAR(
        CREATE_TIME_SERIES(binned_timestamp, avg_cpu_utilization),
            SEQUENCE(min(binned_timestamp), max(binned_timestamp), 15s)) AS interpolated_avg_cpu_utilization
FROM binned_timeseries
GROUP BY hostname
)
SELECT time, ROUND(value, 2) AS interpolated_cpu
FROM interpolated_timeseries
CROSS JOIN UNNEST(interpolated_avg_cpu_utilization)
```

**Example**  
Find the average CPU utilization binned at 30 second intervals for a specific EC2 host over the past 2 hours, filling in the missing values using interpolation based on the last observation carried forward:  

```
WITH binned_timeseries AS (
SELECT hostname, BIN(time, 30s) AS binned_timestamp, ROUND(AVG(measure_value::double), 2) AS avg_cpu_utilization
FROM "sampleDB".DevOps
WHERE measure_name = 'cpu_utilization'
    AND hostname = 'host-Hovjv'
    AND time > ago(2h)
GROUP BY hostname, BIN(time, 30s)
), interpolated_timeseries AS (
SELECT hostname,
    INTERPOLATE_LOCF(
        CREATE_TIME_SERIES(binned_timestamp, avg_cpu_utilization),
            SEQUENCE(min(binned_timestamp), max(binned_timestamp), 15s)) AS interpolated_avg_cpu_utilization
FROM binned_timeseries
GROUP BY hostname
)
SELECT time, ROUND(value, 2) AS interpolated_cpu
FROM interpolated_timeseries
CROSS JOIN UNNEST(interpolated_avg_cpu_utilization)
```

# Derivatives functions
<a name="timeseries-specific-constructs.functions.derivatives"></a>

Derivatives are used calculate the rate of change for a given metric and can be used to proactively respond to an event. For example, suppose you calculate the derivative of the CPU utilization of EC2 instances over the past 5 minutes, and you notice a significant positive derivative. This can be indicative of increased demand on your workload, so you may decide want to spin up more EC2 instances to better handle your workload. 

Amazon Timestream supports two variants of derivative functions. This section provides usage information for the Timestream for LiveAnalytics derivative functions, as well as sample queries. 



## Usage information
<a name="w2aab7c59c13c13c13b9"></a>


| Function | Output data type | Description | 
| --- | --- | --- | 
|  `derivative_linear(timeseries, interval)`  |  timeseries  |  Calculates the [derivative](https://wikipedia.org/wiki/Derivative) of each point in the `timeseries` for the specified `interval`.  | 
|  `non_negative_derivative_linear(timeseries, interval)`  |  timeseries  |  Same as `derivative_linear(timeseries, interval)`, but only returns positive values.  | 

## Query examples
<a name="w2aab7c59c13c13c13c11"></a>

**Example**  
Find the rate of change in the CPU utilization every 5 minutes over the past 1 hour:  

```
SELECT DERIVATIVE_LINEAR(CREATE_TIME_SERIES(time, measure_value::double), 5m) AS result 
FROM “sampleDB”.DevOps 
WHERE measure_name = 'cpu_utilization' 
AND hostname = 'host-Hovjv' and time > ago(1h) 
GROUP BY hostname, measure_name
```

**Example**  
Calculate the rate of increase in errors generated by one or more microservices:  

```
WITH binned_view as (
    SELECT bin(time, 5m) as binned_timestamp, ROUND(AVG(measure_value::double), 2) as value            
    FROM “sampleDB”.DevOps  
    WHERE micro_service = 'jwt'  
    AND time > ago(1h) 
    AND measure_name = 'service_error'
    GROUP BY bin(time, 5m)
)
SELECT non_negative_derivative_linear(CREATE_TIME_SERIES(binned_timestamp, value), 1m) as rateOfErrorIncrease
FROM binned_view
```

# Integral functions
<a name="timeseries-specific-constructs.functions.integrals"></a>

You can use integrals to find the area under the curve per unit of time for your time series events. As an example, suppose you're tracking the volume of requests received by your application per unit of time. In this scenario, you can use the integral function to determine the total volume of requests served per specified interval over a specific time period.

Amazon Timestream supports one variant of integral functions. This section provides usage information for the Timestream for LiveAnalytics integral function, as well as sample queries. 



## Usage information
<a name="w2aab7c59c13c13c15b9"></a>


| Function | Output data type | Description | 
| --- | --- | --- | 
|  `integral_trapezoidal(timeseries(double))` `integral_trapezoidal(timeseries(double), interval day to second)` `integral_trapezoidal(timeseries(bigint))` `integral_trapezoidal(timeseries(bigint), interval day to second)` `integral_trapezoidal(timeseries(integer), interval day to second)` `integral_trapezoidal(timeseries(integer))`  |  double  |  Approximates the [integral](https://wikipedia.org/wiki/Integral) per the specified `interval day to second` for the `timeseries` provided, using the [trapezoidal rule](https://wikipedia.org/wiki/Trapezoidal_rule). The interval day to second parameter is optional and the default is `1s`. For more information about intervals, see [Interval and duration](date-time-functions.md#date-time-functions-interval-duration).  | 

## Query examples
<a name="w2aab7c59c13c13c15c11"></a>

**Example**  
Calculate the total volume of requests served per five minutes over the past hour by a specific host:  

```
SELECT INTEGRAL_TRAPEZOIDAL(CREATE_TIME_SERIES(time, measure_value::double), 5m) AS result FROM sample.DevOps 
WHERE measure_name = 'request' 
AND hostname = 'host-Hovjv' 
AND time > ago (1h) 
GROUP BY hostname, measure_name
```

# Correlation functions
<a name="timeseries-specific-constructs.functions.correlation"></a>

Given two similar length time series, correlation functions provide a correlation coefficient, which explains how the two time series trend over time. The correlation coefficient ranges from `-1.0` to `1.0`. `-1.0` indicates that the two time series trend in opposite directions at the same rate. whereas `1.0` indicates that the two timeseries trend in the same direction at the same rate. A value of `0` indicates no correlation between the two time series. For example, if the price of oil increases, and the stock price of an oil company increases, the trend of the price increase of oil and the price increase of the oil company will have a positive correlation coefficient. A high positive correlation coefficient would indicate that the two prices trend at a similar rate. Similarly, the correlation coefficient between bond prices and bond yields is negative, indicating that these two values trends in the opposite direction over time.

Amazon Timestream supports two variants of correlation functions. This section provides usage information for the Timestream for LiveAnalytics correlation functions, as well as sample queries. 



## Usage information
<a name="w2aab7c59c13c13c19c11"></a>


| Function | Output data type | Description | 
| --- | --- | --- | 
|  `correlate_pearson(timeseries, timeseries)`  |  double  |  Calculates [Pearson's correlation coefficient](https://wikipedia.org/wiki/Pearson_correlation_coefficient) for the two `timeseries`. The timeseries must have the same timestamps.  | 
|  `correlate_spearman(timeseries, timeseries)`  |  double  |  Calculates [Spearman's correlation coefficient](https://en.wikipedia.org/wiki/Spearman%27s_rank_correlation_coefficient) for the two `timeseries`. The timeseries must have the same timestamps.  | 

## Query examples
<a name="w2aab7c59c13c13c19c13"></a>

**Example**  

```
WITH cte_1 AS (
    SELECT INTERPOLATE_LINEAR(
        CREATE_TIME_SERIES(time, measure_value::double), 
        SEQUENCE(min(time), max(time), 10m)) AS result 
    FROM sample.DevOps 
    WHERE measure_name = 'cpu_utilization' 
    AND hostname = 'host-Hovjv' AND time > ago(1h) 
    GROUP BY hostname, measure_name
), 
cte_2 AS (
    SELECT INTERPOLATE_LINEAR(
        CREATE_TIME_SERIES(time, measure_value::double), 
        SEQUENCE(min(time), max(time), 10m)) AS result 
    FROM sample.DevOps 
    WHERE measure_name = 'cpu_utilization' 
    AND hostname = 'host-Hovjv' AND time > ago(1h) 
    GROUP BY hostname, measure_name
) 
SELECT correlate_pearson(cte_1.result, cte_2.result) AS result 
FROM cte_1, cte_2
```

# Filter and reduce functions
<a name="timeseries-specific-constructs.functions.filter-reduce"></a>

Amazon Timestream supports functions for performing filter and reduce operations on time series data. This section provides usage information for the Timestream for LiveAnalytics filter and reduce functions, as well as sample queries. 



## Usage information
<a name="w2aab7c59c13c13c23b7"></a>


| Function | Output data type | Description | 
| --- | --- | --- | 
|  `filter(timeseries(T), function(T, Boolean))`  |  timeseries(T)  |  Constructs a time series from an the input time series, using values for which the passed `function` returns `true`.  | 
|  `reduce(timeseries(T), initialState S, inputFunction(S, T, S), outputFunction(S, R))`  |  R  |  Returns a single value, reduced from the time series. The `inputFunction` will be invoked on each element in timeseries in order. In addition to taking the current element, inputFunction takes the current state (initially `initialState`) and returns the new state. The `outputFunction` will be invoked to turn the final state into the result value. The `outputFunction` can be an identity function.  | 

## Query examples
<a name="w2aab7c59c13c13c23b9"></a>

**Example**  
Construct a time series of CPU utilization of a host and filter points with measurement greater than 70:  

```
WITH time_series_view AS (
    SELECT INTERPOLATE_LINEAR(
        CREATE_TIME_SERIES(time, ROUND(measure_value::double,2)), 
            SEQUENCE(ago(15m), ago(1m), 10s)) AS cpu_user
    FROM sample.DevOps
    WHERE hostname = 'host-Hovjv' and measure_name = 'cpu_utilization'
        AND time > ago(30m)
    GROUP BY hostname
)
SELECT FILTER(cpu_user, x -> x.value > 70.0) AS cpu_above_threshold
from time_series_view
```

**Example**  
Construct a time series of CPU utilization of a host and determine the sum squared of the measurements:  

```
WITH time_series_view AS (
    SELECT INTERPOLATE_LINEAR(
        CREATE_TIME_SERIES(time, ROUND(measure_value::double,2)), 
            SEQUENCE(ago(15m), ago(1m), 10s)) AS cpu_user
    FROM sample.DevOps
    WHERE hostname = 'host-Hovjv' and measure_name = 'cpu_utilization'
        AND time > ago(30m)
    GROUP BY hostname
)
SELECT REDUCE(cpu_user,
    DOUBLE '0.0',
    (s, x) -> x.value * x.value + s,
    s -> s)
from time_series_view
```

**Example**  
Construct a time series of CPU utilization of a host and determine the fraction of samples that are above the CPU threshold:  

```
WITH time_series_view AS (
    SELECT INTERPOLATE_LINEAR(
        CREATE_TIME_SERIES(time, ROUND(measure_value::double,2)), 
            SEQUENCE(ago(15m), ago(1m), 10s)) AS cpu_user
    FROM sample.DevOps
    WHERE hostname = 'host-Hovjv' and measure_name = 'cpu_utilization'
        AND time > ago(30m)
    GROUP BY hostname
)
SELECT ROUND(
    REDUCE(cpu_user, 
      -- initial state 
      CAST(ROW(0, 0) AS ROW(count_high BIGINT, count_total BIGINT)),
      -- function to count the total points and points above a certain threshold
      (s, x) -> CAST(ROW(s.count_high + IF(x.value > 70.0, 1, 0), s.count_total + 1) AS ROW(count_high BIGINT, count_total BIGINT)),
      -- output function converting the counts to fraction above threshold
      s -> IF(s.count_total = 0, NULL, CAST(s.count_high AS DOUBLE) / s.count_total)), 
    4) AS fraction_cpu_above_threshold
from time_series_view
```

# SQL support
<a name="supported-sql-constructs"></a>

Timestream for LiveAnalytics supports some common SQL constructs. You can read more below.

**Topics**
+ [SELECT](supported-sql-constructs.SELECT.md)
+ [Subquery support](supported-sql-constructs.subquery-support.md)
+ [SHOW statements](supported-sql-constructs.SHOW.md)
+ [DESCRIBE statements](supported-sql-constructs.DESCRIBE.md)
+ [UNLOAD](supported-sql-constructs.UNLOAD.md)

# SELECT
<a name="supported-sql-constructs.SELECT"></a>

**SELECT** statements can be used to retrieve data from one or more tables. Timestream's query language supports the following syntax for **SELECT** statements:

```
[ WITH with_query [, ...] ]
            SELECT [ ALL | DISTINCT ] select_expr [, ...]
            [ function (expression) OVER (
            [ PARTITION BY partition_expr_list ]
            [ ORDER BY order_list ]
            [ frame_clause ] )
            [ FROM from_item [, ...] ]
            [ WHERE condition ]
            [ GROUP BY [ ALL | DISTINCT ] grouping_element [, ...] ]
            [ HAVING condition]
            [ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] select ]
            [ ORDER BY order_list ]
            [ LIMIT [ count | ALL ] ]
```

where 
+ `function (expression)` is one of the supported [window functions](window-functions.md).
+ `partition_expr_list` is:

  ```
  expression | column_name [, expr_list ]
  ```
+ `order_list` is:

  ```
  expression | column_name [ ASC | DESC ] 
  [ NULLS FIRST | NULLS LAST ]
  [, order_list ]
  ```
+ `frame_clause` is:

  ```
  ROWS | RANGE
  { UNBOUNDED PRECEDING | expression PRECEDING | CURRENT ROW } |
  {BETWEEN
  { UNBOUNDED PRECEDING | expression { PRECEDING | FOLLOWING } |
  CURRENT ROW}
  AND
  { UNBOUNDED FOLLOWING | expression { PRECEDING | FOLLOWING } |
  CURRENT ROW }}
  ```
+ `from_item` is one of:

  ```
  table_name [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
  from_item join_type from_item [ ON join_condition | USING ( join_column [, ...] ) ]
  ```
+ `join_type` is one of:

  ```
  [ INNER ] JOIN
  LEFT [ OUTER ] JOIN
  RIGHT [ OUTER ] JOIN
  FULL [ OUTER ] JOIN
  ```
+ `grouping_element` is one of:

  ```
  ()
  expression
  ```

# Subquery support
<a name="supported-sql-constructs.subquery-support"></a>

 Timestream supports subqueries in `EXISTS` and `IN` predicates. The `EXISTS` predicate determines if a subquery returns any rows. The `IN` predicate determines if values produced by the subquery match the values or expression of in IN clause. The Timestream query language supports correlated and other subqueries. 

```
SELECT t.c1
FROM (VALUES 1, 2, 3, 4, 5) AS t(c1)
WHERE EXISTS
(SELECT t.c2
 FROM (VALUES 1, 2, 3) AS t(c2)
 WHERE t.c1= t.c2
)
ORDER BY t.c1
```


| c1 | 
| --- | 
|  1  | 
|  2  | 
|  3  | 

```
SELECT t.c1
FROM (VALUES 1, 2, 3, 4, 5) AS t(c1)
WHERE t.c1 IN
(SELECT t.c2
 FROM (VALUES 2, 3, 4) AS t(c2)
)
ORDER BY t.c1
```


| c1 | 
| --- | 
|  2  | 
|  3  | 
|  4  | 

# SHOW statements
<a name="supported-sql-constructs.SHOW"></a>

You can view all the databases in an account by using the `SHOW DATABASES` statement. The syntax is as follows:

```
SHOW DATABASES [LIKE pattern]
```

where the `LIKE` clause can be used to filter database names.

You can view all the tables in an account by using the `SHOW TABLES` statement. The syntax is as follows:

```
SHOW TABLES [FROM database] [LIKE pattern]
```

where the `FROM` clause can be used to filter database names and the `LIKE` clause can be used to filter table names.

You can view all the measures for a table by using the `SHOW MEASURES` statement. The syntax is as follows:

```
SHOW MEASURES FROM database.table [LIKE pattern]
```

where the `FROM` clause will be used to specify the database and table name and the `LIKE` clause can be used to filter measure names.

# DESCRIBE statements
<a name="supported-sql-constructs.DESCRIBE"></a>

You can view the metadata for a table by using the `DESCRIBE` statement. The syntax is as follows:

```
DESCRIBE database.table
```

where `table` contains the table name. The describe statement returns the column names and data types for the table.

# UNLOAD
<a name="supported-sql-constructs.UNLOAD"></a>

Timestream for LiveAnalytics supports an `UNLOAD` command as an extension to its SQL support. Data types supported by `UNLOAD` are described in [Supported data types](supported-data-types.md). The `time` and `unknown` types do not apply to `UNLOAD`.

```
UNLOAD (SELECT statement)
 TO 's3://bucket-name/folder'
 WITH ( option = expression [, ...] )
```

where option is

```
{ partitioned_by = ARRAY[ col_name[,…] ] 
 | format = [ '{ CSV | PARQUET }' ] 
 | compression = [ '{ GZIP | NONE }' ]
 | encryption = [ '{ SSE_KMS | SSE_S3 }' ]
 | kms_key = '<string>'
 | field_delimiter ='<character>'
 | escaped_by = '<character>'
 | include_header = ['{true, false}']
 | max_file_size = '<value>'
}
```

SELECT statement  
The query statement used to select and retrieve data from one or more Timestream for LiveAnalytics tables.   

```
(SELECT column 1, column 2, column 3 from database.table
      where measure_name = "ABC" and timestamp between ago (1d) and now() )
```

TO clause  

```
TO 's3://bucket-name/folder'
```
or  

```
TO 's3://access-point-alias/folder'
```
The `TO` clause in the `UNLOAD` statement specifies the destination for the output of the query results. You need to provide the full path, including either Amazon S3 bucket-name or Amazon S3 access-point-alias with folder location on Amazon S3 where Timestream for LiveAnalytics writes the output file objects. The S3 bucket should be owned by the same account and in the same region. In addition to the query result set, Timestream for LiveAnalytics writes the manifest and metadata files to specified destination folder. 

PARTITIONED\$1BY clause  

```
partitioned_by = ARRAY [col_name[,…] , (default: none)
```
The `partitioned_by` clause is used in queries to group and analyze data at a granular level. When you export your query results to the S3 bucket, you can choose to partition the data based on one or more columns in the select query. When partitioning the data, the exported data is divided into subsets based on the partition column and each subset is stored in a separate folder. Within the results folder that contains your exported data, a sub-folder `folder/results/partition column = partition value/` is automatically created. However, note that partitioned columns are not included in the output file.   
`partitioned_by` is not a mandatory clause in the syntax. If you choose to export the data without any partitioning, you can exclude the clause in the syntax.   

**Example**  
Assuming you are monitoring clickstream data of your website and have 5 channels of traffic namely `direct`, `Social Media`, `Organic Search`, `Other`, and `Referral`. When exporting the data, you can choose to partition the data using the column `Channel`. Within your data folder, `s3://bucketname/results`, you will have five folders each with their respective channel name, for instance, `s3://bucketname/results/channel=Social Media/.` Within this folder you will find the data of all the customers that landed on your website through the `Social Media` channel. Similarly, you will have other folders for the remaining channels.
Exported data partitioned by Channel column  

![\[Folder structure showing channels: Direct, Organic search, Other, Referral, and Social media.\]](http://docs.aws.amazon.com/timestream/latest/developerguide/images/unload-results.png)


FORMAT  

```
format = [ '{ CSV | PARQUET }' , default: CSV
```
The keywords to specify the format of the query results written to your S3 bucket. You can export the data either as a comma separated value (CSV) using a comma (,) as the default delimiter or in the Apache Parquet format, an efficient open columnar storage format for analytics. 

COMPRESSION  

```
compression = [ '{ GZIP | NONE }' ], default: GZIP
```
You can compress the exported data using compression algorithm GZIP or have it uncompressed by specifying the `NONE` option.

ENCRYPTION  

```
encryption = [ '{ SSE_KMS | SSE_S3 }' ], default: SSE_S3
```
The output files on Amazon S3 are encrypted using your selected encryption option. In addition to your data, the manifest and metadata files are also encrypted based on your selected encryption option. We currently support SSE\$1S3 and SSE\$1KMS encryption. SSE\$1S3 is a server-side encryption with Amazon S3 encrypting the data using 256-bit advanced encryption standard (AES) encryption. SSE\$1KMS is a server-side encryption to encrypt data using customer-managed keys.

KMS\$1KEY  

```
kms_key = '<string>'
```
KMS Key is a customer-defined key to encrypt exported query results. KMS Key is securely managed by AWS Key Management Service (AWS KMS) and used to encrypt data files on Amazon S3.

FIELD\$1DELIMITER  

```
field_delimiter ='<character>' , default: (,)
```
When exporting the data in CSV format, this field specifies a single ASCII character that is used to separate fields in the output file, such as pipe character (\$1), a comma (,), or tab (/t). The default delimiter for CSV files is a comma character. If a value in your data contains the chosen delimiter, the delimiter will be quoted with a quote character. For instance, if the value in your data contains `Time,stream`, then this value will be quoted as `"Time,stream"` in the exported data. The quote character used by Timestream for LiveAnalytics is double quotes (").  
Avoid specifying the carriage return character (ASCII 13, hex `0D`, text '\$1r') or the line break character (ASCII 10, hex 0A, text '\$1n') as the `FIELD_DELIMITER` if you want to include headers in the CSV, since that will prevent many parsers from being able to parse the headers correctly in the resulting CSV output.

ESCAPED\$1BY  

```
escaped_by = '<character>', default: (\)
```
When exporting the data in CSV format, this field specifies the character that should be treated as an escape character in the data file written to S3 bucket. Escaping happens in the following scenarios:  

1. If the value itself contains the quote character (") then it will be escaped using an escape character. For example, if the value is `Time"stream`, where (\$1) is the configured escape character, then it will be escaped as `Time\"stream`. 

1. If the value contains the configured escape character, it will be escaped. For example, if the value is `Time\stream`, then it will be escaped as `Time\\stream`. 
If the exported output contains complex data type in the like Arrays, Rows or Timeseries, it will be serialized as a JSON string. Following is an example.    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/supported-sql-constructs.UNLOAD.html)

INCLUDE\$1HEADER  

```
include_header = 'true' , default: 'false'
```
When exporting the data in CSV format, this field lets you include column names as the first row of the exported CSV data files.  
The accepted values are 'true' and 'false' and the default value is 'false'. Text transformation options such as `escaped_by` and `field_delimiter` apply to headers as well.  
When including headers, it is important that you not select a carriage return character (ASCII 13, hex 0D, text '\$1r') or a line break character (ASCII 10, hex 0A, text '\$1n') as the `FIELD_DELIMITER`, since that will prevent many parsers from being able to parse the headers correctly in the resulting CSV output.

MAX\$1FILE\$1SIZE  

```
max_file_size = 'X[MB|GB]' , default: '78GB'
```
This field specifies the maximum size of the files that the `UNLOAD` statement creates in Amazon S3. The `UNLOAD` statement can create multiple files but the maximum size of each file written to Amazon S3 will be approximately what is specified in this field.  
The value of the field must be between 16 MB and 78 GB, inclusive. You can specify it in integer such as `12GB`, or in decimals such as `0.5GB` or `24.7MB`. The default value is 78 GB.  
The actual file size is approximated when the file is being written, so the actual maximum size may not be exactly equal to the number you specify.

# Logical operators
<a name="logical-operators"></a>

Timestream for LiveAnalytics supports the following logical operators.


| Operator | Description | Example | 
| --- | --- | --- | 
|  AND  |  True if both values are true  |  a AND b  | 
|  OR  |  True if either value is true  |  a OR b  | 
|  NOT  |  True if the value is false  |  NOT a  | 
+ The result of an `AND` comparison may be `NULL` if one or both sides of the expression are `NULL`. 
+ If at least one side of an `AND` operator is `FALSE` the expression evaluates to `FALSE`. 
+ The result of an `OR` comparison may be `NULL` if one or both sides of the expression are `NULL`. 
+ If at least one side of an `OR` operator is `TRUE` the expression evaluates to `TRUE`. 
+ The logical complement of `NULL` is `NULL`. 

The following truth table demonstrates the handling of `NULL` in `AND` and `OR`:


| A | B | A and b | A or b | 
| --- | --- | --- | --- | 
|  null  |  null  |  null  |  null  | 
|  false   |  null  |  false  |  null  | 
|  null  |  false  |  false  |  null  | 
|  true  |  null  |  null  |  true  | 
|  null  |  true  |  null  |  true  | 
|  false  |  false  |  false  |  false  | 
|  true  |  false  |  false  |  true  | 
|  false  |  true  |  false  |  true  | 
|  true  |  true  |  true  |  true  | 

The following truth table demonstrates the handling of NULL in NOT:


| A | Not a | 
| --- | --- | 
|  null  |  null  | 
|  true  |  false  | 
|  false  |  true  | 

# Comparison operators
<a name="comparison-operators"></a>

Timestream for LiveAnalytics supports the following comparison operators.


| Operator | Description | 
| --- | --- | 
|  <  |  Less than  | 
|  >  |  Greater than  | 
|  <=  |  Less than or equal to  | 
|  >=  |  Greater than or equal to  | 
|  =  |  Equal  | 
|  <>  |  Not equal  | 
|  \$1=  |  Not equal  | 

**Note**  
The `BETWEEN` operator tests if a value is within a specified range. The syntax is as follows:  

  ```
  BETWEEN min AND max
  ```
The presence of `NULL` in a `BETWEEN` or `NOT BETWEEN` statement will result in the statement evaluating to `NULL`.
`IS NULL `and `IS NOT NULL` operators test whether a value is null (undefined). Using `NULL` with `IS NULL` evaluates to true.
In SQL, a `NULL` value signifies an unknown value.

# Comparison functions
<a name="comparison-functions"></a>

Timestream for LiveAnalytics supports the following comparison functions.

**Topics**
+ [greatest()](comparison-functions.greatest.md)
+ [least()](comparison-functions.least.md)
+ [ALL(), ANY() and SOME()](comparison-functions.all-any-some.md)

# greatest()
<a name="comparison-functions.greatest"></a>

The **greatest()** function returns the largest of the provided values. It returns `NULL` if any of the provided values are `NULL`. The syntax is as follows.

```
greatest(value1, value2, ..., valueN) 
```

# least()
<a name="comparison-functions.least"></a>

The **least()** function returns the smallest of the provided values. It returns `NULL` if any of the provided values are `NULL`. The syntax is as follows.

```
least(value1, value2, ..., valueN) 
```

# ALL(), ANY() and SOME()
<a name="comparison-functions.all-any-some"></a>

The `ALL`, `ANY` and `SOME` quantifiers can be used together with comparison operators in the following way.


| Expression | Meaning | 
| --- | --- | 
|  A = ALL(...)  |  Evaluates to true when A is equal to all values.  | 
|  A <> ALL(...)  |  Evaluates to true when A does not match any value.  | 
|  A < ALL(...)  |  Evaluates to true when A is smaller than the smallest value.  | 
|  A = ANY(...)  |  Evaluates to true when A is equal to any of the values.   | 
|  A <> ANY(...)  |  Evaluates to true when A does not match one or more values.  | 
|  A < ANY(...)  |  Evaluates to true when A is smaller than the biggest value.  | 

## Examples and usage notes
<a name="comparison-functions.all-any-some.examples-usage"></a>

**Note**  
When using `ALL`, `ANY` or `SOME`, the keyword `VALUES` should be used if the comparison values are a list of literals. 

## Example: `ANY()`
<a name="w2aab7c59c21c11c11"></a>

An example of `ANY()` in a query statement as follows.

```
SELECT 11.7 = ANY (VALUES 12.0, 13.5, 11.7)
```

An alternative syntax for the same operation is as follows.

```
SELECT 11.7 = ANY (SELECT 12.0 UNION ALL SELECT 13.5 UNION ALL SELECT 11.7)
```

In this case, `ANY()` evaluates to `True`.

## Example: `ALL()`
<a name="w2aab7c59c21c11c13"></a>

An example of `ALL()` in a query statement as follows.

```
SELECT 17 < ALL (VALUES 19, 20, 15);
```

An alternative syntax for the same operation is as follows.

```
SELECT 17 < ALL (SELECT 19 UNION ALL SELECT 20 UNION ALL SELECT 15);
```

In this case, `ALL()` evaluates to `False`.

## Example: `SOME()`
<a name="w2aab7c59c21c11c15"></a>

An example of `SOME()` in a query statement as follows.

```
SELECT 50 >= SOME (VALUES 53, 77, 27);
```

An alternative syntax for the same operation is as follows.

```
SELECT 50 >= SOME (SELECT 53 UNION ALL SELECT 77 UNION ALL SELECT 27);
```

In this case, `SOME()` evaluates to `True`.

# Conditional expressions
<a name="conditional-expressions"></a>

Timestream for LiveAnalytics supports the following conditional expressions.

**Topics**
+ [The CASE statement](conditional-expressions.CASE.md)
+ [The IF statement](conditional-expressions.IF.md)
+ [The COALESCE statement](conditional-expressions.COALESCE.md)
+ [The NULLIF statement](conditional-expressions.NULLIF.md)
+ [The TRY statement](conditional-expressions.TRY.md)

# The CASE statement
<a name="conditional-expressions.CASE"></a>

The **CASE** statement searches each value expression from left to right until it finds one that equals `expression`. If it finds a match, the result for the matching value is returned. If no match is found, the result from the `ELSE` clause is returned if it exists; otherwise `null` is returned. The syntax is as follows:

```
CASE expression
    WHEN value THEN result
    [ WHEN ... ]
    [ ELSE result ]
END
```

 Timestream also supports the following syntax for **CASE** statements. In this syntax, the "searched" form evaluates each boolean condition from left to right until one is `true` and returns the matching result. If no conditions are `true`, the result from the `ELSE` clause is returned if it exists; otherwise `null` is returned. See below for the alternate syntax: 

```
CASE
    WHEN condition THEN result
    [ WHEN ... ]
    [ ELSE result ]
END
```

# The IF statement
<a name="conditional-expressions.IF"></a>

The **IF** statement evaluates a condition to be true or false and returns the appropriate value. Timestream supports the following two syntax representations for **IF**:

```
if(condition, true_value)
```

This syntax evaluates and returns `true_value` if condition is `true`; otherwise `null` is returned and `true_value` is not evaluated.

```
if(condition, true_value, false_value)
```

This syntax evaluates and returns `true_value` if condition is `true`, otherwise evaluates and returns `false_value`.

## Examples
<a name="conditional-expressions.IF.examples"></a>

```
SELECT
  if(true, 'example 1'),
  if(false, 'example 2'),
  if(true, 'example 3 true', 'example 3 false'),
  if(false, 'example 4 true', 'example 4 false')
```


| \$1col0 | \$1col1 | \$1col2 | \$1col3 | 
| --- | --- | --- | --- | 
|  `example 1`  |  `-` `null`  |  `example 3 true`  |  `example 4 false`  | 

# The COALESCE statement
<a name="conditional-expressions.COALESCE"></a>

 **COALESCE** returns the first non-null value in an argument list. The syntax is as follows:

```
coalesce(value1, value2[,...])
```

# The NULLIF statement
<a name="conditional-expressions.NULLIF"></a>

The **IF** statement evaluates a condition to be true or false and returns the appropriate value. Timestream supports the following two syntax representations for **IF**:

**NULLIF** returns null if `value1` equals `value2`; otherwise it returns `value1`. The syntax is as follows:

```
nullif(value1, value2)
```

# The TRY statement
<a name="conditional-expressions.TRY"></a>

The **TRY** function evaluates an expression and handles certain types of errors by returning `null`. The syntax is as follows:

```
try(expression)
```

# Conversion functions
<a name="conversion-functions"></a>

Timestream for LiveAnalytics supports the following conversion functions.

**Topics**
+ [cast()](#conversion-functions.cast)
+ [try\$1cast()](#conversion-functions.try-cast)

## cast()
<a name="conversion-functions.cast"></a>

 The syntax of the cast function to explicitly cast a value as a type is as follows.

```
cast(value AS type)
```

## try\$1cast()
<a name="conversion-functions.try-cast"></a>

Timestream for LiveAnalytics also supports the try\$1cast function that is similar to cast but returns null if cast fails. The syntax is as follows.

```
try_cast(value AS type)
```

# Mathematical operators
<a name="mathematical-operators"></a>

Timestream for LiveAnalytics supports the following mathematical operators.


| Operator | Description | 
| --- | --- | 
|  \$1  |  Addition  | 
|  -  |  Subtraction  | 
|  \$1  |  Multiplication  | 
|  /  |  Division (integer division performs truncation)  | 
|  %  |  Modulus (remainder)  | 

# Mathematical functions
<a name="mathematical-functions"></a>

Timestream for LiveAnalytics supports the following mathematical functions.


| Function | Output data type | Description | 
| --- | --- | --- | 
|  abs(x)  |  [same as input]  |  Returns the absolute value of x.  | 
|  cbrt(x)  |  double  |  Returns the cube root of x.  | 
|  ceiling(x) or ceil(x)  |  [same as input]  |  Returns x rounded up to the nearest integer.  | 
|  degrees(x)  |  double  |  Converts angle x in radians to degrees.  | 
|  e()  |  double  |  Returns the constant Euler's number.  | 
|  exp(x)  |  double  |  Returns Euler's number raised to the power of x.  | 
|  floor(x)  |  [same as input]  |  Returns x rounded down to the nearest integer.  | 
|  from\$1base(string,radix)  |  bigint  |  Returns the value of string interpreted as a base-radix number.  | 
|  ln(x)  |  double  |  Returns the natural logarithm of x.  | 
|  log2(x)  |  double  |  Returns the base 2 logarithm of x.  | 
|  log10(x)  |  double  |  Returns the base 10 logarithm of x.  | 
|  mod(n,m)   |  [same as input]  |  Returns the modulus (remainder) of n divided by m.  | 
|  pi()   |  double  |  Returns the constant Pi.  | 
|  pow(x, p) or power(x, p)  |  double  |  Returns x raised to the power of p.  | 
|  radians(x)  |  double  |  Converts angle x in degrees to radians.  | 
|  rand() or random()  |  double  |  Returns a pseudo-random value in the range 0.0 1.0.  | 
|  random(n)  |  [same as input]  |  Returns a pseudo-random number between 0 and n (exclusive).  | 
|  round(x)  |  [same as input]  |  Returns x rounded to the nearest integer.  | 
|  round(x,d)  |  [same as input]  |  Returns x rounded to d decimal places.  | 
|  sign(x)  |  [same as input]  |  Returns the signum function of x, that is: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/mathematical-functions.html) For double arguments, the function additionally returns: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/timestream/latest/developerguide/mathematical-functions.html)  | 
|  sqrt(x)   |  double  |  Returns the square root of x.  | 
|  to\$1base(x, radix)   |  varchar  |  Returns the base-radix representation of x.  | 
|  truncate(x)   |  double  |  Returns x rounded to integer by dropping digits after decimal point.  | 
|  acos(x)  |  double  |  Returns the arc cosine of x.  | 
|  asin(x)   |  double  |  Returns the arc sine of x.  | 
|  atan(x)   |  double  |  Returns the arc tangent of x.  | 
|  atan2(y, x)  |  double  |  Returns the arc tangent of y / x.  | 
|  cos(x)  |  double  |  Returns the cosine of x.  | 
|  cosh(x)  |  double  |  Returns the hyperbolic cosine of x.  | 
|  sin(x)   |  double  |  Returns the sine of x.  | 
|  tan(x)  |  double  |  Returns the tangent of x.  | 
|  tanh(x)  |  double  |  Returns the hyperbolic tangent of x.  | 
|  infinity()  |  double  |  Returns the constant representing positive infinity.  | 
|  is\$1finite(x)  |  boolean  |  Determine if x is finite.  | 
|  is\$1infinite(x)  |  boolean  |  Determine if x is infinite.  | 
|  is\$1nan(x)  |  boolean  |  Determine if x is not-a-number.  | 
|  nan()  |  double  |  Returns the constant representing not-a-number.  | 

# String operators
<a name="string-operators"></a>

Timestream for LiveAnalytics supports the `||` operator for concatenating one or more strings.

# String functions
<a name="string-functions"></a>

**Note**  
The input data type of these functions is assumed to be varchar unless otherwise specified.


| Function | Output data type | Description | 
| --- | --- | --- | 
|  chr(n)   |  varchar  |  Returns the Unicode code point n as a varchar.  | 
|  codepoint(x)   |  integer  |  Returns the Unicode code point of the only character of str.  | 
|  concat(x1, ..., xN)  |  varchar  |  Returns the concatenation of x1, x2, ..., xN.  | 
|  hamming\$1distance(x1,x2)   |  bigint  |  Returns the Hamming distance of x1 and x2, i.e. the number of positions at which the corresponding characters are different. Note that the two varchar inputs must have the same length.  | 
|  length(x)  |  bigint  |  Returns the length of x in characters.  | 
|  levenshtein\$1distance(x1, x2)   |  bigint  |  Returns the Levenshtein edit distance of x1 and x2, i.e. the minimum number of single-character edits (insertions, deletions or substitutions) needed to change x1 into x2.  | 
|  lower(x)  |  varchar  |  Converts x to lowercase.  | 
|  lpad(x1, bigint size, x2)  |  varchar  |  Left pads x1 to size characters with x2. If size is less than the length of x1, the result is truncated to size characters. size must not be negative and x2 must be non-empty.  | 
|  ltrim(x)  |  varchar  |  Removes leading whitespace from x.  | 
|  replace(x1, x2)  |  varchar  |  Removes all instances of x2 from x1.  | 
|  replace(x1, x2, x3)  |  varchar  |  Replaces all instances of x2 with x3 in x1.  | 
|  Reverse(x)   |  varchar  |  Returns x with the characters in reverse order.  | 
|  rpad(x1, bigint size, x2)  |  varchar  |  Right pads x1 to size characters with x2. If size is less than the length of x1, the result is truncated to size characters. size must not be negative and x2 must be non-empty.  | 
|  rtrim(x)  |  varchar  |  Removes trailing whitespace from x.  | 
|  split(x1, x2)  |  array(varchar)  |  Splits x1 on delimiter x2 and returns an array.  | 
|  split(x1, x2, bigint limit)  |  array(varchar)  |  Splits x1 on delimiter x2 and returns an array. The last element in the array always contain everything left in the x1. limit must be a positive number.  | 
|  split\$1part(x1, x2, bigint pos)   |  varchar  |  Splits x1 on delimiter x2 and returns the varchar field at pos. Field indexes start with 1. If pos is larger than the number of fields, then null is returned.  | 
|  strpos(x1, x2)   |  bigint  |  Returns the starting position of the first instance of x2 in x1. Positions start with 1. If not found, 0 is returned.  | 
|  strpos(x1, x2,bigint instance)   |  bigint  |  Returns the position of the Nth instance of x2 in x1. Instance must be a positive number. Positions start with 1. If not found, 0 is returned.  | 
|  strrpos(x1, x2)   |  bigint  |  Returns the starting position of the last instance of x2 in x1. Positions start with 1. If not found, 0 is returned.  | 
|  strrpos(x1, x2, bigint instance)   |  bigint  |  Returns the position of the Nth instance of x2 in x1 starting from the end of x1. instance must be a positive number. Positions start with 1. If not found, 0 is returned.  | 
|  position(x2 IN x1)   |  bigint  |  Returns the starting position of the first instance of x2 in x1. Positions start with 1. If not found, 0 is returned.  | 
|  substr(x, bigint start)   |  varchar  |  Returns the rest of x from the starting position start. Positions start with 1. A negative starting position is interpreted as being relative to the end of x.  | 
|  substr(x, bigint start, bigint len)   |  varchar  |  Returns a substring from x of length len from the starting position start. Positions start with 1. A negative starting position is interpreted as being relative to the end of x.  | 
|  trim(x)   |  varchar  |  Removes leading and trailing whitespace from x.  | 
|  upper(x)   |  varchar  |  Converts x to uppercase.  | 

# Array operators
<a name="array-operators"></a>

Timestream for LiveAnalytics supports the following array operators.


| Operator | Description | 
| --- | --- | 
|  []  |  Access an element of an array where the first index starts at 1.  | 
|  \$1\$1  |  Concatenate an array with another array or element of the same type.  | 

# Array functions
<a name="array-functions"></a>

Timestream for LiveAnalytics supports the following array functions.


| Function | Output data type | Description | 
| --- | --- | --- | 
|  array\$1distinct(x)  |  array  |  Remove duplicate values from the array x. <pre>SELECT array_distinct(ARRAY[1,2,2,3])</pre> Example result: `[ 1,2,3 ]`  | 
|  array\$1intersect(x, y)  |  array  |  Returns an array of the elements in the intersection of x and y, without duplicates. <pre>SELECT array_intersect(ARRAY[1,2,3], ARRAY[3,4,5])</pre> Example result: `[ 3 ]`  | 
|  array\$1union(x, y)  |  array  |  Returns an array of the elements in the union of x and y, without duplicates. <pre>SELECT array_union(ARRAY[1,2,3], ARRAY[3,4,5])</pre> Example result: `[ 1,2,3,4,5 ]`  | 
|  array\$1except(x, y)  |  array  |  Returns an array of elements in x but not in y, without duplicates. <pre>SELECT array_except(ARRAY[1,2,3], ARRAY[3,4,5])</pre> Example result: `[ 1,2 ]`  | 
|  array\$1join(x, delimiter, null\$1replacement)   |  varchar  |  Concatenates the elements of the given array using the delimiter and an optional string to replace nulls. <pre>SELECT array_join(ARRAY[1,2,3], ';', '')</pre> Example result: `1;2;3`  | 
|  array\$1max(x)  |  same as array elements  |  Returns the maximum value of input array. <pre>SELECT array_max(ARRAY[1,2,3])</pre> Example result: `3`  | 
|  array\$1min(x)  |  same as array elements  |  Returns the minimum value of input array. <pre>SELECT array_min(ARRAY[1,2,3])</pre> Example result: `1`  | 
|  array\$1position(x, element)  |  bigint  |  Returns the position of the first occurrence of the element in array x (or 0 if not found). <pre>SELECT array_position(ARRAY[3,4,5,9], 5)</pre> Example result: `3`  | 
|  array\$1remove(x, element)  |  array  |  Remove all elements that equal element from array x. <pre>SELECT array_remove(ARRAY[3,4,5,9], 4)</pre> Example result: `[ 3,5,9 ]`  | 
|  array\$1sort(x)  |  array  |  Sorts and returns the array x. The elements of x must be orderable. Null elements will be placed at the end of the returned array. <pre>SELECT array_sort(ARRAY[6,8,2,9,3])</pre> Example result: `[ 2,3,6,8,9 ]`  | 
|  arrays\$1overlap(x, y)   |  boolean  |  Tests if arrays x and y have any non-null elements in common. Returns null if there are no non-null elements in common but either array contains null. <pre>SELECT arrays_overlap(ARRAY[6,8,2,9,3], ARRAY[6,8])</pre> Example result: `true`  | 
|  cardinality(x)  |  bigint  |  Returns the size of the array x. <pre>SELECT cardinality(ARRAY[6,8,2,9,3])</pre> Example result: `5`  | 
|  concat(array1, array2, ..., arrayN)  |  array  |  Concatenates the arrays array1, array2, ..., arrayN. <pre>SELECT concat(ARRAY[6,8,2,9,3], ARRAY[11,32], ARRAY[6,8,2,0,14])</pre> Example result: `[ 6,8,2,9,3,11,32,6,8,2,0,14 ]`  | 
|  element\$1at(array(E), index)  |  E  |  Returns element of array at given index. If index < 0, element\$1at accesses elements from the last to the first. <pre>SELECT element_at(ARRAY[6,8,2,9,3], 1)</pre> Example result: `6`  | 
|  repeat(element, count)   |  array  |  Repeat element for count times. <pre>SELECT repeat(1, 3)</pre> Example result: `[ 1,1,1 ]`  | 
|  reverse(x)  |  array  |  Returns an array which has the reversed order of array x. <pre>SELECT reverse(ARRAY[6,8,2,9,3])</pre> Example result: `[ 3,9,2,8,6 ]`  | 
|  sequence(start, stop)  |  array(bigint)  |  Generate a sequence of integers from start to stop, incrementing by 1 if start is less than or equal to stop, otherwise -1. <pre>SELECT sequence(3, 8)</pre> Example result: `[ 3,4,5,6,7,8 ]`  | 
|  sequence(start, stop, step)   |  array(bigint)  |  Generate a sequence of integers from start to stop, incrementing by step. <pre>SELECT sequence(3, 15, 2)</pre> Example result: `[ 3,5,7,9,11,13,15 ]`  | 
|  sequence(start, stop)   |  array(timestamp)  |  Generate a sequence of timestamps from start date to stop date, incrementing by 1 day. <pre>SELECT sequence('2023-04-02 19:26:12.941000000', '2023-04-06 19:26:12.941000000', 1d)</pre> Example result: `[ 2023-04-02 19:26:12.941000000,2023-04-03 19:26:12.941000000,2023-04-04 19:26:12.941000000,2023-04-05 19:26:12.941000000,2023-04-06 19:26:12.941000000 ]`  | 
|  sequence(start, stop, step)   |  array(timestamp)  |  Generate a sequence of timestamps from start to stop, incrementing by step. The data type of step is interval. <pre>SELECT sequence('2023-04-02 19:26:12.941000000', '2023-04-10 19:26:12.941000000', 2d)</pre> Example result: `[ 2023-04-02 19:26:12.941000000,2023-04-04 19:26:12.941000000,2023-04-06 19:26:12.941000000,2023-04-08 19:26:12.941000000,2023-04-10 19:26:12.941000000 ]`  | 
|  shuffle(x)  |  array  |  Generate a random permutation of the given array x. <pre>SELECT shuffle(ARRAY[6,8,2,9,3])</pre> Example result: `[ 6,3,2,9,8 ]`  | 
|  slice(x, start, length)  |  array  |  Subsets array x starting from index start (or starting from the end if start is negative) with a length of length. <pre>SELECT slice(ARRAY[6,8,2,9,3], 1, 3)</pre> Example result: `[ 6,8,2 ]`  | 
|  zip(array1, array2[, ...])  |  array(row)  |  Merges the given arrays, element-wise, into a single array of rows. If the arguments have an uneven length, missing values are filled with NULL. <pre>SELECT zip(ARRAY[6,8,2,9,3], ARRAY[15,24])</pre> Example result: `[ ( 6, 15 ),( 8, 24 ),( 2, - ),( 9, - ),( 3, - ) ]`  | 

# Bitwise functions
<a name="bitwise-functions"></a>

Timestream for LiveAnalytics supports the following bitwise functions.


| Function | Output data type | Description | 
| --- | --- | --- | 
| bit\$1count(bigint, bigint) | bigint (two's complement) |  Returns the count of bits in the first bigint parameter where the second parameter is a bit signed integer such as 8 or 64. <pre>SELECT bit_count(19, 8)</pre> Example result: `3` <pre>SELECT bit_count(19, 2)</pre> Example result: `Number must be representable with the bits specified. 19 can not be represented with 2 bits`   | 
| bitwise\$1and(bigint, bigint) | bigint (two's complement) |  Returns the bitwise AND of the bigint parameters. <pre>SELECT bitwise_and(12, 7)</pre> Example result: `4`  | 
| bitwise\$1not(bigint) | bigint (two's complement) |  Returns the bitwise NOT of the bigint parameter. <pre>SELECT bitwise_not(12)</pre> Example result: `-13`  | 
| bitwise\$1or(bigint, bigint) | bigint (two's complement) |  Returns the bitwise OR of the bigint parameters. <pre>SELECT bitwise_or(12, 7)</pre> Example result: `15`  | 
| bitwise\$1xor(bigint, bigint) | bigint (two's complement) |  Returns the bitwise XOR of the bigint parameters. <pre>SELECT bitwise_xor(12, 7)</pre> Example result: `11`  | 

# Regular expression functions
<a name="regex-functions"></a>

The regular expression functions in Timestream for LiveAnalytics support the [Java pattern syntax](http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html). Timestream for LiveAnalytics supports the following regular expression functions.


| Function | Output data type | Description | 
| --- | --- | --- | 
|  regexp\$1extract\$1all(string, pattern)  |  array(varchar)  |  Returns the substring(s) matched by the regular expression pattern in string. <pre>SELECT regexp_extract_all('example expect complex', 'ex\w')</pre> Example result: `[ exa,exp ]`  | 
|  regexp\$1extract\$1all(string, pattern, group)  |  array(varchar)  |  Finds all occurrences of the regular expression pattern in string and returns the [capturing group number](http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#gnumber) group. <pre>SELECT regexp_extract_all('example expect complex', '(ex)(\w)', 2)</pre> Example result: `[ a,p ]`  | 
|  regexp\$1extract(string, pattern)  |  varchar  |  Returns the first substring matched by the regular expression pattern in string. <pre>SELECT regexp_extract('example expect', 'ex\w')</pre> Example result: `exa`  | 
|  regexp\$1extract(string, pattern, group)   |  varchar  |  Finds the first occurrence of the regular expression pattern in string and returns the [capturing group number](http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#gnumber) group. <pre>SELECT regexp_extract('example expect', '(ex)(\w)', 2)</pre> Example result: `a`  | 
|  regexp\$1like(string, pattern)   |  boolean  |  Evaluates the regular expression pattern and determines if it is contained within string. This function is similar to the LIKE operator, except that the pattern only needs to be contained within string, rather than needing to match all of string. In other words, this performs a contains operation rather than a match operation. You can match the entire string by anchoring the pattern using ^ and \$1. <pre>SELECT regexp_like('example', 'ex')</pre> Example result: `true`  | 
|  regexp\$1replace(string, pattern)  |  varchar  |  Removes every instance of the substring matched by the regular expression pattern from string. <pre>SELECT regexp_replace('example expect', 'expect')</pre> Example result: `example`  | 
|  regexp\$1replace(string, pattern, replacement)   |  varchar  |  Replaces every instance of the substring matched by the regex pattern in string with replacement. Capturing groups can be referenced in replacement using \$1g for a numbered group or \$1\$1name\$1 for a named group. A dollar sign (\$1) may be included in the replacement by escaping it with a backslash (\$1\$1). <pre>SELECT regexp_replace('example expect', 'expect', 'surprise')</pre> Example result: `example surprise`  | 
|  regexp\$1replace(string, pattern, function)   |  varchar  |  Replaces every instance of the substring matched by the regular expression pattern in string using function. The [lambda expression](https://prestodb.io/docs/current/functions/lambda.html) function is invoked for each match with the capturing groups passed as an array. Capturing group numbers start at one; there is no group for the entire match (if you need this, surround the entire expression with parenthesis). <pre>SELECT regexp_replace('example', '(\w)', x -> upper(x[1]))</pre> Example result: `EXAMPLE`  | 
|  regexp\$1split(string, pattern)   |  array(varchar)  |  Splits string using the regular expression pattern and returns an array. Trailing empty strings are preserved. <pre>SELECT regexp_split('example', 'x')</pre> Example result: `[ e,ample ]`  | 

# Date / time operators
<a name="date-time-operators"></a>

**Note**  
Timestream for LiveAnalytics does not support negative time values. Any operation resulting in negative time results in error.

Timestream for LiveAnalytics supports the following operations on `timestamps`, `dates`, and `intervals`.


| Operator | Description | 
| --- | --- | 
|  \$1  |  Addition  | 
|  -  |  Subtraction  | 

**Topics**
+ [Operations](#date-time-operators-operations)
+ [Addition](#date-time-operators-addition)
+ [Subtraction](#date-time-operators-subtraction)

## Operations
<a name="date-time-operators-operations"></a>

The result type of an operation is based on the operands. Interval literals such as `1day` and `3s` can be used.

```
SELECT date '2022-05-21' + interval '2' day
```

```
SELECT date '2022-05-21' + 2d
```

```
SELECT date '2022-05-21' + 2day
```

Example result for each: `2022-05-23`

Interval units include `second`, `minute`, `hour`, `day`, `week`, `month`, and `year`. But in some cases not all are applicable. For example seconds, minutes, and hours can not be added to or subtracted from a date.

```
SELECT interval '4' year + interval '2' month
```

Example result: `4-2`

```
SELECT typeof(interval '4' year + interval '2' month)
```

Example result: `interval year to month`

Result type of interval operations may be `'interval year to month'` or `'interval day to second'` depending on the operands. Intervals can be added to or subtracted from `dates` and `timestamps`. But a `date` or `timestamp` cannot be added to or subtracted from a `date` or `timestamp`. To find intervals or durations related to dates or timestamps, see `date_diff` and related functions in [Interval and duration](date-time-functions.md#date-time-functions-interval-duration).

## Addition
<a name="date-time-operators-addition"></a>

**Example**  

```
SELECT date '2022-05-21' + interval '2' day
```
Example result: `2022-05-23`

**Example**  

```
SELECT typeof(date '2022-05-21' + interval '2' day)
```
Example result: `date`

**Example**  

```
SELECT interval '2' year + interval '4' month
```
Example result: `2-4`

**Example**  

```
SELECT typeof(interval '2' year + interval '4' month)
```
Example result: `interval year to month`

## Subtraction
<a name="date-time-operators-subtraction"></a>

**Example**  

```
SELECT timestamp '2022-06-17 01:00' - interval '7' hour
```
Example result: `2022-06-16 18:00:00.000000000`

**Example**  

```
SELECT typeof(timestamp '2022-06-17 01:00' - interval '7' hour)
```
Example result: `timestamp`

**Example**  

```
SELECT interval '6' day - interval '4' hour
```
Example result: `5 20:00:00.000000000`

**Example**  

```
SELECT typeof(interval '6' day - interval '4' hour)
```
Example result: `interval day to second`

# Date / time functions
<a name="date-time-functions"></a>

**Note**  
Timestream for LiveAnalytics does not support negative time values. Any operation resulting in negative time results in error.

Timestream for LiveAnalytics uses UTC timezone for date and time. Timestream supports the following functions for date and time.

**Topics**
+ [General and conversion](#date-time-functions-general)
+ [Interval and duration](#date-time-functions-interval-duration)
+ [Formatting and parsing](#date-time-functions-formatting-parsing)
+ [Extraction](#date-time-functions-extraction)

## General and conversion
<a name="date-time-functions-general"></a>

Timestream for LiveAnalytics supports the following general and conversion functions for date and time.


| Function | Output data type | Description | 
| --- | --- | --- | 
|  current\$1date  |  date  |  Returns current date in UTC. No parentheses used. <pre>SELECT current_date</pre> Example result: `2022-07-07`  This is also a reserved keyword. For a list of reserved keywords, see [Reserved keywords](ts-limits.md#limits.reserved).   | 
|  current\$1time  |  time  |  Returns current time in UTC. No parentheses used. <pre>SELECT current_time</pre> Example result: `17:41:52.827000000`  This is also a reserved keyword. For a list of reserved keywords, see [Reserved keywords](ts-limits.md#limits.reserved).   | 
|  current\$1timestamp or now()  |  timestamp  |  Returns current timestamp in UTC. <pre>SELECT current_timestamp</pre> Example result: `2022-07-07 17:42:32.939000000`  This is also a reserved keyword. For a list of reserved keywords, see [Reserved keywords](ts-limits.md#limits.reserved).   | 
|  current\$1timezone()  |  varchar The value will be 'UTC.'  |  Timestream uses UTC timezone for date and time. <pre>SELECT current_timezone()</pre> Example result: `UTC`  | 
|  date(varchar(x)), date(timestamp)  |  date  |  <pre>SELECT date(TIMESTAMP '2022-07-07 17:44:43.771000000')</pre> Example result: `2022-07-07`  | 
|  last\$1day\$1of\$1month(timestamp), last\$1day\$1of\$1month(date)  |  date  |  <pre>SELECT last_day_of_month(TIMESTAMP '2022-07-07 17:44:43.771000000')</pre> Example result: `2022-07-31`  | 
|  from\$1iso8601\$1timestamp(string)  |  timestamp  |  Parses the ISO 8601 timestamp into internal timestamp format. <pre>SELECT from_iso8601_timestamp('2022-06-17T08:04:05.000000000+05:00')</pre> Example result: `2022-06-17 03:04:05.000000000`  | 
|  from\$1iso8601\$1date(string)  |  date  |  Parses the ISO 8601 date string into internal timestamp format for UTC 00:00:00 of the specified date. <pre>SELECT from_iso8601_date('2022-07-17')</pre> Example result: `2022-07-17`  | 
|  to\$1iso8601(timestamp), to\$1iso8601(date)  |  varchar  |  Returns an ISO 8601 formatted string for the input. <pre>SELECT to_iso8601(from_iso8601_date('2022-06-17'))</pre> Example result: `2022-06-17`  | 
|  from\$1milliseconds(bigint)  |  timestamp  |  <pre>SELECT from_milliseconds(1)</pre> Example result: `1970-01-01 00:00:00.001000000`  | 
|  from\$1nanoseconds(bigint)  |  timestamp  |  <pre>select from_nanoseconds(300000001)</pre> Example result: `1970-01-01 00:00:00.300000001`  | 
|  from\$1unixtime(double)  |  timestamp  |  Returns a timestamp which corresponds to the provided unixtime. <pre>SELECT from_unixtime(1)</pre> Example result: `1970-01-01 00:00:01.000000000`  | 
|  localtime  |  time  |  Returns current time in UTC. No parentheses used. <pre>SELECT localtime</pre> Example result: `17:58:22.654000000`  This is also a reserved keyword. For a list of reserved keywords, see [Reserved keywords](ts-limits.md#limits.reserved).   | 
|  localtimestamp  |  timestamp  |  Returns current timestamp in UTC. No parentheses used. <pre>SELECT localtimestamp</pre> Example result: `2022-07-07 17:59:04.368000000`  This is also a reserved keyword. For a list of reserved keywords, see [Reserved keywords](ts-limits.md#limits.reserved).   | 
|  to\$1milliseconds(interval day to second), to\$1milliseconds(timestamp)  |  bigint  |  <pre>SELECT to_milliseconds(INTERVAL '2' DAY + INTERVAL '3' HOUR)</pre> Example result: `183600000` <pre>SELECT to_milliseconds(TIMESTAMP '2022-06-17 17:44:43.771000000')</pre> Example result: `1655487883771`  | 
|  to\$1nanoseconds(interval day to second), to\$1nanoseconds(timestamp)  |  bigint  |  <pre>SELECT to_nanoseconds(INTERVAL '2' DAY + INTERVAL '3' HOUR)</pre> Example result: `183600000000000` <pre>SELECT to_nanoseconds(TIMESTAMP '2022-06-17 17:44:43.771000678')</pre> Example result: `1655487883771000678`  | 
|  to\$1unixtime(timestamp)  |  double  |  Returns unixtime for the provided timestamp. <pre>SELECT to_unixtime('2022-06-17 17:44:43.771000000')</pre> Example result: `1.6554878837710001E9`  | 
|  date\$1trunc(unit, timestamp)  |  timestamp  |  Returns the timestamp truncated to unit, where unit is one of [second, minute, hour, day, week, month, quarter, or year]. <pre>SELECT date_trunc('minute', TIMESTAMP '2022-06-17 17:44:43.771000000')</pre> Example result: `2022-06-17 17:44:00.000000000`  | 

## Interval and duration
<a name="date-time-functions-interval-duration"></a>

Timestream for LiveAnalytics supports the following interval and duration functions for date and time.


| Function | Output data type | Description | 
| --- | --- | --- | 
|  date\$1add(unit, bigint, date), date\$1add(unit, bigint, time), date\$1add(varchar(x), bigint, timestamp)  |  timestamp  |  Adds a bigint of units, where unit is one of [second, minute, hour, day, week, month, quarter, or year]. <pre>SELECT date_add('hour', 9, TIMESTAMP '2022-06-17 00:00:00')</pre> Example result: `2022-06-17 09:00:00.000000000`  | 
|  date\$1diff(unit, date, date) , date\$1diff(unit, time, time) , date\$1diff(unit, timestamp, timestamp)  |  bigint  |  Returns a difference, where unit is one of [second, minute, hour, day, week, month, quarter, or year]. <pre>SELECT date_diff('day', DATE '2020-03-01', DATE '2020-03-02')</pre> Example result: `1`  | 
|  parse\$1duration(string)  |  interval  |  Parses the input string to return an `interval` equivalent. <pre>SELECT parse_duration('42.8ms')</pre> Example result: `0 00:00:00.042800000` <pre>SELECT typeof(parse_duration('42.8ms'))</pre> Example result: `interval day to second`  | 
| bin(timestamp, interval) | timestamp |  Rounds down the `timestamp` parameter's integer value to the nearest multiple of the `interval` parameter's integer value. The meaning of this return value may not be obvious. It is calculated using integer arithmetic first by dividing the timestamp integer by the interval integer and then by multiplying the result by the interval integer. Keeping in mind that a timestamp specifies a UTC point in time as a number of fractions of a second elapsed since the POSIX epoch (January 1, 1970), the return value will seldom align with calendar units. For example, if you specify an interval of 30 days, all the days since the epoch are divided into 30-day increments, and the start of the most recent 30-day increment is returned, which has no relationship to calendar months. Here are some examples: <pre>bin(TIMESTAMP '2022-06-17 10:15:20', 5m)     ==> 2022-06-17 10:15:00.000000000<br />bin(TIMESTAMP '2022-06-17 10:15:20', 1d)     ==> 2022-06-17 00:00:00.000000000<br />bin(TIMESTAMP '2022-06-17 10:15:20', 10day)  ==> 2022-06-17 00:00:00.000000000<br />bin(TIMESTAMP '2022-06-17 10:15:20', 30day)  ==> 2022-05-28 00:00:00.000000000</pre>  | 
|  ago(interval)  |  timestamp  |  Returns the value corresponding to current\$1timestamp `interval`. <pre>SELECT ago(1d)</pre> Example result: `2022-07-06 21:08:53.245000000`  | 
|  interval literals such as 1h, 1d, and 30m  |  interval  |  Interval literals are a convenience for parse\$1duration(string). For example, `1d` is the same as `parse_duration('1d')`. This allows the use of the literals wherever an interval is used. For example, `ago(1d)` and `bin(<timestamp>, 1m)`.  | 

Some interval literals act as shorthand for parse\$1duration. For example, `parse_duration('1day')`, `1day`, `parse_duration('1d')`, and `1d` each return `1 00:00:00.000000000` where the type is `interval day to second`. Space is allowed in the format provided to `parse_duration`. For example `parse_duration('1day')` also returns `00:00:00.000000000`. But `1 day` is not an interval literal.

The units related to `interval day to second` are ns, nanosecond, us, microsecond, ms, millisecond, s, second, m, minute, h, hour, d, and day.

There is also `interval year to month`. The units related to interval year to month are y, year, and month. For example, `SELECT 1year` returns `1-0`. `SELECT 12month` also returns `1-0`. `SELECT 8month` returns `0-8`.

Although the unit of `quarter` is also available for some functions such as `date_trunc` and `date_add`, `quarter` is not available as part of an interval literal.

## Formatting and parsing
<a name="date-time-functions-formatting-parsing"></a>

Timestream for LiveAnalytics supports the following formatting and parsing functions for date and time.


| Function | Output data type | Description | 
| --- | --- | --- | 
|  date\$1format(timestamp, varchar(x))  |  varchar  |  For more information about the format specifiers used by this function, see [https://trino.io/docs/current/functions/datetime.html\$1mysql-date-functions](https://trino.io/docs/current/functions/datetime.html#mysql-date-functions) <pre>SELECT date_format(TIMESTAMP '2019-10-20 10:20:20', '%Y-%m-%d %H:%i:%s')</pre> Example result: `2019-10-20 10:20:20`  | 
|  date\$1parse(varchar(x), varchar(y))  |  timestamp  |  For more information about the format specifiers used by this function, see [https://trino.io/docs/current/functions/datetime.html\$1mysql-date-functions](https://trino.io/docs/current/functions/datetime.html#mysql-date-functions) <pre>SELECT date_parse('2019-10-20 10:20:20', '%Y-%m-%d %H:%i:%s')</pre> Example result: `2019-10-20 10:20:20.000000000`  | 
|  format\$1datetime(timestamp, varchar(x))  |  varchar  |  For more information about the format string used by this function, see [http://joda-time.sourceforge.net/apidocs/org/joda/time/format/DateTimeFormat.html](http://joda-time.sourceforge.net/apidocs/org/joda/time/format/DateTimeFormat.html) <pre>SELECT format_datetime(parse_datetime('1968-01-13 12', 'yyyy-MM-dd HH'), 'yyyy-MM-dd HH')</pre> Example result: `1968-01-13 12`  | 
|  parse\$1datetime(varchar(x), varchar(y))  |  timestamp  |  For more information about the format string used by this function, see [http://joda-time.sourceforge.net/apidocs/org/joda/time/format/DateTimeFormat.html](http://joda-time.sourceforge.net/apidocs/org/joda/time/format/DateTimeFormat.html) <pre>SELECT parse_datetime('2019-12-29 10:10 PST', 'uuuu-LL-dd HH:mm z')</pre> Example result: `2019-12-29 18:10:00.000000000`  | 

## Extraction
<a name="date-time-functions-extraction"></a>

Timestream for LiveAnalytics supports the following extraction functions for date and time. The extract function is the basis for the remaining convenience functions.


| Function | Output data type | Description | 
| --- | --- | --- | 
|  extract  |  bigint  |  Extracts a field from a timestamp, where field is one of [YEAR, QUARTER, MONTH, WEEK, DAY, DAY\$1OF\$1MONTH, DAY\$1OF\$1WEEK, DOW, DAY\$1OF\$1YEAR, DOY, YEAR\$1OF\$1WEEK, YOW, HOUR, MINUTE, or SECOND]. <pre>SELECT extract(YEAR FROM '2019-10-12 23:10:34.000000000')</pre> Example result: `2019`  | 
|  day(timestamp), day(date), day(interval day to second)  |  bigint  |  <pre>SELECT day('2019-10-12 23:10:34.000000000')</pre> Example result: `12`  | 
|  day\$1of\$1month(timestamp), day\$1of\$1month(date), day\$1of\$1month(interval day to second)  |  bigint  |  <pre>SELECT day_of_month('2019-10-12 23:10:34.000000000')</pre> Example result: `12`  | 
|  day\$1of\$1week(timestamp), day\$1of\$1week(date)  |  bigint  |  <pre>SELECT day_of_week('2019-10-12 23:10:34.000000000')</pre> Example result: `6`  | 
|  day\$1of\$1year(timestamp), day\$1of\$1year(date)  |  bigint  |  <pre>SELECT day_of_year('2019-10-12 23:10:34.000000000')</pre> Example result: `285`  | 
|  dow(timestamp), dow(date)  |  bigint  |  Alias for day\$1of\$1week  | 
|  doy(timestamp), doy(date)  |  bigint  |  Alias for day\$1of\$1year  | 
|  hour(timestamp), hour(time), hour(interval day to second)  |  bigint  |  <pre>SELECT hour('2019-10-12 23:10:34.000000000')</pre> Example result: `23`  | 
|  millisecond(timestamp), millisecond(time), millisecond(interval day to second)  |  bigint  |  <pre>SELECT millisecond('2019-10-12 23:10:34.000000000')</pre> Example result: `0`  | 
|  minute(timestamp), minute(time), minute(interval day to second)  |  bigint  |  <pre>SELECT minute('2019-10-12 23:10:34.000000000')</pre> Example result: `10`  | 
|  month(timestamp), month(date), month(interval year to month)  |  bigint  |  <pre>SELECT month('2019-10-12 23:10:34.000000000')</pre> Example result: `10`  | 
|  nanosecond(timestamp), nanosecond(time), nanosecond(interval day to second)  |  bigint  |  <pre>SELECT nanosecond(current_timestamp)</pre> Example result: `162000000`  | 
|  quarter(timestamp), quarter(date)  |  bigint  |  <pre>SELECT quarter('2019-10-12 23:10:34.000000000')</pre> Example result: `4`  | 
|  second(timestamp), second(time), second(interval day to second)  |  bigint  |  <pre>SELECT second('2019-10-12 23:10:34.000000000')</pre> Example result: `34`  | 
|  week(timestamp), week(date)  |  bigint  |  <pre>SELECT week('2019-10-12 23:10:34.000000000')</pre> Example result: `41`  | 
|  week\$1of\$1year(timestamp), week\$1of\$1year(date)  |  bigint  |  Alias for week  | 
|  year(timestamp), year(date), year(interval year to month)  |  bigint  |  <pre>SELECT year('2019-10-12 23:10:34.000000000')</pre> Example result: `2019`  | 
|  year\$1of\$1week(timestamp), year\$1of\$1week(date)  |  bigint  |  <pre>SELECT year_of_week('2019-10-12 23:10:34.000000000')</pre> Example result: `2019`  | 
|  yow(timestamp), yow(date)  |  bigint  |  Alias for year\$1of\$1week  | 

# Aggregate functions
<a name="aggregate-functions"></a>

Timestream for LiveAnalytics supports the following aggregate functions.


| Function | Output data type | Description | 
| --- | --- | --- | 
|  arbitrary(x)  |  [same as input]  |  Returns an arbitrary non-null value of x, if one exists. <pre>SELECT arbitrary(t.c) FROM (VALUES 1, 2, 3, 4) AS t(c)</pre> Example result: `1`  | 
|  array\$1agg(x)  |  array<[same as input]  |  Returns an array created from the input x elements. <pre>SELECT array_agg(t.c) FROM (VALUES 1, 2, 3, 4) AS t(c)</pre> Example result: `[ 1,2,3,4 ]`  | 
|  avg(x)  |  double  |  Returns the average (arithmetic mean) of all input values. <pre>SELECT avg(t.c) FROM (VALUES 1, 2, 3, 4) AS t(c)</pre> Example result: `2.5`  | 
|  bool\$1and(boolean) every(boolean)   |  boolean  |  Returns TRUE if every input value is TRUE, otherwise FALSE. <pre>SELECT bool_and(t.c) FROM (VALUES true, true, false, true) AS t(c)</pre> Example result: `false`  | 
|  bool\$1or(boolean)  |  boolean  |  Returns TRUE if any input value is TRUE, otherwise FALSE. <pre>SELECT bool_or(t.c) FROM (VALUES true, true, false, true) AS t(c)</pre> Example result: `true`  | 
|  count(\$1) count(x)  |  bigint  |  count(\$1) returns the number of input rows. count(x) returns the number of non-null input values. <pre>SELECT count(t.c) FROM (VALUES true, true, false, true) AS t(c)</pre> Example result: `4`  | 
|  count\$1if(x)   |  bigint  |  Returns the number of TRUE input values.  <pre>SELECT count_if(t.c) FROM (VALUES true, true, false, true) AS t(c)</pre> Example result: `3`  | 
|  geometric\$1mean(x)  |  double  |  Returns the geometric mean of all input values. <pre>SELECT geometric_mean(t.c) FROM (VALUES 1, 2, 3, 4) AS t(c)</pre> Example result: `2.213363839400643`  | 
|  max\$1by(x, y)   |  [same as x]  |  Returns the value of x associated with the maximum value of y over all input values. <pre>SELECT max_by(t.c1, t.c2) FROM (VALUES (('a', 1)), (('b', 2)), (('c', 3)), (('d', 4))) AS t(c1, c2)</pre> Example result: `d`  | 
|  max\$1by(x, y, n)   |  array<[same as x]>  |  Returns n values of x associated with the n largest of all input values of y in descending order of y. <pre>SELECT max_by(t.c1, t.c2, 2) FROM (VALUES (('a', 1)), (('b', 2)), (('c', 3)), (('d', 4))) AS t(c1, c2)</pre> Example result: `[ d,c ]`  | 
|  min\$1by(x, y)  |  [same as x]  |  Returns the value of x associated with the minimum value of y over all input values. <pre>SELECT min_by(t.c1, t.c2) FROM (VALUES (('a', 1)), (('b', 2)), (('c', 3)), (('d', 4))) AS t(c1, c2)</pre> Example result: `a`  | 
|  min\$1by(x, y, n)  |  array<[same as x]>  |  Returns n values of x associated with the n smallest of all input values of y in ascending order of y. <pre>SELECT min_by(t.c1, t.c2, 2) FROM (VALUES (('a', 1)), (('b', 2)), (('c', 3)), (('d', 4))) AS t(c1, c2)</pre> Example result: `[ a,b ]`  | 
|  max(x)  |  [same as input]  |  Returns the maximum value of all input values. <pre>SELECT max(t.c) FROM (VALUES 1, 2, 3, 4) AS t(c)</pre> Example result: `4`  | 
|  max(x, n)  |  array<[same as x]>  |  Returns n largest values of all input values of x. <pre>SELECT max(t.c, 2) FROM (VALUES 1, 2, 3, 4) AS t(c)</pre> Example result: `[ 4,3 ]`  | 
|  min(x)  |  [same as input]  |  Returns the minimum value of all input values. <pre>SELECT min(t.c) FROM (VALUES 1, 2, 3, 4) AS t(c)</pre> Example result: `1`  | 
|  min(x, n)  |  array<[same as x]>  |  Returns n smallest values of all input values of x. <pre>SELECT min(t.c, 2) FROM (VALUES 1, 2, 3, 4) AS t(c)</pre> Example result: `[ 1,2 ]`  | 
|  sum(x)   |  [same as input]  |  Returns the sum of all input values. <pre>SELECT sum(t.c) FROM (VALUES 1, 2, 3, 4) AS t(c)</pre> Example result: `10`  | 
|  bitwise\$1and\$1agg(x)  |  bigint  |  Returns the bitwise AND of all input values in 2s complement representation. <pre>SELECT bitwise_and_agg(t.c) FROM (VALUES 1, -3) AS t(c)</pre> Example result: `1`  | 
|  bitwise\$1or\$1agg(x)  |  bigint  |  Returns the bitwise OR of all input values in 2s complement representation. <pre>SELECT bitwise_or_agg(t.c) FROM (VALUES 1, -3) AS t(c)</pre> Example result: `-3`  | 
|  approx\$1distinct(x)   |  bigint  |  Returns the approximate number of distinct input values. This function provides an approximation of count(DISTINCT x). Zero is returned if all input values are null. This function should produce a standard error of 2.3%, which is the standard deviation of the (approximately normal) error distribution over all possible sets. It does not guarantee an upper bound on the error for any specific input set. <pre>SELECT approx_distinct(t.c) FROM (VALUES 1, 2, 3, 4, 8) AS t(c)</pre> Example result: `5`  | 
|  approx\$1distinct(x, e)  |  bigint  |  Returns the approximate number of distinct input values. This function provides an approximation of count(DISTINCT x). Zero is returned if all input values are null. This function should produce a standard error of no more than e, which is the standard deviation of the (approximately normal) error distribution over all possible sets. It does not guarantee an upper bound on the error for any specific input set. The current implementation of this function requires that e be in the range of [0.0040625, 0.26000]. <pre>SELECT approx_distinct(t.c, 0.2) FROM (VALUES 1, 2, 3, 4, 8) AS t(c)</pre> Example result: `5`  | 
|  approx\$1percentile(x, percentage)   |  [same as x]  |  Returns the approximate percentile for all input values of x at the given percentage. The value of percentage must be between zero and one and must be constant for all input rows. <pre>SELECT approx_percentile(t.c, 0.4) FROM (VALUES 1, 2, 3, 4) AS t(c)</pre> Example result: `2`  | 
|  approx\$1percentile(x, percentages)   |  array<[same as x]>  |  Returns the approximate percentile for all input values of x at each of the specified percentages. Each element of the percentages array must be between zero and one, and the array must be constant for all input rows. <pre>SELECT approx_percentile(t.c, ARRAY[0.1, 0.8, 0.8]) FROM (VALUES 1, 2, 3, 4) AS t(c)</pre> Example result: `[ 1,4,4 ]`  | 
|  approx\$1percentile(x, w, percentage)   |  [same as x]  |  Returns the approximate weighed percentile for all input values of x using the per-item weight w at the percentage p. The weight must be an integer value of at least one. It is effectively a replication count for the value x in the percentile set. The value of p must be between zero and one and must be constant for all input rows. <pre>SELECT approx_percentile(t.c, 1, 0.1) FROM (VALUES 1, 2, 3, 4) AS t(c)</pre> Example result: `1`  | 
|  approx\$1percentile(x, w, percentages)   |  array<[same as x]>  |  Returns the approximate weighed percentile for all input values of x using the per-item weight w at each of the given percentages specified in the array. The weight must be an integer value of at least one. It is effectively a replication count for the value x in the percentile set. Each element of the array must be between zero and one, and the array must be constant for all input rows. <pre>SELECT approx_percentile(t.c, 1, ARRAY[0.1, 0.8, 0.8]) FROM (VALUES 1, 2, 3, 4) AS t(c)</pre> Example result: `[ 1,4,4 ]`  | 
|  approx\$1percentile(x, w, percentage, accuracy)  |  [same as x]  |  Returns the approximate weighed percentile for all input values of x using the per-item weight w at the percentage p, with a maximum rank error of accuracy. The weight must be an integer value of at least one. It is effectively a replication count for the value x in the percentile set. The value of p must be between zero and one and must be constant for all input rows. The accuracy must be a value greater than zero and less than one, and it must be constant for all input rows. <pre>SELECT approx_percentile(t.c, 1, 0.1, 0.5) FROM (VALUES 1, 2, 3, 4) AS t(c)</pre> Example result: `1`  | 
|  corr(y, x)  |  double  |  Returns correlation coefficient of input values. <pre>SELECT corr(t.c1, t.c2) FROM (VALUES ((1, 1)), ((2, 2)), ((3, 3)), ((4, 4))) AS t(c1, c2)</pre> Example result: `1.0`  | 
|  covar\$1pop(y, x)  |  double  |  Returns the population covariance of input values. <pre>SELECT covar_pop(t.c1, t.c2) FROM (VALUES ((1, 1)), ((2, 2)), ((3, 3)), ((4, 4))) AS t(c1, c2)</pre> Example result: `1.25`  | 
|  covar\$1samp(y, x)   |  double  |  Returns the sample covariance of input values. <pre>SELECT covar_samp(t.c1, t.c2) FROM (VALUES ((1, 1)), ((2, 2)), ((3, 3)), ((4, 4))) AS t(c1, c2)</pre> Example result: `1.6666666666666667`  | 
|  regr\$1intercept(y, x)  |  double  |  Returns linear regression intercept of input values. y is the dependent value. x is the independent value. <pre>SELECT regr_intercept(t.c1, t.c2) FROM (VALUES ((1, 1)), ((2, 2)), ((3, 3)), ((4, 4))) AS t(c1, c2)</pre> Example result: `0.0`  | 
|  regr\$1slope(y, x)  |  double  |  Returns linear regression slope of input values. y is the dependent value. x is the independent value. <pre>SELECT regr_slope(t.c1, t.c2) FROM (VALUES ((1, 1)), ((2, 2)), ((3, 3)), ((4, 4))) AS t(c1, c2)</pre> Example result: `1.0`  | 
|  skewness(x)  |  double  |  Returns the skewness of all input values. <pre>SELECT skewness(t.c1) FROM (VALUES 1, 2, 3, 4, 8) AS t(c1)</pre> Example result: `0.8978957037987335`  | 
|  stddev\$1pop(x)  |  double  |  Returns the population standard deviation of all input values. <pre>SELECT stddev_pop(t.c1) FROM (VALUES 1, 2, 3, 4, 8) AS t(c1)</pre> Example result: `2.4166091947189146`  | 
|  stddev\$1samp(x) stddev(x)  |  double  |  Returns the sample standard deviation of all input values. <pre>SELECT stddev_samp(t.c1) FROM (VALUES 1, 2, 3, 4, 8) AS t(c1)</pre> Example result: `2.701851217221259`  | 
|  var\$1pop(x)   |  double  |  Returns the population variance of all input values. <pre>SELECT var_pop(t.c1) FROM (VALUES 1, 2, 3, 4, 8) AS t(c1)</pre> Example result: `5.840000000000001`  | 
|  var\$1samp(x) variance(x)   |  double  |  Returns the sample variance of all input values. <pre>SELECT var_samp(t.c1) FROM (VALUES 1, 2, 3, 4, 8) AS t(c1)</pre> Example result: `7.300000000000001`  | 

# Window functions
<a name="window-functions"></a>

Window functions perform calculations across rows of the query result. They run after the HAVING clause but before the ORDER BY clause. Invoking a window function requires special syntax using the OVER clause to specify the window. A window has three components:
+ The partition specification, which separates the input rows into different partitions. This is analogous to how the GROUP BY clause separates rows into different groups for aggregate functions.
+ The ordering specification, which determines the order in which input rows will be processed by the window function.
+ The window frame, which specifies a sliding window of rows to be processed by the function for a given row. If the frame is not specified, it defaults to RANGE UNBOUNDED PRECEDING, which is the same as RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW. This frame contains all rows from the start of the partition up to the last peer of the current row.

All Aggregate Functions can be used as window functions by adding the OVER clause. The aggregate function is computed for each row over the rows within the current row's window frame. In addition to aggregate functions, Timestream for LiveAnalytics supports the following ranking and value functions.


| Function | Output data type | Description | 
| --- | --- | --- | 
|  cume\$1dist()  |  bigint  |  Returns the cumulative distribution of a value in a group of values. The result is the number of rows preceding or peer with the row in the window ordering of the window partition divided by the total number of rows in the window partition. Thus, any tie values in the ordering will evaluate to the same distribution value.  | 
|  dense\$1rank()  |  bigint  |  Returns the rank of a value in a group of values. This is similar to rank(), except that tie values do not produce gaps in the sequence.  | 
|  ntile(n)  |  bigint  |  Divides the rows for each window partition into n buckets ranging from 1 to at most n. Bucket values will differ by at most 1. If the number of rows in the partition does not divide evenly into the number of buckets, then the remainder values are distributed one per bucket, starting with the first bucket.  | 
|  percent\$1rank()  |  double  |  Returns the percentage ranking of a value in group of values. The result is (r - 1) / (n - 1) where r is the rank() of the row and n is the total number of rows in the window partition.  | 
|  rank()  |  bigint  |  Returns the rank of a value in a group of values. The rank is one plus the number of rows preceding the row that are not peer with the row. Thus, tie values in the ordering will produce gaps in the sequence. The ranking is performed for each window partition.  | 
|  row\$1number()  |  bigint  |  Returns a unique, sequential number for each row, starting with one, according to the ordering of rows within the window partition.  | 
|  first\$1value(x)  |  [same as input]  |  Returns the first value of the window. This function is scoped to the window frame. The function takes an expression or target as its parameter.  | 
|  last\$1value(x)  |  [same as input]  |  Returns the last value of the window. This function is scoped to the window frame. The function takes an expression or target as its parameter.  | 
|  nth\$1value(x, offset)  |  [same as input]  |  Returns the value at the specified offset from beginning the window. Offsets start at 1. The offset can be any scalar expression. If the offset is null or greater than the number of values in the window, null is returned. It is an error for the offset to be zero or negative. The function takes an expression or target as its first parameter.  | 
|  lead(x[, offset[, default\$1value]])  |  [same as input]  |  Returns the value at offset rows after the current row in the window. Offsets start at 0, which is the current row. The offset can be any scalar expression. The default offset is 1. If the offset is null or larger than the window, the default\$1value is returned, or if it is not specified null is returned. The function takes an expression or target as its first parameter.  | 
|  lag(x[, offset[, default\$1value]])  |  [same as input]  |  Returns the value at offset rows before the current row in the window Offsets start at 0, which is the current row. The offset can be any scalar expression. The default offset is 1. If the offset is null or larger than the window, the default\$1value is returned, or if it is not specified null is returned. The function takes an expression or target as its first parameter.  | 

# Sample queries
<a name="sample-queries"></a>

This section includes example use cases of Timestream for LiveAnalytics's query language.

**Topics**
+ [Simple queries](sample-queries.basic-scenarios.md)
+ [Queries with time series functions](sample-queries.devops-scenarios.md)
+ [Queries with aggregate functions](sample-queries.iot-scenarios.md)

# Simple queries
<a name="sample-queries.basic-scenarios"></a>

The following gets the 10 most recently added data points for a table.

```
SELECT * FROM <database_name>.<table_name>
ORDER BY time DESC
LIMIT 10
```

The following gets the 5 oldest data points for a specific measure.

```
SELECT * FROM <database_name>.<table_name>
WHERE measure_name = '<measure_name>'
ORDER BY time ASC
LIMIT 5
```

The following works with nanosecond granularity timestamps.

```
SELECT now() AS time_now
, now() - (INTERVAL '12' HOUR) AS twelve_hour_earlier -- Compatibility with ANSI SQL 
, now() - 12h AS also_twelve_hour_earlier -- Convenient time interval literals
, ago(12h) AS twelve_hours_ago -- More convenience with time functionality
, bin(now(), 10m) AS time_binned -- Convenient time binning support
, ago(50ns) AS fifty_ns_ago -- Nanosecond support
, now() + (1h + 50ns) AS hour_fifty_ns_future
```

Measure values for multi-measure records are identified by column name. Measure values for single-measure records are identified by `measure_value::<data_type>`, where `<data_type>` is one of `double`, `bigint`, `boolean`, or `varchar` as described in [Supported data types](supported-data-types.md). For more information about how measure values are modeled, see [Single table vs. multiple tables](https://docs.aws.amazon.com/timestream/latest/developerguide/data-modeling.html#data-modeling-multiVsinglerecords).

The following retrieves values for a measure called `speed` from multi-measure records with a `measure_name` of `IoTMulti-stats`.

```
SELECT speed FROM <database_name>.<table_name> where measure_name = 'IoTMulti-stats'
```

The following retrieves `double` values from single-measure records with a `measure_name` of `load`.

```
SELECT measure_value::double FROM <database_name>.<table_name> WHERE measure_name = 'load'
```

# Queries with time series functions
<a name="sample-queries.devops-scenarios"></a>

**Topics**
+ [Example dataset and queries](#sample-queries.devops-scenarios.example)

## Example dataset and queries
<a name="sample-queries.devops-scenarios.example"></a>

You can use Timestream for LiveAnalytics to understand and improve the performance and availability of your services and applications. Below is an example table and sample queries run on that table. 

The table `ec2_metrics` stores telemetry data, such as CPU utilization and other metrics from EC2 instances. You can view the table below.


| Time | region | az | Hostname | measure\$1name | measure\$1value::double | measure\$1value::bigint | 
| --- | --- | --- | --- | --- | --- | --- | 
|  2019-12-04 19:00:00.000000000  |  us-east-1  |  us-east-1a  |  frontend01  |  cpu\$1utilization  |  35.1  |  null  | 
|  2019-12-04 19:00:00.000000000  |  us-east-1  |  us-east-1a  |  frontend01  |  memory\$1utilization  |  55.3  |  null  | 
|  2019-12-04 19:00:00.000000000  |  us-east-1  |  us-east-1a  |  frontend01  |  network\$1bytes\$1in  |  null  |  1,500  | 
|  2019-12-04 19:00:00.000000000  |  us-east-1  |  us-east-1a  |  frontend01  |  network\$1bytes\$1out  |  null  |  6,700  | 
|  2019-12-04 19:00:00.000000000  |  us-east-1  |  us-east-1b  |  frontend02  |  cpu\$1utilization  |  38.5  |  null  | 
|  2019-12-04 19:00:00.000000000  |  us-east-1  |  us-east-1b  |  frontend02  |  memory\$1utilization  |  58.4  |  null  | 
|  2019-12-04 19:00:00.000000000  |  us-east-1  |  us-east-1b  |  frontend02  |  network\$1bytes\$1in  |  null  |  23,000  | 
|  2019-12-04 19:00:00.000000000  |  us-east-1  |  us-east-1b  |  frontend02  |  network\$1bytes\$1out  |  null  |  12,000  | 
|  2019-12-04 19:00:00.000000000  |  us-east-1  |  us-east-1c  |  frontend03  |  cpu\$1utilization  |  45.0  |  null  | 
|  2019-12-04 19:00:00.000000000  |  us-east-1  |  us-east-1c  |  frontend03  |  memory\$1utilization  |  65.8  |  null  | 
|  2019-12-04 19:00:00.000000000  |  us-east-1  |  us-east-1c  |  frontend03  |  network\$1bytes\$1in  |  null  |  15,000  | 
|  2019-12-04 19:00:00.000000000  |  us-east-1  |  us-east-1c  |  frontend03  |  network\$1bytes\$1out  |  null  |  836,000  | 
|  2019-12-04 19:00:05.000000000  |  us-east-1  |  us-east-1a  |  frontend01  |  cpu\$1utilization  |  55.2  |  null  | 
|  2019-12-04 19:00:05.000000000  |  us-east-1  |  us-east-1a  |  frontend01  |  memory\$1utilization  |  75.0  |  null  | 
|  2019-12-04 19:00:05.000000000  |  us-east-1  |  us-east-1a  |  frontend01  |  network\$1bytes\$1in  |  null  |  1,245  | 
|  2019-12-04 19:00:05.000000000  |  us-east-1  |  us-east-1a  |  frontend01  |  network\$1bytes\$1out  |  null  |  68,432  | 
|  2019-12-04 19:00:08.000000000  |  us-east-1  |  us-east-1b  |  frontend02  |  cpu\$1utilization  |  65.6  |  null  | 
|  2019-12-04 19:00:08.000000000  |  us-east-1  |  us-east-1b  |  frontend02  |  memory\$1utilization  |  85.3  |  null  | 
|  2019-12-04 19:00:08.000000000  |  us-east-1  |  us-east-1b  |  frontend02  |  network\$1bytes\$1in  |  null  |  1,245  | 
|  2019-12-04 19:00:08.000000000  |  us-east-1  |  us-east-1b  |  frontend02  |  network\$1bytes\$1out  |  null  |  68,432  | 
|  2019-12-04 19:00:20.000000000  |  us-east-1  |  us-east-1c  |  frontend03  |  cpu\$1utilization  |  12.1  |  null  | 
|  2019-12-04 19:00:20.000000000  |  us-east-1  |  us-east-1c  |  frontend03  |  memory\$1utilization  |  32.0  |  null  | 
|  2019-12-04 19:00:20.000000000  |  us-east-1  |  us-east-1c  |  frontend03  |  network\$1bytes\$1in  |  null  |  1,400  | 
|  2019-12-04 19:00:20.000000000  |  us-east-1  |  us-east-1c  |  frontend03  |  network\$1bytes\$1out  |  null  |  345  | 
|  2019-12-04 19:00:10.000000000  |  us-east-1  |  us-east-1a  |  frontend01  |  cpu\$1utilization  |  15.3  |  null  | 
|  2019-12-04 19:00:10.000000000  |  us-east-1  |  us-east-1a  |  frontend01  |  memory\$1utilization  |  35.4  |  null  | 
|  2019-12-04 19:00:10.000000000  |  us-east-1  |  us-east-1a  |  frontend01  |  network\$1bytes\$1in  |  null  |  23  | 
|  2019-12-04 19:00:10.000000000  |  us-east-1  |  us-east-1a  |  frontend01  |  network\$1bytes\$1out  |  null  |  0  | 
|  2019-12-04 19:00:16.000000000  |  us-east-1  |  us-east-1b  |  frontend02  |  cpu\$1utilization  |  44.0  |  null  | 
|  2019-12-04 19:00:16.000000000  |  us-east-1  |  us-east-1b  |  frontend02  |  memory\$1utilization  |  64.2  |  null  | 
|  2019-12-04 19:00:16.000000000  |  us-east-1  |  us-east-1b  |  frontend02  |  network\$1bytes\$1in  |  null  |  1,450  | 
|  2019-12-04 19:00:16.000000000  |  us-east-1  |  us-east-1b  |  frontend02  |  network\$1bytes\$1out  |  null  |  200  | 
|  2019-12-04 19:00:40.000000000  |  us-east-1  |  us-east-1c  |  frontend03  |  cpu\$1utilization  |  66.4  |  null  | 
|  2019-12-04 19:00:40.000000000  |  us-east-1  |  us-east-1c  |  frontend03  |  memory\$1utilization  |  86.3  |  null  | 
|  2019-12-04 19:00:40.000000000  |  us-east-1  |  us-east-1c  |  frontend03  |  network\$1bytes\$1in  |  null  |  300  | 
|  2019-12-04 19:00:40.000000000  |  us-east-1  |  us-east-1c  |  frontend03  |  network\$1bytes\$1out  |  null  |  423  | 

Find the average, p90, p95, and p99 CPU utilization for a specific EC2 host over the past 2 hours:

```
SELECT region, az, hostname, BIN(time, 15s) AS binned_timestamp,
    ROUND(AVG(measure_value::double), 2) AS avg_cpu_utilization,
    ROUND(APPROX_PERCENTILE(measure_value::double, 0.9), 2) AS p90_cpu_utilization,
    ROUND(APPROX_PERCENTILE(measure_value::double, 0.95), 2) AS p95_cpu_utilization,
    ROUND(APPROX_PERCENTILE(measure_value::double, 0.99), 2) AS p99_cpu_utilization
FROM "sampleDB".DevOps
WHERE measure_name = 'cpu_utilization'
    AND hostname = 'host-Hovjv'
    AND time > ago(2h)
GROUP BY region, hostname, az, BIN(time, 15s)
ORDER BY binned_timestamp ASC
```

Identify EC2 hosts with CPU utilization that is higher by 10 % or more compared to the average CPU utilization of the entire fleet for the past 2 hours:

```
WITH avg_fleet_utilization AS (
    SELECT COUNT(DISTINCT hostname) AS total_host_count, AVG(measure_value::double) AS fleet_avg_cpu_utilization
    FROM "sampleDB".DevOps
    WHERE measure_name = 'cpu_utilization'
        AND time > ago(2h)
), avg_per_host_cpu AS (
    SELECT region, az, hostname, AVG(measure_value::double) AS avg_cpu_utilization
    FROM "sampleDB".DevOps
    WHERE measure_name = 'cpu_utilization'
        AND time > ago(2h)
    GROUP BY region, az, hostname
)
SELECT region, az, hostname, avg_cpu_utilization, fleet_avg_cpu_utilization
FROM avg_fleet_utilization, avg_per_host_cpu
WHERE avg_cpu_utilization > 1.1 * fleet_avg_cpu_utilization
ORDER BY avg_cpu_utilization DESC
```

Find the average CPU utilization binned at 30 second intervals for a specific EC2 host over the past 2 hours:

```
SELECT BIN(time, 30s) AS binned_timestamp, ROUND(AVG(measure_value::double), 2) AS avg_cpu_utilization
FROM "sampleDB".DevOps
WHERE measure_name = 'cpu_utilization'
    AND hostname = 'host-Hovjv'
    AND time > ago(2h)
GROUP BY hostname, BIN(time, 30s)
ORDER BY binned_timestamp ASC
```

Find the average CPU utilization binned at 30 second intervals for a specific EC2 host over the past 2 hours, filling in the missing values using linear interpolation:

```
WITH binned_timeseries AS (
    SELECT hostname, BIN(time, 30s) AS binned_timestamp, ROUND(AVG(measure_value::double), 2) AS avg_cpu_utilization
    FROM "sampleDB".DevOps
    WHERE measure_name = 'cpu_utilization'
        AND hostname = 'host-Hovjv'
        AND time > ago(2h)
    GROUP BY hostname, BIN(time, 30s)
), interpolated_timeseries AS (
    SELECT hostname,
        INTERPOLATE_LINEAR(
            CREATE_TIME_SERIES(binned_timestamp, avg_cpu_utilization),
                SEQUENCE(min(binned_timestamp), max(binned_timestamp), 15s)) AS interpolated_avg_cpu_utilization
    FROM binned_timeseries
    GROUP BY hostname
)
SELECT time, ROUND(value, 2) AS interpolated_cpu
FROM interpolated_timeseries
CROSS JOIN UNNEST(interpolated_avg_cpu_utilization)
```

Find the average CPU utilization binned at 30 second intervals for a specific EC2 host over the past 2 hours, filling in the missing values using interpolation based on the last observation carried forward:

```
WITH binned_timeseries AS (
    SELECT hostname, BIN(time, 30s) AS binned_timestamp, ROUND(AVG(measure_value::double), 2) AS avg_cpu_utilization
    FROM "sampleDB".DevOps
    WHERE measure_name = 'cpu_utilization'
        AND hostname = 'host-Hovjv'
        AND time > ago(2h)
    GROUP BY hostname, BIN(time, 30s)
), interpolated_timeseries AS (
    SELECT hostname,
        INTERPOLATE_LOCF(
            CREATE_TIME_SERIES(binned_timestamp, avg_cpu_utilization),
                SEQUENCE(min(binned_timestamp), max(binned_timestamp), 15s)) AS interpolated_avg_cpu_utilization
    FROM binned_timeseries
    GROUP BY hostname
)
SELECT time, ROUND(value, 2) AS interpolated_cpu
FROM interpolated_timeseries
CROSS JOIN UNNEST(interpolated_avg_cpu_utilization)
```

# Queries with aggregate functions
<a name="sample-queries.iot-scenarios"></a>

Below is an example IoT scenario example data set to illustrate queries with aggregate functions.

**Topics**
+ [Example data](#sample-queries.iot-scenarios.example-data)
+ [Example queries](#sample-queries.iot-scenarios.example-queries)

## Example data
<a name="sample-queries.iot-scenarios.example-data"></a>

Timestream enables you to store and analyze IoT sensor data such as the location, fuel consumption, speed, and load capacity of one or more fleets of trucks to enable effective fleet management. Below is the schema and some of the data of a table iot\$1trucks that stores telemetry such as location, fuel consumption, speed, and load capacity of trucks.


| Time | truck\$1id | Make | Model | Fleet | fuel\$1capacity | load\$1capacity | measure\$1name | measure\$1value::double | measure\$1value::varchar | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 
|  2019-12-04 19:00:00.000000000  |  123456781  |  GMC  |  Astro  |  Alpha  |  100  |  500  |  fuel\$1reading  |  65.2  |  null  | 
|  2019-12-04 19:00:00.000000000  |  123456781  |  GMC  |  Astro  |  Alpha  |  100  |  500  |  load  |  400.0  |  null  | 
|  2019-12-04 19:00:00.000000000  |  123456781  |  GMC  |  Astro  |  Alpha  |  100  |  500  |  speed  |  90.2  |  null  | 
|  2019-12-04 19:00:00.000000000  |  123456781  |  GMC  |  Astro  |  Alpha  |  100  |  500  |  location  |  null  |  47.6062 N, 122.3321 W  | 
|  2019-12-04 19:00:00.000000000  |  123456782  |  Kenworth  |  W900  |  Alpha  |  150  |  1000  |  fuel\$1reading  |  10.1  |  null  | 
|  2019-12-04 19:00:00.000000000  |  123456782  |  Kenworth  |  W900  |  Alpha  |  150  |  1000  |  load  |  950.3  |  null  | 
|  2019-12-04 19:00:00.000000000  |  123456782  |  Kenworth  |  W900  |  Alpha  |  150  |  1000  |  speed  |  50.8  |  null  | 
|  2019-12-04 19:00:00.000000000  |  123456782  |  Kenworth  |  W900  |  Alpha  |  150  |  1000  |  location  |  null  |  40.7128 degrees N, 74.0060 degrees W  | 

## Example queries
<a name="sample-queries.iot-scenarios.example-queries"></a>

Get a list of all the sensor attributes and values being monitored for each truck in the fleet.

```
SELECT
    truck_id,
    fleet,
    fuel_capacity,
    model,
    load_capacity,
    make,
    measure_name
FROM "sampleDB".IoT
GROUP BY truck_id, fleet, fuel_capacity, model, load_capacity, make, measure_name
```

Get the most recent fuel reading of each truck in the fleet in the past 24 hours.

```
WITH latest_recorded_time AS (
    SELECT
        truck_id,
        max(time) as latest_time
    FROM "sampleDB".IoT
    WHERE measure_name = 'fuel-reading'
    AND time >= ago(24h)
    GROUP BY truck_id
)
SELECT
    b.truck_id,
    b.fleet,
    b.make,
    b.model,
    b.time,
    b.measure_value::double as last_reported_fuel_reading
FROM
latest_recorded_time a INNER JOIN "sampleDB".IoT b
ON a.truck_id = b.truck_id AND b.time = a.latest_time
WHERE b.measure_name = 'fuel-reading'
AND b.time > ago(24h)
ORDER BY b.truck_id
```

Identify trucks that have been running on low fuel(less than 10 %) in the past 48 hours:

```
WITH low_fuel_trucks AS (
    SELECT time, truck_id, fleet, make, model, (measure_value::double/cast(fuel_capacity as double)*100) AS fuel_pct
    FROM "sampleDB".IoT
    WHERE time >= ago(48h)
    AND (measure_value::double/cast(fuel_capacity as double)*100) < 10
    AND measure_name = 'fuel-reading'
),
other_trucks AS (
SELECT time, truck_id, (measure_value::double/cast(fuel_capacity as double)*100) as remaining_fuel
    FROM "sampleDB".IoT
    WHERE time >= ago(48h)
    AND truck_id IN (SELECT truck_id FROM low_fuel_trucks)
    AND (measure_value::double/cast(fuel_capacity as double)*100) >= 10
    AND measure_name = 'fuel-reading'
),
trucks_that_refuelled AS (
    SELECT a.truck_id
    FROM low_fuel_trucks a JOIN other_trucks b
    ON a.truck_id = b.truck_id AND b.time >= a.time
)
SELECT DISTINCT truck_id, fleet, make, model, fuel_pct
FROM low_fuel_trucks
WHERE truck_id NOT IN (
    SELECT truck_id FROM trucks_that_refuelled
)
```

Find the average load and max speed for each truck for the past week:

```
SELECT
    bin(time, 1d) as binned_time,
    fleet,
    truck_id,
    make,
    model,
    AVG(
        CASE WHEN measure_name = 'load' THEN measure_value::double ELSE NULL END
    ) AS avg_load_tons,
    MAX(
        CASE WHEN measure_name = 'speed' THEN measure_value::double ELSE NULL END
    ) AS max_speed_mph
FROM "sampleDB".IoT
WHERE time >= ago(7d)
AND measure_name IN ('load', 'speed')
GROUP BY fleet, truck_id, make, model, bin(time, 1d)
ORDER BY truck_id
```

Get the load efficiency for each truck for the past week:

```
WITH average_load_per_truck AS (
    SELECT
        truck_id,
        avg(measure_value::double)  AS avg_load
    FROM "sampleDB".IoT
    WHERE measure_name = 'load'
    AND time >= ago(7d)
    GROUP BY truck_id, fleet, load_capacity, make, model
),
truck_load_efficiency AS (
    SELECT
        a.truck_id,
        fleet,
        load_capacity,
        make,
        model,
        avg_load,
        measure_value::double,
        time,
        (measure_value::double*100)/avg_load as load_efficiency -- , approx_percentile(avg_load_pct, DOUBLE '0.9')
    FROM "sampleDB".IoT a JOIN average_load_per_truck b
    ON a.truck_id = b.truck_id
    WHERE a.measure_name = 'load'
)
SELECT
    truck_id,
    time,
    load_efficiency
FROM truck_load_efficiency
ORDER BY truck_id, time
```

# API reference
<a name="API_Reference"></a>

This section contains the API Reference documentation for Amazon Timestream. 

Timestream has two APIs: Query and Write.
+ The **Write API** allows you to perform operations like table creation, resource tagging, and writing of records to Timestream.
+ The **Query API** allows you to perform query operations.

**Note**  
Both APIs include the DescribeEndpoints action. *For both Query and Write, the DescribeEndpoints action are identical.*

You can read more about each API below, along with data types, common errors and parameters.

**Note**  
For error codes common to all AWS services, see the [AWS Support section](https://docs.aws.amazon.com/awssupport/latest/APIReference/CommonErrors.html). 

**Topics**
+ [Actions](API_Operations.md)
+ [Data Types](API_Types.md)
+ [Common Error Types](CommonErrors.md)
+ [Common Parameters](CommonParameters.md)

# Actions
<a name="API_Operations"></a>

The following actions are supported by Amazon Timestream Write:
+  [CreateBatchLoadTask](API_CreateBatchLoadTask.md) 
+  [CreateDatabase](API_CreateDatabase.md) 
+  [CreateTable](API_CreateTable.md) 
+  [DeleteDatabase](API_DeleteDatabase.md) 
+  [DeleteTable](API_DeleteTable.md) 
+  [DescribeBatchLoadTask](API_DescribeBatchLoadTask.md) 
+  [DescribeDatabase](API_DescribeDatabase.md) 
+  [DescribeEndpoints](API_DescribeEndpoints.md) 
+  [DescribeTable](API_DescribeTable.md) 
+  [ListBatchLoadTasks](API_ListBatchLoadTasks.md) 
+  [ListDatabases](API_ListDatabases.md) 
+  [ListTables](API_ListTables.md) 
+  [ListTagsForResource](API_ListTagsForResource.md) 
+  [ResumeBatchLoadTask](API_ResumeBatchLoadTask.md) 
+  [TagResource](API_TagResource.md) 
+  [UntagResource](API_UntagResource.md) 
+  [UpdateDatabase](API_UpdateDatabase.md) 
+  [UpdateTable](API_UpdateTable.md) 
+  [WriteRecords](API_WriteRecords.md) 

The following actions are supported by Amazon Timestream Query:
+  [CancelQuery](API_query_CancelQuery.md) 
+  [CreateScheduledQuery](API_query_CreateScheduledQuery.md) 
+  [DeleteScheduledQuery](API_query_DeleteScheduledQuery.md) 
+  [DescribeAccountSettings](API_query_DescribeAccountSettings.md) 
+  [DescribeEndpoints](API_query_DescribeEndpoints.md) 
+  [DescribeScheduledQuery](API_query_DescribeScheduledQuery.md) 
+  [ExecuteScheduledQuery](API_query_ExecuteScheduledQuery.md) 
+  [ListScheduledQueries](API_query_ListScheduledQueries.md) 
+  [ListTagsForResource](API_query_ListTagsForResource.md) 
+  [PrepareQuery](API_query_PrepareQuery.md) 
+  [Query](API_query_Query.md) 
+  [TagResource](API_query_TagResource.md) 
+  [UntagResource](API_query_UntagResource.md) 
+  [UpdateAccountSettings](API_query_UpdateAccountSettings.md) 
+  [UpdateScheduledQuery](API_query_UpdateScheduledQuery.md) 

# Amazon Timestream Write
<a name="API_Operations_Amazon_Timestream_Write"></a>

The following actions are supported by Amazon Timestream Write:
+  [CreateBatchLoadTask](API_CreateBatchLoadTask.md) 
+  [CreateDatabase](API_CreateDatabase.md) 
+  [CreateTable](API_CreateTable.md) 
+  [DeleteDatabase](API_DeleteDatabase.md) 
+  [DeleteTable](API_DeleteTable.md) 
+  [DescribeBatchLoadTask](API_DescribeBatchLoadTask.md) 
+  [DescribeDatabase](API_DescribeDatabase.md) 
+  [DescribeEndpoints](API_DescribeEndpoints.md) 
+  [DescribeTable](API_DescribeTable.md) 
+  [ListBatchLoadTasks](API_ListBatchLoadTasks.md) 
+  [ListDatabases](API_ListDatabases.md) 
+  [ListTables](API_ListTables.md) 
+  [ListTagsForResource](API_ListTagsForResource.md) 
+  [ResumeBatchLoadTask](API_ResumeBatchLoadTask.md) 
+  [TagResource](API_TagResource.md) 
+  [UntagResource](API_UntagResource.md) 
+  [UpdateDatabase](API_UpdateDatabase.md) 
+  [UpdateTable](API_UpdateTable.md) 
+  [WriteRecords](API_WriteRecords.md) 

# CreateBatchLoadTask
<a name="API_CreateBatchLoadTask"></a>

Creates a new Timestream batch load task. A batch load task processes data from a CSV source in an S3 location and writes to a Timestream table. A mapping from source to target is defined in a batch load task. Errors and events are written to a report at an S3 location. For the report, if the AWS KMS key is not specified, the report will be encrypted with an S3 managed key when `SSE_S3` is the option. Otherwise an error is thrown. For more information, see [AWS managed keys](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-managed-cmk). [Service quotas apply](https://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html). For details, see [code sample](https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.create-batch-load.html).

## Request Syntax
<a name="API_CreateBatchLoadTask_RequestSyntax"></a>

```
{
   "ClientToken": "string",
   "DataModelConfiguration": { 
      "DataModel": { 
         "DimensionMappings": [ 
            { 
               "DestinationColumn": "string",
               "SourceColumn": "string"
            }
         ],
         "MeasureNameColumn": "string",
         "MixedMeasureMappings": [ 
            { 
               "MeasureName": "string",
               "MeasureValueType": "string",
               "MultiMeasureAttributeMappings": [ 
                  { 
                     "MeasureValueType": "string",
                     "SourceColumn": "string",
                     "TargetMultiMeasureAttributeName": "string"
                  }
               ],
               "SourceColumn": "string",
               "TargetMeasureName": "string"
            }
         ],
         "MultiMeasureMappings": { 
            "MultiMeasureAttributeMappings": [ 
               { 
                  "MeasureValueType": "string",
                  "SourceColumn": "string",
                  "TargetMultiMeasureAttributeName": "string"
               }
            ],
            "TargetMultiMeasureName": "string"
         },
         "TimeColumn": "string",
         "TimeUnit": "string"
      },
      "DataModelS3Configuration": { 
         "BucketName": "string",
         "ObjectKey": "string"
      }
   },
   "DataSourceConfiguration": { 
      "CsvConfiguration": { 
         "ColumnSeparator": "string",
         "EscapeChar": "string",
         "NullValue": "string",
         "QuoteChar": "string",
         "TrimWhiteSpace": boolean
      },
      "DataFormat": "string",
      "DataSourceS3Configuration": { 
         "BucketName": "string",
         "ObjectKeyPrefix": "string"
      }
   },
   "RecordVersion": number,
   "ReportConfiguration": { 
      "ReportS3Configuration": { 
         "BucketName": "string",
         "EncryptionOption": "string",
         "KmsKeyId": "string",
         "ObjectKeyPrefix": "string"
      }
   },
   "TargetDatabaseName": "string",
   "TargetTableName": "string"
}
```

## Request Parameters
<a name="API_CreateBatchLoadTask_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [ClientToken](#API_CreateBatchLoadTask_RequestSyntax) **   <a name="timestream-CreateBatchLoadTask-request-ClientToken"></a>
  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 64.  
Required: No

 ** [DataModelConfiguration](#API_CreateBatchLoadTask_RequestSyntax) **   <a name="timestream-CreateBatchLoadTask-request-DataModelConfiguration"></a>
  
Type: [DataModelConfiguration](API_DataModelConfiguration.md) object  
Required: No

 ** [DataSourceConfiguration](#API_CreateBatchLoadTask_RequestSyntax) **   <a name="timestream-CreateBatchLoadTask-request-DataSourceConfiguration"></a>
Defines configuration details about the data source for a batch load task.  
Type: [DataSourceConfiguration](API_DataSourceConfiguration.md) object  
Required: Yes

 ** [RecordVersion](#API_CreateBatchLoadTask_RequestSyntax) **   <a name="timestream-CreateBatchLoadTask-request-RecordVersion"></a>
  
Type: Long  
Required: No

 ** [ReportConfiguration](#API_CreateBatchLoadTask_RequestSyntax) **   <a name="timestream-CreateBatchLoadTask-request-ReportConfiguration"></a>
Report configuration for a batch load task. This contains details about where error reports are stored.  
Type: [ReportConfiguration](API_ReportConfiguration.md) object  
Required: Yes

 ** [TargetDatabaseName](#API_CreateBatchLoadTask_RequestSyntax) **   <a name="timestream-CreateBatchLoadTask-request-TargetDatabaseName"></a>
Target Timestream database for a batch load task.  
Type: String  
Pattern: `[a-zA-Z0-9_.-]+`   
Required: Yes

 ** [TargetTableName](#API_CreateBatchLoadTask_RequestSyntax) **   <a name="timestream-CreateBatchLoadTask-request-TargetTableName"></a>
Target Timestream table for a batch load task.  
Type: String  
Pattern: `[a-zA-Z0-9_.-]+`   
Required: Yes

## Response Syntax
<a name="API_CreateBatchLoadTask_ResponseSyntax"></a>

```
{
   "TaskId": "string"
}
```

## Response Elements
<a name="API_CreateBatchLoadTask_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [TaskId](#API_CreateBatchLoadTask_ResponseSyntax) **   <a name="timestream-CreateBatchLoadTask-response-TaskId"></a>
The ID of the batch load task.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 32.  
Pattern: `[A-Z0-9]+` 

## Errors
<a name="API_CreateBatchLoadTask_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You are not authorized to perform this action.  
HTTP Status Code: 400

 ** ConflictException **   
Timestream was unable to process this request because it contains resource that already exists.  
HTTP Status Code: 400

 ** InternalServerException **   
 Timestream was unable to fully process this request because of an internal server error.  
HTTP Status Code: 500

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The operation tried to access a nonexistent resource. The resource might not be specified correctly, or its status might not be ACTIVE.  
HTTP Status Code: 400

 ** ServiceQuotaExceededException **   
 The instance quota of resource exceeded for this account.  
HTTP Status Code: 400

 ** ThrottlingException **   
 Too many requests were made by a user and they exceeded the service quotas. The request was throttled.  
HTTP Status Code: 400

 ** ValidationException **   
 An invalid or malformed request.  
HTTP Status Code: 400

## See Also
<a name="API_CreateBatchLoadTask_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-write-2018-11-01/CreateBatchLoadTask) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-write-2018-11-01/CreateBatchLoadTask) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/CreateBatchLoadTask) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-write-2018-11-01/CreateBatchLoadTask) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/CreateBatchLoadTask) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-write-2018-11-01/CreateBatchLoadTask) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-write-2018-11-01/CreateBatchLoadTask) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-write-2018-11-01/CreateBatchLoadTask) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-write-2018-11-01/CreateBatchLoadTask) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/CreateBatchLoadTask) 

# CreateDatabase
<a name="API_CreateDatabase"></a>

Creates a new Timestream database. If the AWS KMS key is not specified, the database will be encrypted with a Timestream managed AWS KMS key located in your account. For more information, see [AWS managed keys](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-managed-cmk). [Service quotas apply](https://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html). For details, see [code sample](https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.create-db.html). 

## Request Syntax
<a name="API_CreateDatabase_RequestSyntax"></a>

```
{
   "DatabaseName": "string",
   "KmsKeyId": "string",
   "Tags": [ 
      { 
         "Key": "string",
         "Value": "string"
      }
   ]
}
```

## Request Parameters
<a name="API_CreateDatabase_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [DatabaseName](#API_CreateDatabase_RequestSyntax) **   <a name="timestream-CreateDatabase-request-DatabaseName"></a>
The name of the Timestream database.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 256.  
Pattern: `[a-zA-Z0-9_.-]+`   
Required: Yes

 ** [KmsKeyId](#API_CreateDatabase_RequestSyntax) **   <a name="timestream-CreateDatabase-request-KmsKeyId"></a>
The AWS KMS key for the database. If the AWS KMS key is not specified, the database will be encrypted with a Timestream managed AWS KMS key located in your account. For more information, see [AWS managed keys](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-managed-cmk).  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: No

 ** [Tags](#API_CreateDatabase_RequestSyntax) **   <a name="timestream-CreateDatabase-request-Tags"></a>
 A list of key-value pairs to label the table.   
Type: Array of [Tag](API_Tag.md) objects  
Array Members: Minimum number of 0 items. Maximum number of 200 items.  
Required: No

## Response Syntax
<a name="API_CreateDatabase_ResponseSyntax"></a>

```
{
   "Database": { 
      "Arn": "string",
      "CreationTime": number,
      "DatabaseName": "string",
      "KmsKeyId": "string",
      "LastUpdatedTime": number,
      "TableCount": number
   }
}
```

## Response Elements
<a name="API_CreateDatabase_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [Database](#API_CreateDatabase_ResponseSyntax) **   <a name="timestream-CreateDatabase-response-Database"></a>
The newly created Timestream database.  
Type: [Database](API_Database.md) object

## Errors
<a name="API_CreateDatabase_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You are not authorized to perform this action.  
HTTP Status Code: 400

 ** ConflictException **   
Timestream was unable to process this request because it contains resource that already exists.  
HTTP Status Code: 400

 ** InternalServerException **   
 Timestream was unable to fully process this request because of an internal server error.  
HTTP Status Code: 500

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** ServiceQuotaExceededException **   
 The instance quota of resource exceeded for this account.  
HTTP Status Code: 400

 ** ThrottlingException **   
 Too many requests were made by a user and they exceeded the service quotas. The request was throttled.  
HTTP Status Code: 400

 ** ValidationException **   
 An invalid or malformed request.  
HTTP Status Code: 400

## See Also
<a name="API_CreateDatabase_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-write-2018-11-01/CreateDatabase) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-write-2018-11-01/CreateDatabase) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/CreateDatabase) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-write-2018-11-01/CreateDatabase) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/CreateDatabase) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-write-2018-11-01/CreateDatabase) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-write-2018-11-01/CreateDatabase) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-write-2018-11-01/CreateDatabase) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-write-2018-11-01/CreateDatabase) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/CreateDatabase) 

# CreateTable
<a name="API_CreateTable"></a>

Adds a new table to an existing database in your account. In an AWS account, table names must be at least unique within each Region if they are in the same database. You might have identical table names in the same Region if the tables are in separate databases. While creating the table, you must specify the table name, database name, and the retention properties. [Service quotas apply](https://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html). See [code sample](https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.create-table.html) for details. 

## Request Syntax
<a name="API_CreateTable_RequestSyntax"></a>

```
{
   "DatabaseName": "string",
   "MagneticStoreWriteProperties": { 
      "EnableMagneticStoreWrites": boolean,
      "MagneticStoreRejectedDataLocation": { 
         "S3Configuration": { 
            "BucketName": "string",
            "EncryptionOption": "string",
            "KmsKeyId": "string",
            "ObjectKeyPrefix": "string"
         }
      }
   },
   "RetentionProperties": { 
      "MagneticStoreRetentionPeriodInDays": number,
      "MemoryStoreRetentionPeriodInHours": number
   },
   "Schema": { 
      "CompositePartitionKey": [ 
         { 
            "EnforcementInRecord": "string",
            "Name": "string",
            "Type": "string"
         }
      ]
   },
   "TableName": "string",
   "Tags": [ 
      { 
         "Key": "string",
         "Value": "string"
      }
   ]
}
```

## Request Parameters
<a name="API_CreateTable_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [DatabaseName](#API_CreateTable_RequestSyntax) **   <a name="timestream-CreateTable-request-DatabaseName"></a>
The name of the Timestream database.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 256.  
Pattern: `[a-zA-Z0-9_.-]+`   
Required: Yes

 ** [MagneticStoreWriteProperties](#API_CreateTable_RequestSyntax) **   <a name="timestream-CreateTable-request-MagneticStoreWriteProperties"></a>
Contains properties to set on the table when enabling magnetic store writes.  
Type: [MagneticStoreWriteProperties](API_MagneticStoreWriteProperties.md) object  
Required: No

 ** [RetentionProperties](#API_CreateTable_RequestSyntax) **   <a name="timestream-CreateTable-request-RetentionProperties"></a>
The duration for which your time-series data must be stored in the memory store and the magnetic store.  
Type: [RetentionProperties](API_RetentionProperties.md) object  
Required: No

 ** [Schema](#API_CreateTable_RequestSyntax) **   <a name="timestream-CreateTable-request-Schema"></a>
 The schema of the table.   
Type: [Schema](API_Schema.md) object  
Required: No

 ** [TableName](#API_CreateTable_RequestSyntax) **   <a name="timestream-CreateTable-request-TableName"></a>
The name of the Timestream table.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 256.  
Pattern: `[a-zA-Z0-9_.-]+`   
Required: Yes

 ** [Tags](#API_CreateTable_RequestSyntax) **   <a name="timestream-CreateTable-request-Tags"></a>
 A list of key-value pairs to label the table.   
Type: Array of [Tag](API_Tag.md) objects  
Array Members: Minimum number of 0 items. Maximum number of 200 items.  
Required: No

## Response Syntax
<a name="API_CreateTable_ResponseSyntax"></a>

```
{
   "Table": { 
      "Arn": "string",
      "CreationTime": number,
      "DatabaseName": "string",
      "LastUpdatedTime": number,
      "MagneticStoreWriteProperties": { 
         "EnableMagneticStoreWrites": boolean,
         "MagneticStoreRejectedDataLocation": { 
            "S3Configuration": { 
               "BucketName": "string",
               "EncryptionOption": "string",
               "KmsKeyId": "string",
               "ObjectKeyPrefix": "string"
            }
         }
      },
      "RetentionProperties": { 
         "MagneticStoreRetentionPeriodInDays": number,
         "MemoryStoreRetentionPeriodInHours": number
      },
      "Schema": { 
         "CompositePartitionKey": [ 
            { 
               "EnforcementInRecord": "string",
               "Name": "string",
               "Type": "string"
            }
         ]
      },
      "TableName": "string",
      "TableStatus": "string"
   }
}
```

## Response Elements
<a name="API_CreateTable_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [Table](#API_CreateTable_ResponseSyntax) **   <a name="timestream-CreateTable-response-Table"></a>
The newly created Timestream table.  
Type: [Table](API_Table.md) object

## Errors
<a name="API_CreateTable_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You are not authorized to perform this action.  
HTTP Status Code: 400

 ** ConflictException **   
Timestream was unable to process this request because it contains resource that already exists.  
HTTP Status Code: 400

 ** InternalServerException **   
 Timestream was unable to fully process this request because of an internal server error.  
HTTP Status Code: 500

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The operation tried to access a nonexistent resource. The resource might not be specified correctly, or its status might not be ACTIVE.  
HTTP Status Code: 400

 ** ServiceQuotaExceededException **   
 The instance quota of resource exceeded for this account.  
HTTP Status Code: 400

 ** ThrottlingException **   
 Too many requests were made by a user and they exceeded the service quotas. The request was throttled.  
HTTP Status Code: 400

 ** ValidationException **   
 An invalid or malformed request.  
HTTP Status Code: 400

## See Also
<a name="API_CreateTable_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-write-2018-11-01/CreateTable) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-write-2018-11-01/CreateTable) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/CreateTable) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-write-2018-11-01/CreateTable) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/CreateTable) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-write-2018-11-01/CreateTable) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-write-2018-11-01/CreateTable) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-write-2018-11-01/CreateTable) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-write-2018-11-01/CreateTable) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/CreateTable) 

# DeleteDatabase
<a name="API_DeleteDatabase"></a>

Deletes a given Timestream database. *This is an irreversible operation. After a database is deleted, the time-series data from its tables cannot be recovered.* 

**Note**  
All tables in the database must be deleted first, or a ValidationException error will be thrown.   
Due to the nature of distributed retries, the operation can return either success or a ResourceNotFoundException. Clients should consider them equivalent.

See [code sample](https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.delete-db.html) for details.

## Request Syntax
<a name="API_DeleteDatabase_RequestSyntax"></a>

```
{
   "DatabaseName": "string"
}
```

## Request Parameters
<a name="API_DeleteDatabase_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [DatabaseName](#API_DeleteDatabase_RequestSyntax) **   <a name="timestream-DeleteDatabase-request-DatabaseName"></a>
The name of the Timestream database to be deleted.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 256.  
Required: Yes

## Response Elements
<a name="API_DeleteDatabase_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response with an empty HTTP body.

## Errors
<a name="API_DeleteDatabase_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You are not authorized to perform this action.  
HTTP Status Code: 400

 ** InternalServerException **   
 Timestream was unable to fully process this request because of an internal server error.  
HTTP Status Code: 500

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The operation tried to access a nonexistent resource. The resource might not be specified correctly, or its status might not be ACTIVE.  
HTTP Status Code: 400

 ** ThrottlingException **   
 Too many requests were made by a user and they exceeded the service quotas. The request was throttled.  
HTTP Status Code: 400

 ** ValidationException **   
 An invalid or malformed request.  
HTTP Status Code: 400

## See Also
<a name="API_DeleteDatabase_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-write-2018-11-01/DeleteDatabase) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-write-2018-11-01/DeleteDatabase) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/DeleteDatabase) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-write-2018-11-01/DeleteDatabase) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/DeleteDatabase) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-write-2018-11-01/DeleteDatabase) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-write-2018-11-01/DeleteDatabase) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-write-2018-11-01/DeleteDatabase) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-write-2018-11-01/DeleteDatabase) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/DeleteDatabase) 

# DeleteTable
<a name="API_DeleteTable"></a>

Deletes a given Timestream table. This is an irreversible operation. After a Timestream database table is deleted, the time-series data stored in the table cannot be recovered. 

**Note**  
Due to the nature of distributed retries, the operation can return either success or a ResourceNotFoundException. Clients should consider them equivalent.

See [code sample](https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.delete-table.html) for details.

## Request Syntax
<a name="API_DeleteTable_RequestSyntax"></a>

```
{
   "DatabaseName": "string",
   "TableName": "string"
}
```

## Request Parameters
<a name="API_DeleteTable_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [DatabaseName](#API_DeleteTable_RequestSyntax) **   <a name="timestream-DeleteTable-request-DatabaseName"></a>
The name of the database where the Timestream database is to be deleted.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 256.  
Required: Yes

 ** [TableName](#API_DeleteTable_RequestSyntax) **   <a name="timestream-DeleteTable-request-TableName"></a>
The name of the Timestream table to be deleted.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 256.  
Required: Yes

## Response Elements
<a name="API_DeleteTable_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response with an empty HTTP body.

## Errors
<a name="API_DeleteTable_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You are not authorized to perform this action.  
HTTP Status Code: 400

 ** InternalServerException **   
 Timestream was unable to fully process this request because of an internal server error.  
HTTP Status Code: 500

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The operation tried to access a nonexistent resource. The resource might not be specified correctly, or its status might not be ACTIVE.  
HTTP Status Code: 400

 ** ThrottlingException **   
 Too many requests were made by a user and they exceeded the service quotas. The request was throttled.  
HTTP Status Code: 400

 ** ValidationException **   
 An invalid or malformed request.  
HTTP Status Code: 400

## See Also
<a name="API_DeleteTable_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-write-2018-11-01/DeleteTable) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-write-2018-11-01/DeleteTable) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/DeleteTable) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-write-2018-11-01/DeleteTable) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/DeleteTable) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-write-2018-11-01/DeleteTable) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-write-2018-11-01/DeleteTable) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-write-2018-11-01/DeleteTable) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-write-2018-11-01/DeleteTable) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/DeleteTable) 

# DescribeBatchLoadTask
<a name="API_DescribeBatchLoadTask"></a>

Returns information about the batch load task, including configurations, mappings, progress, and other details. [Service quotas apply](https://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html). See [code sample](https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.describe-batch-load.html) for details.

## Request Syntax
<a name="API_DescribeBatchLoadTask_RequestSyntax"></a>

```
{
   "TaskId": "string"
}
```

## Request Parameters
<a name="API_DescribeBatchLoadTask_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [TaskId](#API_DescribeBatchLoadTask_RequestSyntax) **   <a name="timestream-DescribeBatchLoadTask-request-TaskId"></a>
The ID of the batch load task.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 32.  
Pattern: `[A-Z0-9]+`   
Required: Yes

## Response Syntax
<a name="API_DescribeBatchLoadTask_ResponseSyntax"></a>

```
{
   "BatchLoadTaskDescription": { 
      "CreationTime": number,
      "DataModelConfiguration": { 
         "DataModel": { 
            "DimensionMappings": [ 
               { 
                  "DestinationColumn": "string",
                  "SourceColumn": "string"
               }
            ],
            "MeasureNameColumn": "string",
            "MixedMeasureMappings": [ 
               { 
                  "MeasureName": "string",
                  "MeasureValueType": "string",
                  "MultiMeasureAttributeMappings": [ 
                     { 
                        "MeasureValueType": "string",
                        "SourceColumn": "string",
                        "TargetMultiMeasureAttributeName": "string"
                     }
                  ],
                  "SourceColumn": "string",
                  "TargetMeasureName": "string"
               }
            ],
            "MultiMeasureMappings": { 
               "MultiMeasureAttributeMappings": [ 
                  { 
                     "MeasureValueType": "string",
                     "SourceColumn": "string",
                     "TargetMultiMeasureAttributeName": "string"
                  }
               ],
               "TargetMultiMeasureName": "string"
            },
            "TimeColumn": "string",
            "TimeUnit": "string"
         },
         "DataModelS3Configuration": { 
            "BucketName": "string",
            "ObjectKey": "string"
         }
      },
      "DataSourceConfiguration": { 
         "CsvConfiguration": { 
            "ColumnSeparator": "string",
            "EscapeChar": "string",
            "NullValue": "string",
            "QuoteChar": "string",
            "TrimWhiteSpace": boolean
         },
         "DataFormat": "string",
         "DataSourceS3Configuration": { 
            "BucketName": "string",
            "ObjectKeyPrefix": "string"
         }
      },
      "ErrorMessage": "string",
      "LastUpdatedTime": number,
      "ProgressReport": { 
         "BytesMetered": number,
         "FileFailures": number,
         "ParseFailures": number,
         "RecordIngestionFailures": number,
         "RecordsIngested": number,
         "RecordsProcessed": number
      },
      "RecordVersion": number,
      "ReportConfiguration": { 
         "ReportS3Configuration": { 
            "BucketName": "string",
            "EncryptionOption": "string",
            "KmsKeyId": "string",
            "ObjectKeyPrefix": "string"
         }
      },
      "ResumableUntil": number,
      "TargetDatabaseName": "string",
      "TargetTableName": "string",
      "TaskId": "string",
      "TaskStatus": "string"
   }
}
```

## Response Elements
<a name="API_DescribeBatchLoadTask_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [BatchLoadTaskDescription](#API_DescribeBatchLoadTask_ResponseSyntax) **   <a name="timestream-DescribeBatchLoadTask-response-BatchLoadTaskDescription"></a>
Description of the batch load task.  
Type: [BatchLoadTaskDescription](API_BatchLoadTaskDescription.md) object

## Errors
<a name="API_DescribeBatchLoadTask_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You are not authorized to perform this action.  
HTTP Status Code: 400

 ** InternalServerException **   
 Timestream was unable to fully process this request because of an internal server error.  
HTTP Status Code: 500

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The operation tried to access a nonexistent resource. The resource might not be specified correctly, or its status might not be ACTIVE.  
HTTP Status Code: 400

 ** ThrottlingException **   
 Too many requests were made by a user and they exceeded the service quotas. The request was throttled.  
HTTP Status Code: 400

## See Also
<a name="API_DescribeBatchLoadTask_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-write-2018-11-01/DescribeBatchLoadTask) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-write-2018-11-01/DescribeBatchLoadTask) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/DescribeBatchLoadTask) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-write-2018-11-01/DescribeBatchLoadTask) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/DescribeBatchLoadTask) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-write-2018-11-01/DescribeBatchLoadTask) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-write-2018-11-01/DescribeBatchLoadTask) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-write-2018-11-01/DescribeBatchLoadTask) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-write-2018-11-01/DescribeBatchLoadTask) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/DescribeBatchLoadTask) 

# DescribeDatabase
<a name="API_DescribeDatabase"></a>

Returns information about the database, including the database name, time that the database was created, and the total number of tables found within the database. [Service quotas apply](https://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html). See [code sample](https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.describe-db.html) for details.

## Request Syntax
<a name="API_DescribeDatabase_RequestSyntax"></a>

```
{
   "DatabaseName": "string"
}
```

## Request Parameters
<a name="API_DescribeDatabase_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [DatabaseName](#API_DescribeDatabase_RequestSyntax) **   <a name="timestream-DescribeDatabase-request-DatabaseName"></a>
The name of the Timestream database.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 256.  
Required: Yes

## Response Syntax
<a name="API_DescribeDatabase_ResponseSyntax"></a>

```
{
   "Database": { 
      "Arn": "string",
      "CreationTime": number,
      "DatabaseName": "string",
      "KmsKeyId": "string",
      "LastUpdatedTime": number,
      "TableCount": number
   }
}
```

## Response Elements
<a name="API_DescribeDatabase_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [Database](#API_DescribeDatabase_ResponseSyntax) **   <a name="timestream-DescribeDatabase-response-Database"></a>
The name of the Timestream table.  
Type: [Database](API_Database.md) object

## Errors
<a name="API_DescribeDatabase_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You are not authorized to perform this action.  
HTTP Status Code: 400

 ** InternalServerException **   
 Timestream was unable to fully process this request because of an internal server error.  
HTTP Status Code: 500

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The operation tried to access a nonexistent resource. The resource might not be specified correctly, or its status might not be ACTIVE.  
HTTP Status Code: 400

 ** ThrottlingException **   
 Too many requests were made by a user and they exceeded the service quotas. The request was throttled.  
HTTP Status Code: 400

 ** ValidationException **   
 An invalid or malformed request.  
HTTP Status Code: 400

## See Also
<a name="API_DescribeDatabase_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-write-2018-11-01/DescribeDatabase) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-write-2018-11-01/DescribeDatabase) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/DescribeDatabase) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-write-2018-11-01/DescribeDatabase) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/DescribeDatabase) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-write-2018-11-01/DescribeDatabase) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-write-2018-11-01/DescribeDatabase) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-write-2018-11-01/DescribeDatabase) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-write-2018-11-01/DescribeDatabase) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/DescribeDatabase) 

# DescribeEndpoints
<a name="API_DescribeEndpoints"></a>

Returns a list of available endpoints to make Timestream API calls against. This API operation is available through both the Write and Query APIs.

Because the Timestream SDKs are designed to transparently work with the service’s architecture, including the management and mapping of the service endpoints, *we don't recommend that you use this API operation unless*:
+ You are using [VPC endpoints (AWS PrivateLink) with Timestream](https://docs.aws.amazon.com/timestream/latest/developerguide/VPCEndpoints) 
+ Your application uses a programming language that does not yet have SDK support
+ You require better control over the client-side implementation

For detailed information on how and when to use and implement DescribeEndpoints, see [The Endpoint Discovery Pattern](https://docs.aws.amazon.com/timestream/latest/developerguide/Using.API.html#Using-API.endpoint-discovery).

## Response Syntax
<a name="API_DescribeEndpoints_ResponseSyntax"></a>

```
{
   "Endpoints": [ 
      { 
         "Address": "string",
         "CachePeriodInMinutes": number
      }
   ]
}
```

## Response Elements
<a name="API_DescribeEndpoints_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [Endpoints](#API_DescribeEndpoints_ResponseSyntax) **   <a name="timestream-DescribeEndpoints-response-Endpoints"></a>
An `Endpoints` object is returned when a `DescribeEndpoints` request is made.  
Type: Array of [Endpoint](API_Endpoint.md) objects

## Errors
<a name="API_DescribeEndpoints_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** InternalServerException **   
 Timestream was unable to fully process this request because of an internal server error.  
HTTP Status Code: 500

 ** ThrottlingException **   
 Too many requests were made by a user and they exceeded the service quotas. The request was throttled.  
HTTP Status Code: 400

 ** ValidationException **   
 An invalid or malformed request.  
HTTP Status Code: 400

## See Also
<a name="API_DescribeEndpoints_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-write-2018-11-01/DescribeEndpoints) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-write-2018-11-01/DescribeEndpoints) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/DescribeEndpoints) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-write-2018-11-01/DescribeEndpoints) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/DescribeEndpoints) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-write-2018-11-01/DescribeEndpoints) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-write-2018-11-01/DescribeEndpoints) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-write-2018-11-01/DescribeEndpoints) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-write-2018-11-01/DescribeEndpoints) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/DescribeEndpoints) 

# DescribeTable
<a name="API_DescribeTable"></a>

Returns information about the table, including the table name, database name, retention duration of the memory store and the magnetic store. [Service quotas apply](https://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html). See [code sample](https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.describe-table.html) for details. 

## Request Syntax
<a name="API_DescribeTable_RequestSyntax"></a>

```
{
   "DatabaseName": "string",
   "TableName": "string"
}
```

## Request Parameters
<a name="API_DescribeTable_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [DatabaseName](#API_DescribeTable_RequestSyntax) **   <a name="timestream-DescribeTable-request-DatabaseName"></a>
The name of the Timestream database.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 256.  
Required: Yes

 ** [TableName](#API_DescribeTable_RequestSyntax) **   <a name="timestream-DescribeTable-request-TableName"></a>
The name of the Timestream table.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 256.  
Required: Yes

## Response Syntax
<a name="API_DescribeTable_ResponseSyntax"></a>

```
{
   "Table": { 
      "Arn": "string",
      "CreationTime": number,
      "DatabaseName": "string",
      "LastUpdatedTime": number,
      "MagneticStoreWriteProperties": { 
         "EnableMagneticStoreWrites": boolean,
         "MagneticStoreRejectedDataLocation": { 
            "S3Configuration": { 
               "BucketName": "string",
               "EncryptionOption": "string",
               "KmsKeyId": "string",
               "ObjectKeyPrefix": "string"
            }
         }
      },
      "RetentionProperties": { 
         "MagneticStoreRetentionPeriodInDays": number,
         "MemoryStoreRetentionPeriodInHours": number
      },
      "Schema": { 
         "CompositePartitionKey": [ 
            { 
               "EnforcementInRecord": "string",
               "Name": "string",
               "Type": "string"
            }
         ]
      },
      "TableName": "string",
      "TableStatus": "string"
   }
}
```

## Response Elements
<a name="API_DescribeTable_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [Table](#API_DescribeTable_ResponseSyntax) **   <a name="timestream-DescribeTable-response-Table"></a>
The Timestream table.  
Type: [Table](API_Table.md) object

## Errors
<a name="API_DescribeTable_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You are not authorized to perform this action.  
HTTP Status Code: 400

 ** InternalServerException **   
 Timestream was unable to fully process this request because of an internal server error.  
HTTP Status Code: 500

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The operation tried to access a nonexistent resource. The resource might not be specified correctly, or its status might not be ACTIVE.  
HTTP Status Code: 400

 ** ThrottlingException **   
 Too many requests were made by a user and they exceeded the service quotas. The request was throttled.  
HTTP Status Code: 400

 ** ValidationException **   
 An invalid or malformed request.  
HTTP Status Code: 400

## See Also
<a name="API_DescribeTable_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-write-2018-11-01/DescribeTable) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-write-2018-11-01/DescribeTable) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/DescribeTable) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-write-2018-11-01/DescribeTable) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/DescribeTable) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-write-2018-11-01/DescribeTable) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-write-2018-11-01/DescribeTable) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-write-2018-11-01/DescribeTable) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-write-2018-11-01/DescribeTable) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/DescribeTable) 

# ListBatchLoadTasks
<a name="API_ListBatchLoadTasks"></a>

Provides a list of batch load tasks, along with the name, status, when the task is resumable until, and other details. See [code sample](https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.list-batch-load-tasks.html) for details.

## Request Syntax
<a name="API_ListBatchLoadTasks_RequestSyntax"></a>

```
{
   "MaxResults": number,
   "NextToken": "string",
   "TaskStatus": "string"
}
```

## Request Parameters
<a name="API_ListBatchLoadTasks_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [MaxResults](#API_ListBatchLoadTasks_RequestSyntax) **   <a name="timestream-ListBatchLoadTasks-request-MaxResults"></a>
The total number of items to return in the output. If the total number of items available is more than the value specified, a NextToken is provided in the output. To resume pagination, provide the NextToken value as argument of a subsequent API invocation.  
Type: Integer  
Valid Range: Minimum value of 1. Maximum value of 100.  
Required: No

 ** [NextToken](#API_ListBatchLoadTasks_RequestSyntax) **   <a name="timestream-ListBatchLoadTasks-request-NextToken"></a>
A token to specify where to start paginating. This is the NextToken from a previously truncated response.  
Type: String  
Required: No

 ** [TaskStatus](#API_ListBatchLoadTasks_RequestSyntax) **   <a name="timestream-ListBatchLoadTasks-request-TaskStatus"></a>
Status of the batch load task.  
Type: String  
Valid Values: `CREATED | IN_PROGRESS | FAILED | SUCCEEDED | PROGRESS_STOPPED | PENDING_RESUME`   
Required: No

## Response Syntax
<a name="API_ListBatchLoadTasks_ResponseSyntax"></a>

```
{
   "BatchLoadTasks": [ 
      { 
         "CreationTime": number,
         "DatabaseName": "string",
         "LastUpdatedTime": number,
         "ResumableUntil": number,
         "TableName": "string",
         "TaskId": "string",
         "TaskStatus": "string"
      }
   ],
   "NextToken": "string"
}
```

## Response Elements
<a name="API_ListBatchLoadTasks_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [BatchLoadTasks](#API_ListBatchLoadTasks_ResponseSyntax) **   <a name="timestream-ListBatchLoadTasks-response-BatchLoadTasks"></a>
A list of batch load task details.  
Type: Array of [BatchLoadTask](API_BatchLoadTask.md) objects

 ** [NextToken](#API_ListBatchLoadTasks_ResponseSyntax) **   <a name="timestream-ListBatchLoadTasks-response-NextToken"></a>
A token to specify where to start paginating. Provide the next ListBatchLoadTasksRequest.  
Type: String

## Errors
<a name="API_ListBatchLoadTasks_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You are not authorized to perform this action.  
HTTP Status Code: 400

 ** InternalServerException **   
 Timestream was unable to fully process this request because of an internal server error.  
HTTP Status Code: 500

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** ThrottlingException **   
 Too many requests were made by a user and they exceeded the service quotas. The request was throttled.  
HTTP Status Code: 400

 ** ValidationException **   
 An invalid or malformed request.  
HTTP Status Code: 400

## See Also
<a name="API_ListBatchLoadTasks_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-write-2018-11-01/ListBatchLoadTasks) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-write-2018-11-01/ListBatchLoadTasks) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/ListBatchLoadTasks) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-write-2018-11-01/ListBatchLoadTasks) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/ListBatchLoadTasks) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-write-2018-11-01/ListBatchLoadTasks) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-write-2018-11-01/ListBatchLoadTasks) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-write-2018-11-01/ListBatchLoadTasks) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-write-2018-11-01/ListBatchLoadTasks) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/ListBatchLoadTasks) 

# ListDatabases
<a name="API_ListDatabases"></a>

Returns a list of your Timestream databases. [Service quotas apply](https://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html). See [code sample](https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.list-db.html) for details. 

## Request Syntax
<a name="API_ListDatabases_RequestSyntax"></a>

```
{
   "MaxResults": number,
   "NextToken": "string"
}
```

## Request Parameters
<a name="API_ListDatabases_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [MaxResults](#API_ListDatabases_RequestSyntax) **   <a name="timestream-ListDatabases-request-MaxResults"></a>
The total number of items to return in the output. If the total number of items available is more than the value specified, a NextToken is provided in the output. To resume pagination, provide the NextToken value as argument of a subsequent API invocation.  
Type: Integer  
Valid Range: Minimum value of 1. Maximum value of 20.  
Required: No

 ** [NextToken](#API_ListDatabases_RequestSyntax) **   <a name="timestream-ListDatabases-request-NextToken"></a>
The pagination token. To resume pagination, provide the NextToken value as argument of a subsequent API invocation.  
Type: String  
Required: No

## Response Syntax
<a name="API_ListDatabases_ResponseSyntax"></a>

```
{
   "Databases": [ 
      { 
         "Arn": "string",
         "CreationTime": number,
         "DatabaseName": "string",
         "KmsKeyId": "string",
         "LastUpdatedTime": number,
         "TableCount": number
      }
   ],
   "NextToken": "string"
}
```

## Response Elements
<a name="API_ListDatabases_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [Databases](#API_ListDatabases_ResponseSyntax) **   <a name="timestream-ListDatabases-response-Databases"></a>
A list of database names.  
Type: Array of [Database](API_Database.md) objects

 ** [NextToken](#API_ListDatabases_ResponseSyntax) **   <a name="timestream-ListDatabases-response-NextToken"></a>
The pagination token. This parameter is returned when the response is truncated.  
Type: String

## Errors
<a name="API_ListDatabases_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You are not authorized to perform this action.  
HTTP Status Code: 400

 ** InternalServerException **   
 Timestream was unable to fully process this request because of an internal server error.  
HTTP Status Code: 500

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** ThrottlingException **   
 Too many requests were made by a user and they exceeded the service quotas. The request was throttled.  
HTTP Status Code: 400

 ** ValidationException **   
 An invalid or malformed request.  
HTTP Status Code: 400

## See Also
<a name="API_ListDatabases_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-write-2018-11-01/ListDatabases) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-write-2018-11-01/ListDatabases) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/ListDatabases) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-write-2018-11-01/ListDatabases) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/ListDatabases) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-write-2018-11-01/ListDatabases) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-write-2018-11-01/ListDatabases) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-write-2018-11-01/ListDatabases) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-write-2018-11-01/ListDatabases) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/ListDatabases) 

# ListTables
<a name="API_ListTables"></a>

Provides a list of tables, along with the name, status, and retention properties of each table. See [code sample](https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.list-table.html) for details. 

## Request Syntax
<a name="API_ListTables_RequestSyntax"></a>

```
{
   "DatabaseName": "string",
   "MaxResults": number,
   "NextToken": "string"
}
```

## Request Parameters
<a name="API_ListTables_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [DatabaseName](#API_ListTables_RequestSyntax) **   <a name="timestream-ListTables-request-DatabaseName"></a>
The name of the Timestream database.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 256.  
Required: No

 ** [MaxResults](#API_ListTables_RequestSyntax) **   <a name="timestream-ListTables-request-MaxResults"></a>
The total number of items to return in the output. If the total number of items available is more than the value specified, a NextToken is provided in the output. To resume pagination, provide the NextToken value as argument of a subsequent API invocation.  
Type: Integer  
Valid Range: Minimum value of 1. Maximum value of 20.  
Required: No

 ** [NextToken](#API_ListTables_RequestSyntax) **   <a name="timestream-ListTables-request-NextToken"></a>
The pagination token. To resume pagination, provide the NextToken value as argument of a subsequent API invocation.  
Type: String  
Required: No

## Response Syntax
<a name="API_ListTables_ResponseSyntax"></a>

```
{
   "NextToken": "string",
   "Tables": [ 
      { 
         "Arn": "string",
         "CreationTime": number,
         "DatabaseName": "string",
         "LastUpdatedTime": number,
         "MagneticStoreWriteProperties": { 
            "EnableMagneticStoreWrites": boolean,
            "MagneticStoreRejectedDataLocation": { 
               "S3Configuration": { 
                  "BucketName": "string",
                  "EncryptionOption": "string",
                  "KmsKeyId": "string",
                  "ObjectKeyPrefix": "string"
               }
            }
         },
         "RetentionProperties": { 
            "MagneticStoreRetentionPeriodInDays": number,
            "MemoryStoreRetentionPeriodInHours": number
         },
         "Schema": { 
            "CompositePartitionKey": [ 
               { 
                  "EnforcementInRecord": "string",
                  "Name": "string",
                  "Type": "string"
               }
            ]
         },
         "TableName": "string",
         "TableStatus": "string"
      }
   ]
}
```

## Response Elements
<a name="API_ListTables_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [NextToken](#API_ListTables_ResponseSyntax) **   <a name="timestream-ListTables-response-NextToken"></a>
A token to specify where to start paginating. This is the NextToken from a previously truncated response.  
Type: String

 ** [Tables](#API_ListTables_ResponseSyntax) **   <a name="timestream-ListTables-response-Tables"></a>
A list of tables.  
Type: Array of [Table](API_Table.md) objects

## Errors
<a name="API_ListTables_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You are not authorized to perform this action.  
HTTP Status Code: 400

 ** InternalServerException **   
 Timestream was unable to fully process this request because of an internal server error.  
HTTP Status Code: 500

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The operation tried to access a nonexistent resource. The resource might not be specified correctly, or its status might not be ACTIVE.  
HTTP Status Code: 400

 ** ThrottlingException **   
 Too many requests were made by a user and they exceeded the service quotas. The request was throttled.  
HTTP Status Code: 400

 ** ValidationException **   
 An invalid or malformed request.  
HTTP Status Code: 400

## See Also
<a name="API_ListTables_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-write-2018-11-01/ListTables) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-write-2018-11-01/ListTables) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/ListTables) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-write-2018-11-01/ListTables) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/ListTables) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-write-2018-11-01/ListTables) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-write-2018-11-01/ListTables) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-write-2018-11-01/ListTables) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-write-2018-11-01/ListTables) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/ListTables) 

# ListTagsForResource
<a name="API_ListTagsForResource"></a>

 Lists all tags on a Timestream resource. 

## Request Syntax
<a name="API_ListTagsForResource_RequestSyntax"></a>

```
{
   "ResourceARN": "string"
}
```

## Request Parameters
<a name="API_ListTagsForResource_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [ResourceARN](#API_ListTagsForResource_RequestSyntax) **   <a name="timestream-ListTagsForResource-request-ResourceARN"></a>
 The Timestream resource with tags to be listed. This value is an Amazon Resource Name (ARN).   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 1011.  
Required: Yes

## Response Syntax
<a name="API_ListTagsForResource_ResponseSyntax"></a>

```
{
   "Tags": [ 
      { 
         "Key": "string",
         "Value": "string"
      }
   ]
}
```

## Response Elements
<a name="API_ListTagsForResource_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [Tags](#API_ListTagsForResource_ResponseSyntax) **   <a name="timestream-ListTagsForResource-response-Tags"></a>
 The tags currently associated with the Timestream resource.   
Type: Array of [Tag](API_Tag.md) objects  
Array Members: Minimum number of 0 items. Maximum number of 200 items.

## Errors
<a name="API_ListTagsForResource_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The operation tried to access a nonexistent resource. The resource might not be specified correctly, or its status might not be ACTIVE.  
HTTP Status Code: 400

 ** ThrottlingException **   
 Too many requests were made by a user and they exceeded the service quotas. The request was throttled.  
HTTP Status Code: 400

 ** ValidationException **   
 An invalid or malformed request.  
HTTP Status Code: 400

## See Also
<a name="API_ListTagsForResource_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-write-2018-11-01/ListTagsForResource) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-write-2018-11-01/ListTagsForResource) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/ListTagsForResource) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-write-2018-11-01/ListTagsForResource) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/ListTagsForResource) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-write-2018-11-01/ListTagsForResource) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-write-2018-11-01/ListTagsForResource) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-write-2018-11-01/ListTagsForResource) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-write-2018-11-01/ListTagsForResource) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/ListTagsForResource) 

# ResumeBatchLoadTask
<a name="API_ResumeBatchLoadTask"></a>

 

## Request Syntax
<a name="API_ResumeBatchLoadTask_RequestSyntax"></a>

```
{
   "TaskId": "string"
}
```

## Request Parameters
<a name="API_ResumeBatchLoadTask_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [TaskId](#API_ResumeBatchLoadTask_RequestSyntax) **   <a name="timestream-ResumeBatchLoadTask-request-TaskId"></a>
The ID of the batch load task to resume.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 32.  
Pattern: `[A-Z0-9]+`   
Required: Yes

## Response Elements
<a name="API_ResumeBatchLoadTask_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response with an empty HTTP body.

## Errors
<a name="API_ResumeBatchLoadTask_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You are not authorized to perform this action.  
HTTP Status Code: 400

 ** InternalServerException **   
 Timestream was unable to fully process this request because of an internal server error.  
HTTP Status Code: 500

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The operation tried to access a nonexistent resource. The resource might not be specified correctly, or its status might not be ACTIVE.  
HTTP Status Code: 400

 ** ThrottlingException **   
 Too many requests were made by a user and they exceeded the service quotas. The request was throttled.  
HTTP Status Code: 400

 ** ValidationException **   
 An invalid or malformed request.  
HTTP Status Code: 400

## See Also
<a name="API_ResumeBatchLoadTask_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-write-2018-11-01/ResumeBatchLoadTask) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-write-2018-11-01/ResumeBatchLoadTask) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/ResumeBatchLoadTask) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-write-2018-11-01/ResumeBatchLoadTask) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/ResumeBatchLoadTask) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-write-2018-11-01/ResumeBatchLoadTask) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-write-2018-11-01/ResumeBatchLoadTask) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-write-2018-11-01/ResumeBatchLoadTask) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-write-2018-11-01/ResumeBatchLoadTask) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/ResumeBatchLoadTask) 

# TagResource
<a name="API_TagResource"></a>

 Associates a set of tags with a Timestream resource. You can then activate these user-defined tags so that they appear on the Billing and Cost Management console for cost allocation tracking. 

## Request Syntax
<a name="API_TagResource_RequestSyntax"></a>

```
{
   "ResourceARN": "string",
   "Tags": [ 
      { 
         "Key": "string",
         "Value": "string"
      }
   ]
}
```

## Request Parameters
<a name="API_TagResource_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [ResourceARN](#API_TagResource_RequestSyntax) **   <a name="timestream-TagResource-request-ResourceARN"></a>
 Identifies the Timestream resource to which tags should be added. This value is an Amazon Resource Name (ARN).   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 1011.  
Required: Yes

 ** [Tags](#API_TagResource_RequestSyntax) **   <a name="timestream-TagResource-request-Tags"></a>
 The tags to be assigned to the Timestream resource.   
Type: Array of [Tag](API_Tag.md) objects  
Array Members: Minimum number of 0 items. Maximum number of 200 items.  
Required: Yes

## Response Elements
<a name="API_TagResource_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response with an empty HTTP body.

## Errors
<a name="API_TagResource_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The operation tried to access a nonexistent resource. The resource might not be specified correctly, or its status might not be ACTIVE.  
HTTP Status Code: 400

 ** ServiceQuotaExceededException **   
 The instance quota of resource exceeded for this account.  
HTTP Status Code: 400

 ** ThrottlingException **   
 Too many requests were made by a user and they exceeded the service quotas. The request was throttled.  
HTTP Status Code: 400

 ** ValidationException **   
 An invalid or malformed request.  
HTTP Status Code: 400

## See Also
<a name="API_TagResource_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-write-2018-11-01/TagResource) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-write-2018-11-01/TagResource) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/TagResource) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-write-2018-11-01/TagResource) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/TagResource) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-write-2018-11-01/TagResource) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-write-2018-11-01/TagResource) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-write-2018-11-01/TagResource) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-write-2018-11-01/TagResource) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/TagResource) 

# UntagResource
<a name="API_UntagResource"></a>

 Removes the association of tags from a Timestream resource. 

## Request Syntax
<a name="API_UntagResource_RequestSyntax"></a>

```
{
   "ResourceARN": "string",
   "TagKeys": [ "string" ]
}
```

## Request Parameters
<a name="API_UntagResource_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [ResourceARN](#API_UntagResource_RequestSyntax) **   <a name="timestream-UntagResource-request-ResourceARN"></a>
 The Timestream resource that the tags will be removed from. This value is an Amazon Resource Name (ARN).   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 1011.  
Required: Yes

 ** [TagKeys](#API_UntagResource_RequestSyntax) **   <a name="timestream-UntagResource-request-TagKeys"></a>
 A list of tags keys. Existing tags of the resource whose keys are members of this list will be removed from the Timestream resource.   
Type: Array of strings  
Array Members: Minimum number of 0 items. Maximum number of 200 items.  
Length Constraints: Minimum length of 1. Maximum length of 128.  
Required: Yes

## Response Elements
<a name="API_UntagResource_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response with an empty HTTP body.

## Errors
<a name="API_UntagResource_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The operation tried to access a nonexistent resource. The resource might not be specified correctly, or its status might not be ACTIVE.  
HTTP Status Code: 400

 ** ServiceQuotaExceededException **   
 The instance quota of resource exceeded for this account.  
HTTP Status Code: 400

 ** ThrottlingException **   
 Too many requests were made by a user and they exceeded the service quotas. The request was throttled.  
HTTP Status Code: 400

 ** ValidationException **   
 An invalid or malformed request.  
HTTP Status Code: 400

## See Also
<a name="API_UntagResource_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-write-2018-11-01/UntagResource) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-write-2018-11-01/UntagResource) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/UntagResource) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-write-2018-11-01/UntagResource) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/UntagResource) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-write-2018-11-01/UntagResource) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-write-2018-11-01/UntagResource) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-write-2018-11-01/UntagResource) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-write-2018-11-01/UntagResource) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/UntagResource) 

# UpdateDatabase
<a name="API_UpdateDatabase"></a>

 Modifies the AWS KMS key for an existing database. While updating the database, you must specify the database name and the identifier of the new AWS KMS key to be used (`KmsKeyId`). If there are any concurrent `UpdateDatabase` requests, first writer wins. 

See [code sample](https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.update-db.html) for details.

## Request Syntax
<a name="API_UpdateDatabase_RequestSyntax"></a>

```
{
   "DatabaseName": "string",
   "KmsKeyId": "string"
}
```

## Request Parameters
<a name="API_UpdateDatabase_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [DatabaseName](#API_UpdateDatabase_RequestSyntax) **   <a name="timestream-UpdateDatabase-request-DatabaseName"></a>
 The name of the database.   
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 256.  
Required: Yes

 ** [KmsKeyId](#API_UpdateDatabase_RequestSyntax) **   <a name="timestream-UpdateDatabase-request-KmsKeyId"></a>
 The identifier of the new AWS KMS key (`KmsKeyId`) to be used to encrypt the data stored in the database. If the `KmsKeyId` currently registered with the database is the same as the `KmsKeyId` in the request, there will not be any update.   
You can specify the `KmsKeyId` using any of the following:  
+ Key ID: `1234abcd-12ab-34cd-56ef-1234567890ab` 
+ Key ARN: `arn:aws:kms:us-east-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab` 
+ Alias name: `alias/ExampleAlias` 
+ Alias ARN: `arn:aws:kms:us-east-1:111122223333:alias/ExampleAlias` 
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: Yes

## Response Syntax
<a name="API_UpdateDatabase_ResponseSyntax"></a>

```
{
   "Database": { 
      "Arn": "string",
      "CreationTime": number,
      "DatabaseName": "string",
      "KmsKeyId": "string",
      "LastUpdatedTime": number,
      "TableCount": number
   }
}
```

## Response Elements
<a name="API_UpdateDatabase_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [Database](#API_UpdateDatabase_ResponseSyntax) **   <a name="timestream-UpdateDatabase-response-Database"></a>
A top-level container for a table. Databases and tables are the fundamental management concepts in Amazon Timestream. All tables in a database are encrypted with the same AWS KMS key.  
Type: [Database](API_Database.md) object

## Errors
<a name="API_UpdateDatabase_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You are not authorized to perform this action.  
HTTP Status Code: 400

 ** InternalServerException **   
 Timestream was unable to fully process this request because of an internal server error.  
HTTP Status Code: 500

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The operation tried to access a nonexistent resource. The resource might not be specified correctly, or its status might not be ACTIVE.  
HTTP Status Code: 400

 ** ServiceQuotaExceededException **   
 The instance quota of resource exceeded for this account.  
HTTP Status Code: 400

 ** ThrottlingException **   
 Too many requests were made by a user and they exceeded the service quotas. The request was throttled.  
HTTP Status Code: 400

 ** ValidationException **   
 An invalid or malformed request.  
HTTP Status Code: 400

## See Also
<a name="API_UpdateDatabase_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-write-2018-11-01/UpdateDatabase) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-write-2018-11-01/UpdateDatabase) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/UpdateDatabase) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-write-2018-11-01/UpdateDatabase) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/UpdateDatabase) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-write-2018-11-01/UpdateDatabase) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-write-2018-11-01/UpdateDatabase) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-write-2018-11-01/UpdateDatabase) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-write-2018-11-01/UpdateDatabase) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/UpdateDatabase) 

# UpdateTable
<a name="API_UpdateTable"></a>

Modifies the retention duration of the memory store and magnetic store for your Timestream table. Note that the change in retention duration takes effect immediately. For example, if the retention period of the memory store was initially set to 2 hours and then changed to 24 hours, the memory store will be capable of holding 24 hours of data, but will be populated with 24 hours of data 22 hours after this change was made. Timestream does not retrieve data from the magnetic store to populate the memory store. 

See [code sample](https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.update-table.html) for details.

## Request Syntax
<a name="API_UpdateTable_RequestSyntax"></a>

```
{
   "DatabaseName": "string",
   "MagneticStoreWriteProperties": { 
      "EnableMagneticStoreWrites": boolean,
      "MagneticStoreRejectedDataLocation": { 
         "S3Configuration": { 
            "BucketName": "string",
            "EncryptionOption": "string",
            "KmsKeyId": "string",
            "ObjectKeyPrefix": "string"
         }
      }
   },
   "RetentionProperties": { 
      "MagneticStoreRetentionPeriodInDays": number,
      "MemoryStoreRetentionPeriodInHours": number
   },
   "Schema": { 
      "CompositePartitionKey": [ 
         { 
            "EnforcementInRecord": "string",
            "Name": "string",
            "Type": "string"
         }
      ]
   },
   "TableName": "string"
}
```

## Request Parameters
<a name="API_UpdateTable_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [DatabaseName](#API_UpdateTable_RequestSyntax) **   <a name="timestream-UpdateTable-request-DatabaseName"></a>
The name of the Timestream database.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 256.  
Required: Yes

 ** [MagneticStoreWriteProperties](#API_UpdateTable_RequestSyntax) **   <a name="timestream-UpdateTable-request-MagneticStoreWriteProperties"></a>
Contains properties to set on the table when enabling magnetic store writes.  
Type: [MagneticStoreWriteProperties](API_MagneticStoreWriteProperties.md) object  
Required: No

 ** [RetentionProperties](#API_UpdateTable_RequestSyntax) **   <a name="timestream-UpdateTable-request-RetentionProperties"></a>
The retention duration of the memory store and the magnetic store.  
Type: [RetentionProperties](API_RetentionProperties.md) object  
Required: No

 ** [Schema](#API_UpdateTable_RequestSyntax) **   <a name="timestream-UpdateTable-request-Schema"></a>
 The schema of the table.   
Type: [Schema](API_Schema.md) object  
Required: No

 ** [TableName](#API_UpdateTable_RequestSyntax) **   <a name="timestream-UpdateTable-request-TableName"></a>
The name of the Timestream table.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 256.  
Required: Yes

## Response Syntax
<a name="API_UpdateTable_ResponseSyntax"></a>

```
{
   "Table": { 
      "Arn": "string",
      "CreationTime": number,
      "DatabaseName": "string",
      "LastUpdatedTime": number,
      "MagneticStoreWriteProperties": { 
         "EnableMagneticStoreWrites": boolean,
         "MagneticStoreRejectedDataLocation": { 
            "S3Configuration": { 
               "BucketName": "string",
               "EncryptionOption": "string",
               "KmsKeyId": "string",
               "ObjectKeyPrefix": "string"
            }
         }
      },
      "RetentionProperties": { 
         "MagneticStoreRetentionPeriodInDays": number,
         "MemoryStoreRetentionPeriodInHours": number
      },
      "Schema": { 
         "CompositePartitionKey": [ 
            { 
               "EnforcementInRecord": "string",
               "Name": "string",
               "Type": "string"
            }
         ]
      },
      "TableName": "string",
      "TableStatus": "string"
   }
}
```

## Response Elements
<a name="API_UpdateTable_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [Table](#API_UpdateTable_ResponseSyntax) **   <a name="timestream-UpdateTable-response-Table"></a>
The updated Timestream table.  
Type: [Table](API_Table.md) object

## Errors
<a name="API_UpdateTable_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You are not authorized to perform this action.  
HTTP Status Code: 400

 ** InternalServerException **   
 Timestream was unable to fully process this request because of an internal server error.  
HTTP Status Code: 500

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The operation tried to access a nonexistent resource. The resource might not be specified correctly, or its status might not be ACTIVE.  
HTTP Status Code: 400

 ** ThrottlingException **   
 Too many requests were made by a user and they exceeded the service quotas. The request was throttled.  
HTTP Status Code: 400

 ** ValidationException **   
 An invalid or malformed request.  
HTTP Status Code: 400

## See Also
<a name="API_UpdateTable_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-write-2018-11-01/UpdateTable) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-write-2018-11-01/UpdateTable) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/UpdateTable) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-write-2018-11-01/UpdateTable) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/UpdateTable) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-write-2018-11-01/UpdateTable) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-write-2018-11-01/UpdateTable) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-write-2018-11-01/UpdateTable) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-write-2018-11-01/UpdateTable) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/UpdateTable) 

# WriteRecords
<a name="API_WriteRecords"></a>

Enables you to write your time-series data into Timestream. You can specify a single data point or a batch of data points to be inserted into the system. Timestream offers you a flexible schema that auto detects the column names and data types for your Timestream tables based on the dimension names and data types of the data points you specify when invoking writes into the database. 

Timestream supports eventual consistency read semantics. This means that when you query data immediately after writing a batch of data into Timestream, the query results might not reflect the results of a recently completed write operation. The results may also include some stale data. If you repeat the query request after a short time, the results should return the latest data. [Service quotas apply](https://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html). 

See [code sample](https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.write.html) for details.

 **Upserts** 

You can use the `Version` parameter in a `WriteRecords` request to update data points. Timestream tracks a version number with each record. `Version` defaults to `1` when it's not specified for the record in the request. Timestream updates an existing record’s measure value along with its `Version` when it receives a write request with a higher `Version` number for that record. When it receives an update request where the measure value is the same as that of the existing record, Timestream still updates `Version`, if it is greater than the existing value of `Version`. You can update a data point as many times as desired, as long as the value of `Version` continuously increases. 

 For example, suppose you write a new record without indicating `Version` in the request. Timestream stores this record, and set `Version` to `1`. Now, suppose you try to update this record with a `WriteRecords` request of the same record with a different measure value but, like before, do not provide `Version`. In this case, Timestream will reject this update with a `RejectedRecordsException` since the updated record’s version is not greater than the existing value of Version. 

However, if you were to resend the update request with `Version` set to `2`, Timestream would then succeed in updating the record’s value, and the `Version` would be set to `2`. Next, suppose you sent a `WriteRecords` request with this same record and an identical measure value, but with `Version` set to `3`. In this case, Timestream would only update `Version` to `3`. Any further updates would need to send a version number greater than `3`, or the update requests would receive a `RejectedRecordsException`. 

## Request Syntax
<a name="API_WriteRecords_RequestSyntax"></a>

```
{
   "CommonAttributes": { 
      "Dimensions": [ 
         { 
            "DimensionValueType": "string",
            "Name": "string",
            "Value": "string"
         }
      ],
      "MeasureName": "string",
      "MeasureValue": "string",
      "MeasureValues": [ 
         { 
            "Name": "string",
            "Type": "string",
            "Value": "string"
         }
      ],
      "MeasureValueType": "string",
      "Time": "string",
      "TimeUnit": "string",
      "Version": number
   },
   "DatabaseName": "string",
   "Records": [ 
      { 
         "Dimensions": [ 
            { 
               "DimensionValueType": "string",
               "Name": "string",
               "Value": "string"
            }
         ],
         "MeasureName": "string",
         "MeasureValue": "string",
         "MeasureValues": [ 
            { 
               "Name": "string",
               "Type": "string",
               "Value": "string"
            }
         ],
         "MeasureValueType": "string",
         "Time": "string",
         "TimeUnit": "string",
         "Version": number
      }
   ],
   "TableName": "string"
}
```

## Request Parameters
<a name="API_WriteRecords_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [CommonAttributes](#API_WriteRecords_RequestSyntax) **   <a name="timestream-WriteRecords-request-CommonAttributes"></a>
A record that contains the common measure, dimension, time, and version attributes shared across all the records in the request. The measure and dimension attributes specified will be merged with the measure and dimension attributes in the records object when the data is written into Timestream. Dimensions may not overlap, or a `ValidationException` will be thrown. In other words, a record must contain dimensions with unique names.   
Type: [Record](API_Record.md) object  
Required: No

 ** [DatabaseName](#API_WriteRecords_RequestSyntax) **   <a name="timestream-WriteRecords-request-DatabaseName"></a>
The name of the Timestream database.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 256.  
Required: Yes

 ** [Records](#API_WriteRecords_RequestSyntax) **   <a name="timestream-WriteRecords-request-Records"></a>
An array of records that contain the unique measure, dimension, time, and version attributes for each time-series data point.  
Type: Array of [Record](API_Record.md) objects  
Array Members: Minimum number of 1 item. Maximum number of 100 items.  
Required: Yes

 ** [TableName](#API_WriteRecords_RequestSyntax) **   <a name="timestream-WriteRecords-request-TableName"></a>
The name of the Timestream table.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 256.  
Required: Yes

## Response Syntax
<a name="API_WriteRecords_ResponseSyntax"></a>

```
{
   "RecordsIngested": { 
      "MagneticStore": number,
      "MemoryStore": number,
      "Total": number
   }
}
```

## Response Elements
<a name="API_WriteRecords_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [RecordsIngested](#API_WriteRecords_ResponseSyntax) **   <a name="timestream-WriteRecords-response-RecordsIngested"></a>
Information on the records ingested by this request.  
Type: [RecordsIngested](API_RecordsIngested.md) object

## Errors
<a name="API_WriteRecords_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You are not authorized to perform this action.  
HTTP Status Code: 400

 ** InternalServerException **   
 Timestream was unable to fully process this request because of an internal server error.  
HTTP Status Code: 500

 ** InvalidEndpointException **   
The requested endpoint was not valid.  
HTTP Status Code: 400

 ** RejectedRecordsException **   
 WriteRecords would throw this exception in the following cases:   
+ Records with duplicate data where there are multiple records with the same dimensions, timestamps, and measure names but: 
  + Measure values are different
  + Version is not present in the request *or* the value of version in the new record is equal to or lower than the existing value

   In this case, if Timestream rejects data, the `ExistingVersion` field in the `RejectedRecords` response will indicate the current record’s version. To force an update, you can resend the request with a version for the record set to a value greater than the `ExistingVersion`.
+  Records with timestamps that lie outside the retention duration of the memory store. 
+  Records with dimensions or measures that exceed the Timestream defined limits. 
 For more information, see [Quotas](https://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html) in the Amazon Timestream Developer Guide.     
 ** RejectedRecords **   
 
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The operation tried to access a nonexistent resource. The resource might not be specified correctly, or its status might not be ACTIVE.  
HTTP Status Code: 400

 ** ThrottlingException **   
 Too many requests were made by a user and they exceeded the service quotas. The request was throttled.  
HTTP Status Code: 400

 ** ValidationException **   
 An invalid or malformed request.  
HTTP Status Code: 400

## See Also
<a name="API_WriteRecords_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-write-2018-11-01/WriteRecords) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-write-2018-11-01/WriteRecords) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/WriteRecords) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-write-2018-11-01/WriteRecords) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/WriteRecords) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-write-2018-11-01/WriteRecords) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-write-2018-11-01/WriteRecords) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-write-2018-11-01/WriteRecords) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-write-2018-11-01/WriteRecords) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/WriteRecords) 

# Amazon Timestream Query
<a name="API_Operations_Amazon_Timestream_Query"></a>

The following actions are supported by Amazon Timestream Query:
+  [CancelQuery](API_query_CancelQuery.md) 
+  [CreateScheduledQuery](API_query_CreateScheduledQuery.md) 
+  [DeleteScheduledQuery](API_query_DeleteScheduledQuery.md) 
+  [DescribeAccountSettings](API_query_DescribeAccountSettings.md) 
+  [DescribeEndpoints](API_query_DescribeEndpoints.md) 
+  [DescribeScheduledQuery](API_query_DescribeScheduledQuery.md) 
+  [ExecuteScheduledQuery](API_query_ExecuteScheduledQuery.md) 
+  [ListScheduledQueries](API_query_ListScheduledQueries.md) 
+  [ListTagsForResource](API_query_ListTagsForResource.md) 
+  [PrepareQuery](API_query_PrepareQuery.md) 
+  [Query](API_query_Query.md) 
+  [TagResource](API_query_TagResource.md) 
+  [UntagResource](API_query_UntagResource.md) 
+  [UpdateAccountSettings](API_query_UpdateAccountSettings.md) 
+  [UpdateScheduledQuery](API_query_UpdateScheduledQuery.md) 

# CancelQuery
<a name="API_query_CancelQuery"></a>

 Cancels a query that has been issued. Cancellation is provided only if the query has not completed running before the cancellation request was issued. Because cancellation is an idempotent operation, subsequent cancellation requests will return a `CancellationMessage`, indicating that the query has already been canceled. See [code sample](https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.cancel-query.html) for details. 

## Request Syntax
<a name="API_query_CancelQuery_RequestSyntax"></a>

```
{
   "QueryId": "string"
}
```

## Request Parameters
<a name="API_query_CancelQuery_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [QueryId](#API_query_CancelQuery_RequestSyntax) **   <a name="timestream-query_CancelQuery-request-QueryId"></a>
 The ID of the query that needs to be cancelled. `QueryID` is returned as part of the query result.   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 64.  
Pattern: `[a-zA-Z0-9]+`   
Required: Yes

## Response Syntax
<a name="API_query_CancelQuery_ResponseSyntax"></a>

```
{
   "CancellationMessage": "string"
}
```

## Response Elements
<a name="API_query_CancelQuery_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [CancellationMessage](#API_query_CancelQuery_ResponseSyntax) **   <a name="timestream-query_CancelQuery-response-CancellationMessage"></a>
 A `CancellationMessage` is returned when a `CancelQuery` request for the query specified by `QueryId` has already been issued.   
Type: String

## Errors
<a name="API_query_CancelQuery_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You do not have the necessary permissions to access the account settings.  
HTTP Status Code: 400

 ** InternalServerException **   
An internal server error occurred while processing the request.  
HTTP Status Code: 400

 ** InvalidEndpointException **   
The requested endpoint is invalid.  
HTTP Status Code: 400

 ** ThrottlingException **   
The request was throttled due to excessive requests.  
HTTP Status Code: 400

 ** ValidationException **   
 Invalid or malformed request.   
HTTP Status Code: 400

## See Also
<a name="API_query_CancelQuery_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-query-2018-11-01/CancelQuery) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-query-2018-11-01/CancelQuery) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/CancelQuery) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-query-2018-11-01/CancelQuery) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/CancelQuery) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-query-2018-11-01/CancelQuery) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-query-2018-11-01/CancelQuery) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-query-2018-11-01/CancelQuery) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-query-2018-11-01/CancelQuery) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/CancelQuery) 

# CreateScheduledQuery
<a name="API_query_CreateScheduledQuery"></a>

 Create a scheduled query that will be run on your behalf at the configured schedule. Timestream assumes the execution role provided as part of the `ScheduledQueryExecutionRoleArn` parameter to run the query. You can use the `NotificationConfiguration` parameter to configure notification for your scheduled query operations.

## Request Syntax
<a name="API_query_CreateScheduledQuery_RequestSyntax"></a>

```
{
   "ClientToken": "string",
   "ErrorReportConfiguration": { 
      "S3Configuration": { 
         "BucketName": "string",
         "EncryptionOption": "string",
         "ObjectKeyPrefix": "string"
      }
   },
   "KmsKeyId": "string",
   "Name": "string",
   "NotificationConfiguration": { 
      "SnsConfiguration": { 
         "TopicArn": "string"
      }
   },
   "QueryString": "string",
   "ScheduleConfiguration": { 
      "ScheduleExpression": "string"
   },
   "ScheduledQueryExecutionRoleArn": "string",
   "Tags": [ 
      { 
         "Key": "string",
         "Value": "string"
      }
   ],
   "TargetConfiguration": { 
      "TimestreamConfiguration": { 
         "DatabaseName": "string",
         "DimensionMappings": [ 
            { 
               "DimensionValueType": "string",
               "Name": "string"
            }
         ],
         "MeasureNameColumn": "string",
         "MixedMeasureMappings": [ 
            { 
               "MeasureName": "string",
               "MeasureValueType": "string",
               "MultiMeasureAttributeMappings": [ 
                  { 
                     "MeasureValueType": "string",
                     "SourceColumn": "string",
                     "TargetMultiMeasureAttributeName": "string"
                  }
               ],
               "SourceColumn": "string",
               "TargetMeasureName": "string"
            }
         ],
         "MultiMeasureMappings": { 
            "MultiMeasureAttributeMappings": [ 
               { 
                  "MeasureValueType": "string",
                  "SourceColumn": "string",
                  "TargetMultiMeasureAttributeName": "string"
               }
            ],
            "TargetMultiMeasureName": "string"
         },
         "TableName": "string",
         "TimeColumn": "string"
      }
   }
}
```

## Request Parameters
<a name="API_query_CreateScheduledQuery_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [ClientToken](#API_query_CreateScheduledQuery_RequestSyntax) **   <a name="timestream-query_CreateScheduledQuery-request-ClientToken"></a>
Using a ClientToken makes the call to CreateScheduledQuery idempotent, in other words, making the same request repeatedly will produce the same result. Making multiple identical CreateScheduledQuery requests has the same effect as making a single request.   
+  If CreateScheduledQuery is called without a `ClientToken`, the Query SDK generates a `ClientToken` on your behalf.
+  After 8 hours, any request with the same `ClientToken` is treated as a new request. 
Type: String  
Length Constraints: Minimum length of 32. Maximum length of 128.  
Required: No

 ** [ErrorReportConfiguration](#API_query_CreateScheduledQuery_RequestSyntax) **   <a name="timestream-query_CreateScheduledQuery-request-ErrorReportConfiguration"></a>
Configuration for error reporting. Error reports will be generated when a problem is encountered when writing the query results.   
Type: [ErrorReportConfiguration](API_query_ErrorReportConfiguration.md) object  
Required: Yes

 ** [KmsKeyId](#API_query_CreateScheduledQuery_RequestSyntax) **   <a name="timestream-query_CreateScheduledQuery-request-KmsKeyId"></a>
The Amazon KMS key used to encrypt the scheduled query resource, at-rest. If the Amazon KMS key is not specified, the scheduled query resource will be encrypted with a Timestream owned Amazon KMS key. To specify a KMS key, use the key ID, key ARN, alias name, or alias ARN. When using an alias name, prefix the name with *alias/*   
If ErrorReportConfiguration uses `SSE_KMS` as encryption type, the same KmsKeyId is used to encrypt the error report at rest.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: No

 ** [Name](#API_query_CreateScheduledQuery_RequestSyntax) **   <a name="timestream-query_CreateScheduledQuery-request-Name"></a>
Name of the scheduled query.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 64.  
Pattern: `[a-zA-Z0-9|!\-_*'\(\)]([a-zA-Z0-9]|[!\-_*'\(\)\/.])+`   
Required: Yes

 ** [NotificationConfiguration](#API_query_CreateScheduledQuery_RequestSyntax) **   <a name="timestream-query_CreateScheduledQuery-request-NotificationConfiguration"></a>
Notification configuration for the scheduled query. A notification is sent by Timestream when a query run finishes, when the state is updated or when you delete it.   
Type: [NotificationConfiguration](API_query_NotificationConfiguration.md) object  
Required: Yes

 ** [QueryString](#API_query_CreateScheduledQuery_RequestSyntax) **   <a name="timestream-query_CreateScheduledQuery-request-QueryString"></a>
The query string to run. Parameter names can be specified in the query string `@` character followed by an identifier. The named Parameter `@scheduled_runtime` is reserved and can be used in the query to get the time at which the query is scheduled to run.  
The timestamp calculated according to the ScheduleConfiguration parameter, will be the value of `@scheduled_runtime` paramater for each query run. For example, consider an instance of a scheduled query executing on 2021-12-01 00:00:00. For this instance, the `@scheduled_runtime` parameter is initialized to the timestamp 2021-12-01 00:00:00 when invoking the query.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 262144.  
Required: Yes

 ** [ScheduleConfiguration](#API_query_CreateScheduledQuery_RequestSyntax) **   <a name="timestream-query_CreateScheduledQuery-request-ScheduleConfiguration"></a>
The schedule configuration for the query.  
Type: [ScheduleConfiguration](API_query_ScheduleConfiguration.md) object  
Required: Yes

 ** [ScheduledQueryExecutionRoleArn](#API_query_CreateScheduledQuery_RequestSyntax) **   <a name="timestream-query_CreateScheduledQuery-request-ScheduledQueryExecutionRoleArn"></a>
The ARN for the IAM role that Timestream will assume when running the scheduled query.   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: Yes

 ** [Tags](#API_query_CreateScheduledQuery_RequestSyntax) **   <a name="timestream-query_CreateScheduledQuery-request-Tags"></a>
A list of key-value pairs to label the scheduled query.  
Type: Array of [Tag](API_query_Tag.md) objects  
Array Members: Minimum number of 0 items. Maximum number of 200 items.  
Required: No

 ** [TargetConfiguration](#API_query_CreateScheduledQuery_RequestSyntax) **   <a name="timestream-query_CreateScheduledQuery-request-TargetConfiguration"></a>
Configuration used for writing the result of a query.  
Type: [TargetConfiguration](API_query_TargetConfiguration.md) object  
Required: No

## Response Syntax
<a name="API_query_CreateScheduledQuery_ResponseSyntax"></a>

```
{
   "Arn": "string"
}
```

## Response Elements
<a name="API_query_CreateScheduledQuery_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [Arn](#API_query_CreateScheduledQuery_ResponseSyntax) **   <a name="timestream-query_CreateScheduledQuery-response-Arn"></a>
ARN for the created scheduled query.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.

## Errors
<a name="API_query_CreateScheduledQuery_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You do not have the necessary permissions to access the account settings.  
HTTP Status Code: 400

 ** ConflictException **   
 Unable to poll results for a cancelled query.   
HTTP Status Code: 400

 ** InternalServerException **   
An internal server error occurred while processing the request.  
HTTP Status Code: 400

 ** InvalidEndpointException **   
The requested endpoint is invalid.  
HTTP Status Code: 400

 ** ServiceQuotaExceededException **   
You have exceeded the service quota.  
HTTP Status Code: 400

 ** ThrottlingException **   
The request was throttled due to excessive requests.  
HTTP Status Code: 400

 ** ValidationException **   
 Invalid or malformed request.   
HTTP Status Code: 400

## See Also
<a name="API_query_CreateScheduledQuery_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-query-2018-11-01/CreateScheduledQuery) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-query-2018-11-01/CreateScheduledQuery) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/CreateScheduledQuery) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-query-2018-11-01/CreateScheduledQuery) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/CreateScheduledQuery) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-query-2018-11-01/CreateScheduledQuery) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-query-2018-11-01/CreateScheduledQuery) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-query-2018-11-01/CreateScheduledQuery) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-query-2018-11-01/CreateScheduledQuery) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/CreateScheduledQuery) 

# DeleteScheduledQuery
<a name="API_query_DeleteScheduledQuery"></a>

Deletes a given scheduled query. This is an irreversible operation. 

## Request Syntax
<a name="API_query_DeleteScheduledQuery_RequestSyntax"></a>

```
{
   "ScheduledQueryArn": "string"
}
```

## Request Parameters
<a name="API_query_DeleteScheduledQuery_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [ScheduledQueryArn](#API_query_DeleteScheduledQuery_RequestSyntax) **   <a name="timestream-query_DeleteScheduledQuery-request-ScheduledQueryArn"></a>
The ARN of the scheduled query.   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: Yes

## Response Elements
<a name="API_query_DeleteScheduledQuery_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response with an empty HTTP body.

## Errors
<a name="API_query_DeleteScheduledQuery_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You do not have the necessary permissions to access the account settings.  
HTTP Status Code: 400

 ** InternalServerException **   
An internal server error occurred while processing the request.  
HTTP Status Code: 400

 ** InvalidEndpointException **   
The requested endpoint is invalid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The requested resource could not be found.    
 ** ScheduledQueryArn **   
The ARN of the scheduled query.
HTTP Status Code: 400

 ** ThrottlingException **   
The request was throttled due to excessive requests.  
HTTP Status Code: 400

 ** ValidationException **   
 Invalid or malformed request.   
HTTP Status Code: 400

## See Also
<a name="API_query_DeleteScheduledQuery_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-query-2018-11-01/DeleteScheduledQuery) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-query-2018-11-01/DeleteScheduledQuery) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/DeleteScheduledQuery) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-query-2018-11-01/DeleteScheduledQuery) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/DeleteScheduledQuery) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-query-2018-11-01/DeleteScheduledQuery) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-query-2018-11-01/DeleteScheduledQuery) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-query-2018-11-01/DeleteScheduledQuery) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-query-2018-11-01/DeleteScheduledQuery) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/DeleteScheduledQuery) 

# DescribeAccountSettings
<a name="API_query_DescribeAccountSettings"></a>

Describes the settings for your account that include the query pricing model and the configured maximum TCUs the service can use for your query workload.

You're charged only for the duration of compute units used for your workloads.

## Response Syntax
<a name="API_query_DescribeAccountSettings_ResponseSyntax"></a>

```
{
   "MaxQueryTCU": number,
   "QueryCompute": { 
      "ComputeMode": "string",
      "ProvisionedCapacity": { 
         "ActiveQueryTCU": number,
         "LastUpdate": { 
            "Status": "string",
            "StatusMessage": "string",
            "TargetQueryTCU": number
         },
         "NotificationConfiguration": { 
            "RoleArn": "string",
            "SnsConfiguration": { 
               "TopicArn": "string"
            }
         }
      }
   },
   "QueryPricingModel": "string"
}
```

## Response Elements
<a name="API_query_DescribeAccountSettings_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [MaxQueryTCU](#API_query_DescribeAccountSettings_ResponseSyntax) **   <a name="timestream-query_DescribeAccountSettings-response-MaxQueryTCU"></a>
The maximum number of [Timestream compute units](https://docs.aws.amazon.com/timestream/latest/developerguide/tcu.html) (TCUs) the service will use at any point in time to serve your queries. To run queries, you must set a minimum capacity of 4 TCU. You can set the maximum number of TCU in multiples of 4, for example, 4, 8, 16, 32, and so on. This configuration is applicable only for on-demand usage of (TCUs).   
Type: Integer

 ** [QueryCompute](#API_query_DescribeAccountSettings_ResponseSyntax) **   <a name="timestream-query_DescribeAccountSettings-response-QueryCompute"></a>
An object that contains the usage settings for Timestream Compute Units (TCUs) in your account for the query workload. QueryCompute is available only in the Asia Pacific (Mumbai) region.  
Type: [QueryComputeResponse](API_query_QueryComputeResponse.md) object

 ** [QueryPricingModel](#API_query_DescribeAccountSettings_ResponseSyntax) **   <a name="timestream-query_DescribeAccountSettings-response-QueryPricingModel"></a>
The pricing model for queries in your account.  
The `QueryPricingModel` parameter is used by several Timestream operations; however, the `UpdateAccountSettings` API operation doesn't recognize any values other than `COMPUTE_UNITS`.
Type: String  
Valid Values: `BYTES_SCANNED | COMPUTE_UNITS` 

## Errors
<a name="API_query_DescribeAccountSettings_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You do not have the necessary permissions to access the account settings.  
HTTP Status Code: 400

 ** InternalServerException **   
An internal server error occurred while processing the request.  
HTTP Status Code: 400

 ** InvalidEndpointException **   
The requested endpoint is invalid.  
HTTP Status Code: 400

 ** ThrottlingException **   
The request was throttled due to excessive requests.  
HTTP Status Code: 400

## See Also
<a name="API_query_DescribeAccountSettings_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-query-2018-11-01/DescribeAccountSettings) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-query-2018-11-01/DescribeAccountSettings) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/DescribeAccountSettings) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-query-2018-11-01/DescribeAccountSettings) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/DescribeAccountSettings) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-query-2018-11-01/DescribeAccountSettings) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-query-2018-11-01/DescribeAccountSettings) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-query-2018-11-01/DescribeAccountSettings) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-query-2018-11-01/DescribeAccountSettings) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/DescribeAccountSettings) 

# DescribeEndpoints
<a name="API_query_DescribeEndpoints"></a>

DescribeEndpoints returns a list of available endpoints to make Timestream API calls against. This API is available through both Write and Query.

Because the Timestream SDKs are designed to transparently work with the service’s architecture, including the management and mapping of the service endpoints, *it is not recommended that you use this API unless*:
+ You are using [VPC endpoints (AWS PrivateLink) with Timestream ](https://docs.aws.amazon.com/timestream/latest/developerguide/VPCEndpoints) 
+ Your application uses a programming language that does not yet have SDK support
+ You require better control over the client-side implementation

For detailed information on how and when to use and implement DescribeEndpoints, see [The Endpoint Discovery Pattern](https://docs.aws.amazon.com/timestream/latest/developerguide/Using.API.html#Using-API.endpoint-discovery).

## Response Syntax
<a name="API_query_DescribeEndpoints_ResponseSyntax"></a>

```
{
   "Endpoints": [ 
      { 
         "Address": "string",
         "CachePeriodInMinutes": number
      }
   ]
}
```

## Response Elements
<a name="API_query_DescribeEndpoints_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [Endpoints](#API_query_DescribeEndpoints_ResponseSyntax) **   <a name="timestream-query_DescribeEndpoints-response-Endpoints"></a>
An `Endpoints` object is returned when a `DescribeEndpoints` request is made.  
Type: Array of [Endpoint](API_query_Endpoint.md) objects

## Errors
<a name="API_query_DescribeEndpoints_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** InternalServerException **   
An internal server error occurred while processing the request.  
HTTP Status Code: 400

 ** ThrottlingException **   
The request was throttled due to excessive requests.  
HTTP Status Code: 400

 ** ValidationException **   
 Invalid or malformed request.   
HTTP Status Code: 400

## See Also
<a name="API_query_DescribeEndpoints_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-query-2018-11-01/DescribeEndpoints) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-query-2018-11-01/DescribeEndpoints) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/DescribeEndpoints) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-query-2018-11-01/DescribeEndpoints) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/DescribeEndpoints) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-query-2018-11-01/DescribeEndpoints) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-query-2018-11-01/DescribeEndpoints) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-query-2018-11-01/DescribeEndpoints) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-query-2018-11-01/DescribeEndpoints) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/DescribeEndpoints) 

# DescribeScheduledQuery
<a name="API_query_DescribeScheduledQuery"></a>

Provides detailed information about a scheduled query.

## Request Syntax
<a name="API_query_DescribeScheduledQuery_RequestSyntax"></a>

```
{
   "ScheduledQueryArn": "string"
}
```

## Request Parameters
<a name="API_query_DescribeScheduledQuery_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [ScheduledQueryArn](#API_query_DescribeScheduledQuery_RequestSyntax) **   <a name="timestream-query_DescribeScheduledQuery-request-ScheduledQueryArn"></a>
The ARN of the scheduled query.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: Yes

## Response Syntax
<a name="API_query_DescribeScheduledQuery_ResponseSyntax"></a>

```
{
   "ScheduledQuery": { 
      "Arn": "string",
      "CreationTime": number,
      "ErrorReportConfiguration": { 
         "S3Configuration": { 
            "BucketName": "string",
            "EncryptionOption": "string",
            "ObjectKeyPrefix": "string"
         }
      },
      "KmsKeyId": "string",
      "LastRunSummary": { 
         "ErrorReportLocation": { 
            "S3ReportLocation": { 
               "BucketName": "string",
               "ObjectKey": "string"
            }
         },
         "ExecutionStats": { 
            "BytesMetered": number,
            "CumulativeBytesScanned": number,
            "DataWrites": number,
            "ExecutionTimeInMillis": number,
            "QueryResultRows": number,
            "RecordsIngested": number
         },
         "FailureReason": "string",
         "InvocationTime": number,
         "QueryInsightsResponse": { 
            "OutputBytes": number,
            "OutputRows": number,
            "QuerySpatialCoverage": { 
               "Max": { 
                  "PartitionKey": [ "string" ],
                  "TableArn": "string",
                  "Value": number
               }
            },
            "QueryTableCount": number,
            "QueryTemporalRange": { 
               "Max": { 
                  "TableArn": "string",
                  "Value": number
               }
            }
         },
         "RunStatus": "string",
         "TriggerTime": number
      },
      "Name": "string",
      "NextInvocationTime": number,
      "NotificationConfiguration": { 
         "SnsConfiguration": { 
            "TopicArn": "string"
         }
      },
      "PreviousInvocationTime": number,
      "QueryString": "string",
      "RecentlyFailedRuns": [ 
         { 
            "ErrorReportLocation": { 
               "S3ReportLocation": { 
                  "BucketName": "string",
                  "ObjectKey": "string"
               }
            },
            "ExecutionStats": { 
               "BytesMetered": number,
               "CumulativeBytesScanned": number,
               "DataWrites": number,
               "ExecutionTimeInMillis": number,
               "QueryResultRows": number,
               "RecordsIngested": number
            },
            "FailureReason": "string",
            "InvocationTime": number,
            "QueryInsightsResponse": { 
               "OutputBytes": number,
               "OutputRows": number,
               "QuerySpatialCoverage": { 
                  "Max": { 
                     "PartitionKey": [ "string" ],
                     "TableArn": "string",
                     "Value": number
                  }
               },
               "QueryTableCount": number,
               "QueryTemporalRange": { 
                  "Max": { 
                     "TableArn": "string",
                     "Value": number
                  }
               }
            },
            "RunStatus": "string",
            "TriggerTime": number
         }
      ],
      "ScheduleConfiguration": { 
         "ScheduleExpression": "string"
      },
      "ScheduledQueryExecutionRoleArn": "string",
      "State": "string",
      "TargetConfiguration": { 
         "TimestreamConfiguration": { 
            "DatabaseName": "string",
            "DimensionMappings": [ 
               { 
                  "DimensionValueType": "string",
                  "Name": "string"
               }
            ],
            "MeasureNameColumn": "string",
            "MixedMeasureMappings": [ 
               { 
                  "MeasureName": "string",
                  "MeasureValueType": "string",
                  "MultiMeasureAttributeMappings": [ 
                     { 
                        "MeasureValueType": "string",
                        "SourceColumn": "string",
                        "TargetMultiMeasureAttributeName": "string"
                     }
                  ],
                  "SourceColumn": "string",
                  "TargetMeasureName": "string"
               }
            ],
            "MultiMeasureMappings": { 
               "MultiMeasureAttributeMappings": [ 
                  { 
                     "MeasureValueType": "string",
                     "SourceColumn": "string",
                     "TargetMultiMeasureAttributeName": "string"
                  }
               ],
               "TargetMultiMeasureName": "string"
            },
            "TableName": "string",
            "TimeColumn": "string"
         }
      }
   }
}
```

## Response Elements
<a name="API_query_DescribeScheduledQuery_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [ScheduledQuery](#API_query_DescribeScheduledQuery_ResponseSyntax) **   <a name="timestream-query_DescribeScheduledQuery-response-ScheduledQuery"></a>
The scheduled query.  
Type: [ScheduledQueryDescription](API_query_ScheduledQueryDescription.md) object

## Errors
<a name="API_query_DescribeScheduledQuery_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You do not have the necessary permissions to access the account settings.  
HTTP Status Code: 400

 ** InternalServerException **   
An internal server error occurred while processing the request.  
HTTP Status Code: 400

 ** InvalidEndpointException **   
The requested endpoint is invalid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The requested resource could not be found.    
 ** ScheduledQueryArn **   
The ARN of the scheduled query.
HTTP Status Code: 400

 ** ThrottlingException **   
The request was throttled due to excessive requests.  
HTTP Status Code: 400

 ** ValidationException **   
 Invalid or malformed request.   
HTTP Status Code: 400

## See Also
<a name="API_query_DescribeScheduledQuery_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-query-2018-11-01/DescribeScheduledQuery) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-query-2018-11-01/DescribeScheduledQuery) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/DescribeScheduledQuery) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-query-2018-11-01/DescribeScheduledQuery) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/DescribeScheduledQuery) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-query-2018-11-01/DescribeScheduledQuery) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-query-2018-11-01/DescribeScheduledQuery) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-query-2018-11-01/DescribeScheduledQuery) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-query-2018-11-01/DescribeScheduledQuery) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/DescribeScheduledQuery) 

# ExecuteScheduledQuery
<a name="API_query_ExecuteScheduledQuery"></a>

 You can use this API to run a scheduled query manually. 

If you enabled `QueryInsights`, this API also returns insights and metrics related to the query that you executed as part of an Amazon SNS notification. `QueryInsights` helps with performance tuning of your query. For more information about `QueryInsights`, see [Using query insights to optimize queries in Amazon Timestream](https://docs.aws.amazon.com/timestream/latest/developerguide/using-query-insights.html).

## Request Syntax
<a name="API_query_ExecuteScheduledQuery_RequestSyntax"></a>

```
{
   "ClientToken": "string",
   "InvocationTime": number,
   "QueryInsights": { 
      "Mode": "string"
   },
   "ScheduledQueryArn": "string"
}
```

## Request Parameters
<a name="API_query_ExecuteScheduledQuery_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [ClientToken](#API_query_ExecuteScheduledQuery_RequestSyntax) **   <a name="timestream-query_ExecuteScheduledQuery-request-ClientToken"></a>
Not used.   
Type: String  
Length Constraints: Minimum length of 32. Maximum length of 128.  
Required: No

 ** [InvocationTime](#API_query_ExecuteScheduledQuery_RequestSyntax) **   <a name="timestream-query_ExecuteScheduledQuery-request-InvocationTime"></a>
The timestamp in UTC. Query will be run as if it was invoked at this timestamp.   
Type: Timestamp  
Required: Yes

 ** [QueryInsights](#API_query_ExecuteScheduledQuery_RequestSyntax) **   <a name="timestream-query_ExecuteScheduledQuery-request-QueryInsights"></a>
Encapsulates settings for enabling `QueryInsights`.  
Enabling `QueryInsights` returns insights and metrics as a part of the Amazon SNS notification for the query that you executed. You can use `QueryInsights` to tune your query performance and cost.  
Type: [ScheduledQueryInsights](API_query_ScheduledQueryInsights.md) object  
Required: No

 ** [ScheduledQueryArn](#API_query_ExecuteScheduledQuery_RequestSyntax) **   <a name="timestream-query_ExecuteScheduledQuery-request-ScheduledQueryArn"></a>
ARN of the scheduled query.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: Yes

## Response Elements
<a name="API_query_ExecuteScheduledQuery_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response with an empty HTTP body.

## Errors
<a name="API_query_ExecuteScheduledQuery_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You do not have the necessary permissions to access the account settings.  
HTTP Status Code: 400

 ** InternalServerException **   
An internal server error occurred while processing the request.  
HTTP Status Code: 400

 ** InvalidEndpointException **   
The requested endpoint is invalid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The requested resource could not be found.    
 ** ScheduledQueryArn **   
The ARN of the scheduled query.
HTTP Status Code: 400

 ** ThrottlingException **   
The request was throttled due to excessive requests.  
HTTP Status Code: 400

 ** ValidationException **   
 Invalid or malformed request.   
HTTP Status Code: 400

## Examples
<a name="API_query_ExecuteScheduledQuery_Examples"></a>

### Scheduled query notification message for the ENABLED\$1WITH\$1RATE\$1CONTROL mode
<a name="API_query_ExecuteScheduledQuery_Example_1"></a>

The following example shows a successful scheduled query notification message for the `ENABLED_WITH_RATE_CONTROL` mode of the `QueryInsights` parameter.

```
"SuccessNotificationMessage": {
    "type": "MANUAL_TRIGGER_SUCCESS",
    "arn": "arn:aws:timestream:<Region>:<Account>:scheduled-query/sq-test-49c6ed55-c2e7-4cc2-9956-4a0ecea13420-80e05b035236a4c3",
    "scheduledQueryRunSummary": {
        "invocationEpochSecond": 1723710546,
        "triggerTimeMillis": 1723710547490,
        "runStatus": "MANUAL_TRIGGER_SUCCESS",
        "executionStats": {
            "executionTimeInMillis": 17343,
            "dataWrites": 1024,
            "bytesMetered": 0,
            "cumulativeBytesScanned": 600,
            "recordsIngested": 1,
            "queryResultRows": 1
        },
        "queryInsightsResponse": {
            "querySpatialCoverage": {
                "max": {
                    "value": 1.0,
                    "tableArn": "arn:aws:timestream:<Region>:<Account>:database/BaseDb/table/BaseTable",
                    "partitionKey": [
                        "measure_name"
                    ]
                }
            },
            "queryTemporalRange": {
                "max": {
                    "value": 2399999999999,
                    "tableArn": "arn:aws:timestream:<Region>:<Account>:database/BaseDb/table/BaseTable"
                }
            },
            "queryTableCount": 1,
            "outputRows": 1,
            "outputBytes": 59
        }
    }
}
```

### Scheduled query notification message for the DISABLED mode
<a name="API_query_ExecuteScheduledQuery_Example_2"></a>

The following example shows a successful scheduled query notification message for the `DISABLED` mode of the `QueryInsights` parameter.

```
"SuccessNotificationMessage": {
    "type": "MANUAL_TRIGGER_SUCCESS",
    "arn": "arn:aws:timestream:<Region>:<Account>:scheduled-query/sq-test-fa109d9e-6528-4a0d-ac40-482fa05e657f-140faaeecdc5b2a7",
    "scheduledQueryRunSummary": {
        "invocationEpochSecond": 1723711401,
        "triggerTimeMillis": 1723711402144,
        "runStatus": "MANUAL_TRIGGER_SUCCESS",
        "executionStats": {
            "executionTimeInMillis": 17992,
            "dataWrites": 1024,
            "bytesMetered": 0,
            "cumulativeBytesScanned": 600,
            "recordsIngested": 1,
            "queryResultRows": 1
        }
    }
}
```

### Failure notification message for the ENABLED\$1WITH\$1RATE\$1CONTROL mode
<a name="API_query_ExecuteScheduledQuery_Example_3"></a>

The following example shows a failed scheduled query notification message for the `ENABLED_WITH_RATE_CONTROL` mode of the `QueryInsights` parameter.

```
"FailureNotificationMessage": {
    "type": "MANUAL_TRIGGER_FAILURE",
    "arn": "arn:aws:timestream:<Region>:<Account>:scheduled-query/sq-test-b261670d-790c-4116-9db5-0798071b18b1-b7e27a1d79be226d",
    "scheduledQueryRunSummary": {
        "invocationEpochSecond": 1727915513,
        "triggerTimeMillis": 1727915513894,
        "runStatus": "MANUAL_TRIGGER_FAILURE",
        "executionStats": {
            "executionTimeInMillis": 10777,
            "dataWrites": 0,
            "bytesMetered": 0,
            "cumulativeBytesScanned": 0,
            "recordsIngested": 0,
            "queryResultRows": 4
        },
        "errorReportLocation": {
            "s3ReportLocation": {
                "bucketName": "amzn-s3-demo-bucket",
                "objectKey": "4my-organization-f7a3c5d065a1a95e/1727915513/MANUAL/1727915513894/5e14b3df-b147-49f4-9331-784f749b68ae"
            }
        },
        "failureReason": "Schedule encountered some errors and is incomplete. Please take a look at error report for further details"
    }
}
```

### Failure notification message for the DISABLED mode
<a name="API_query_ExecuteScheduledQuery_Example_4"></a>

The following example shows a failed scheduled query notification message for the `DISABLED` mode of the `QueryInsights` parameter.

```
"FailureNotificationMessage": {
    "type": "MANUAL_TRIGGER_FAILURE",
    "arn": "arn:aws:timestream:<Region>:<Account>:scheduled-query/sq-test-b261670d-790c-4116-9db5-0798071b18b1-b7e27a1d79be226d",
    "scheduledQueryRunSummary": {
        "invocationEpochSecond": 1727915194,
        "triggerTimeMillis": 1727915195119,
        "runStatus": "MANUAL_TRIGGER_FAILURE",
        "executionStats": {
            "executionTimeInMillis": 10777,
            "dataWrites": 0,
            "bytesMetered": 0,
            "cumulativeBytesScanned": 0,
            "recordsIngested": 0,
            "queryResultRows": 4
        },
        "errorReportLocation": {
            "s3ReportLocation": {
                "bucketName": "amzn-s3-demo-bucket",
                "objectKey": "4my-organization-b7e27a1d79be226d/1727915194/MANUAL/1727915195119/08dea9f5-9a0a-4e63-a5f7-ded23247bb98"
            }
        },
        "failureReason": "Schedule encountered some errors and is incomplete. Please take a look at error report for further details"
    }
}
```

## See Also
<a name="API_query_ExecuteScheduledQuery_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-query-2018-11-01/ExecuteScheduledQuery) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-query-2018-11-01/ExecuteScheduledQuery) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/ExecuteScheduledQuery) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-query-2018-11-01/ExecuteScheduledQuery) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/ExecuteScheduledQuery) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-query-2018-11-01/ExecuteScheduledQuery) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-query-2018-11-01/ExecuteScheduledQuery) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-query-2018-11-01/ExecuteScheduledQuery) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-query-2018-11-01/ExecuteScheduledQuery) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/ExecuteScheduledQuery) 

# ListScheduledQueries
<a name="API_query_ListScheduledQueries"></a>

Gets a list of all scheduled queries in the caller's Amazon account and Region. `ListScheduledQueries` is eventually consistent. 

## Request Syntax
<a name="API_query_ListScheduledQueries_RequestSyntax"></a>

```
{
   "MaxResults": number,
   "NextToken": "string"
}
```

## Request Parameters
<a name="API_query_ListScheduledQueries_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [MaxResults](#API_query_ListScheduledQueries_RequestSyntax) **   <a name="timestream-query_ListScheduledQueries-request-MaxResults"></a>
The maximum number of items to return in the output. If the total number of items available is more than the value specified, a `NextToken` is provided in the output. To resume pagination, provide the `NextToken` value as the argument to the subsequent call to `ListScheduledQueriesRequest`.  
Type: Integer  
Valid Range: Minimum value of 1. Maximum value of 1000.  
Required: No

 ** [NextToken](#API_query_ListScheduledQueries_RequestSyntax) **   <a name="timestream-query_ListScheduledQueries-request-NextToken"></a>
 A pagination token to resume pagination.  
Type: String  
Required: No

## Response Syntax
<a name="API_query_ListScheduledQueries_ResponseSyntax"></a>

```
{
   "NextToken": "string",
   "ScheduledQueries": [ 
      { 
         "Arn": "string",
         "CreationTime": number,
         "ErrorReportConfiguration": { 
            "S3Configuration": { 
               "BucketName": "string",
               "EncryptionOption": "string",
               "ObjectKeyPrefix": "string"
            }
         },
         "LastRunStatus": "string",
         "Name": "string",
         "NextInvocationTime": number,
         "PreviousInvocationTime": number,
         "State": "string",
         "TargetDestination": { 
            "TimestreamDestination": { 
               "DatabaseName": "string",
               "TableName": "string"
            }
         }
      }
   ]
}
```

## Response Elements
<a name="API_query_ListScheduledQueries_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [NextToken](#API_query_ListScheduledQueries_ResponseSyntax) **   <a name="timestream-query_ListScheduledQueries-response-NextToken"></a>
A token to specify where to start paginating. This is the NextToken from a previously truncated response.  
Type: String

 ** [ScheduledQueries](#API_query_ListScheduledQueries_ResponseSyntax) **   <a name="timestream-query_ListScheduledQueries-response-ScheduledQueries"></a>
A list of scheduled queries.  
Type: Array of [ScheduledQuery](API_query_ScheduledQuery.md) objects

## Errors
<a name="API_query_ListScheduledQueries_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You do not have the necessary permissions to access the account settings.  
HTTP Status Code: 400

 ** InternalServerException **   
An internal server error occurred while processing the request.  
HTTP Status Code: 400

 ** InvalidEndpointException **   
The requested endpoint is invalid.  
HTTP Status Code: 400

 ** ThrottlingException **   
The request was throttled due to excessive requests.  
HTTP Status Code: 400

 ** ValidationException **   
 Invalid or malformed request.   
HTTP Status Code: 400

## See Also
<a name="API_query_ListScheduledQueries_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-query-2018-11-01/ListScheduledQueries) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-query-2018-11-01/ListScheduledQueries) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/ListScheduledQueries) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-query-2018-11-01/ListScheduledQueries) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/ListScheduledQueries) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-query-2018-11-01/ListScheduledQueries) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-query-2018-11-01/ListScheduledQueries) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-query-2018-11-01/ListScheduledQueries) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-query-2018-11-01/ListScheduledQueries) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/ListScheduledQueries) 

# ListTagsForResource
<a name="API_query_ListTagsForResource"></a>

List all tags on a Timestream query resource.

## Request Syntax
<a name="API_query_ListTagsForResource_RequestSyntax"></a>

```
{
   "MaxResults": number,
   "NextToken": "string",
   "ResourceARN": "string"
}
```

## Request Parameters
<a name="API_query_ListTagsForResource_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [MaxResults](#API_query_ListTagsForResource_RequestSyntax) **   <a name="timestream-query_ListTagsForResource-request-MaxResults"></a>
The maximum number of tags to return.  
Type: Integer  
Valid Range: Minimum value of 1. Maximum value of 200.  
Required: No

 ** [NextToken](#API_query_ListTagsForResource_RequestSyntax) **   <a name="timestream-query_ListTagsForResource-request-NextToken"></a>
A pagination token to resume pagination.  
Type: String  
Required: No

 ** [ResourceARN](#API_query_ListTagsForResource_RequestSyntax) **   <a name="timestream-query_ListTagsForResource-request-ResourceARN"></a>
The Timestream resource with tags to be listed. This value is an Amazon Resource Name (ARN).  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: Yes

## Response Syntax
<a name="API_query_ListTagsForResource_ResponseSyntax"></a>

```
{
   "NextToken": "string",
   "Tags": [ 
      { 
         "Key": "string",
         "Value": "string"
      }
   ]
}
```

## Response Elements
<a name="API_query_ListTagsForResource_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [NextToken](#API_query_ListTagsForResource_ResponseSyntax) **   <a name="timestream-query_ListTagsForResource-response-NextToken"></a>
A pagination token to resume pagination with a subsequent call to `ListTagsForResourceResponse`.  
Type: String

 ** [Tags](#API_query_ListTagsForResource_ResponseSyntax) **   <a name="timestream-query_ListTagsForResource-response-Tags"></a>
The tags currently associated with the Timestream resource.   
Type: Array of [Tag](API_query_Tag.md) objects  
Array Members: Minimum number of 0 items. Maximum number of 200 items.

## Errors
<a name="API_query_ListTagsForResource_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** InvalidEndpointException **   
The requested endpoint is invalid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The requested resource could not be found.    
 ** ScheduledQueryArn **   
The ARN of the scheduled query.
HTTP Status Code: 400

 ** ThrottlingException **   
The request was throttled due to excessive requests.  
HTTP Status Code: 400

 ** ValidationException **   
 Invalid or malformed request.   
HTTP Status Code: 400

## See Also
<a name="API_query_ListTagsForResource_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-query-2018-11-01/ListTagsForResource) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-query-2018-11-01/ListTagsForResource) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/ListTagsForResource) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-query-2018-11-01/ListTagsForResource) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/ListTagsForResource) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-query-2018-11-01/ListTagsForResource) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-query-2018-11-01/ListTagsForResource) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-query-2018-11-01/ListTagsForResource) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-query-2018-11-01/ListTagsForResource) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/ListTagsForResource) 

# PrepareQuery
<a name="API_query_PrepareQuery"></a>

A synchronous operation that allows you to submit a query with parameters to be stored by Timestream for later running. Timestream only supports using this operation with `ValidateOnly` set to `true`. 

## Request Syntax
<a name="API_query_PrepareQuery_RequestSyntax"></a>

```
{
   "QueryString": "string",
   "ValidateOnly": boolean
}
```

## Request Parameters
<a name="API_query_PrepareQuery_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [QueryString](#API_query_PrepareQuery_RequestSyntax) **   <a name="timestream-query_PrepareQuery-request-QueryString"></a>
The Timestream query string that you want to use as a prepared statement. Parameter names can be specified in the query string `@` character followed by an identifier.   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 262144.  
Required: Yes

 ** [ValidateOnly](#API_query_PrepareQuery_RequestSyntax) **   <a name="timestream-query_PrepareQuery-request-ValidateOnly"></a>
By setting this value to `true`, Timestream will only validate that the query string is a valid Timestream query, and not store the prepared query for later use.  
Type: Boolean  
Required: No

## Response Syntax
<a name="API_query_PrepareQuery_ResponseSyntax"></a>

```
{
   "Columns": [ 
      { 
         "Aliased": boolean,
         "DatabaseName": "string",
         "Name": "string",
         "TableName": "string",
         "Type": { 
            "ArrayColumnInfo": { 
               "Name": "string",
               "Type": "Type"
            },
            "RowColumnInfo": [ 
               { 
                  "Name": "string",
                  "Type": "Type"
               }
            ],
            "ScalarType": "string",
            "TimeSeriesMeasureValueColumnInfo": { 
               "Name": "string",
               "Type": "Type"
            }
         }
      }
   ],
   "Parameters": [ 
      { 
         "Name": "string",
         "Type": { 
            "ArrayColumnInfo": { 
               "Name": "string",
               "Type": "Type"
            },
            "RowColumnInfo": [ 
               { 
                  "Name": "string",
                  "Type": "Type"
               }
            ],
            "ScalarType": "string",
            "TimeSeriesMeasureValueColumnInfo": { 
               "Name": "string",
               "Type": "Type"
            }
         }
      }
   ],
   "QueryString": "string"
}
```

## Response Elements
<a name="API_query_PrepareQuery_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [Columns](#API_query_PrepareQuery_ResponseSyntax) **   <a name="timestream-query_PrepareQuery-response-Columns"></a>
A list of SELECT clause columns of the submitted query string.   
Type: Array of [SelectColumn](API_query_SelectColumn.md) objects

 ** [Parameters](#API_query_PrepareQuery_ResponseSyntax) **   <a name="timestream-query_PrepareQuery-response-Parameters"></a>
A list of parameters used in the submitted query string.   
Type: Array of [ParameterMapping](API_query_ParameterMapping.md) objects

 ** [QueryString](#API_query_PrepareQuery_ResponseSyntax) **   <a name="timestream-query_PrepareQuery-response-QueryString"></a>
The query string that you want prepare.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 262144.

## Errors
<a name="API_query_PrepareQuery_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You do not have the necessary permissions to access the account settings.  
HTTP Status Code: 400

 ** InternalServerException **   
An internal server error occurred while processing the request.  
HTTP Status Code: 400

 ** InvalidEndpointException **   
The requested endpoint is invalid.  
HTTP Status Code: 400

 ** ThrottlingException **   
The request was throttled due to excessive requests.  
HTTP Status Code: 400

 ** ValidationException **   
 Invalid or malformed request.   
HTTP Status Code: 400

## See Also
<a name="API_query_PrepareQuery_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-query-2018-11-01/PrepareQuery) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-query-2018-11-01/PrepareQuery) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/PrepareQuery) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-query-2018-11-01/PrepareQuery) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/PrepareQuery) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-query-2018-11-01/PrepareQuery) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-query-2018-11-01/PrepareQuery) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-query-2018-11-01/PrepareQuery) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-query-2018-11-01/PrepareQuery) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/PrepareQuery) 

# Query
<a name="API_query_Query"></a>

 `Query` is a synchronous operation that enables you to run a query against your Amazon Timestream data.

If you enabled `QueryInsights`, this API also returns insights and metrics related to the query that you executed. `QueryInsights` helps with performance tuning of your query. For more information about `QueryInsights`, see [Using query insights to optimize queries in Amazon Timestream](https://docs.aws.amazon.com/timestream/latest/developerguide/using-query-insights.html).

**Note**  
The maximum number of `Query` API requests you're allowed to make with `QueryInsights` enabled is 1 query per second (QPS). If you exceed this query rate, it might result in throttling.

 `Query` will time out after 60 seconds. You must update the default timeout in the SDK to support a timeout of 60 seconds. See the [code sample](https://docs.aws.amazon.com/timestream/latest/developerguide/code-samples.run-query.html) for details. 

Your query request will fail in the following cases:
+  If you submit a `Query` request with the same client token outside of the 5-minute idempotency window. 
+  If you submit a `Query` request with the same client token, but change other parameters, within the 5-minute idempotency window. 
+  If the size of the row (including the query metadata) exceeds 1 MB, then the query will fail with the following error message: 

   `Query aborted as max page response size has been exceeded by the output result row` 
+  If the IAM principal of the query initiator and the result reader are not the same and/or the query initiator and the result reader do not have the same query string in the query requests, the query will fail with an `Invalid pagination token` error. 

## Request Syntax
<a name="API_query_Query_RequestSyntax"></a>

```
{
   "ClientToken": "string",
   "MaxRows": number,
   "NextToken": "string",
   "QueryInsights": { 
      "Mode": "string"
   },
   "QueryString": "string"
}
```

## Request Parameters
<a name="API_query_Query_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [ClientToken](#API_query_Query_RequestSyntax) **   <a name="timestream-query_Query-request-ClientToken"></a>
 Unique, case-sensitive string of up to 64 ASCII characters specified when a `Query` request is made. Providing a `ClientToken` makes the call to `Query` *idempotent*. This means that running the same query repeatedly will produce the same result. In other words, making multiple identical `Query` requests has the same effect as making a single request. When using `ClientToken` in a query, note the following:   
+  If the Query API is instantiated without a `ClientToken`, the Query SDK generates a `ClientToken` on your behalf.
+ If the `Query` invocation only contains the `ClientToken` but does not include a `NextToken`, that invocation of `Query` is assumed to be a new query run.
+ If the invocation contains `NextToken`, that particular invocation is assumed to be a subsequent invocation of a prior call to the Query API, and a result set is returned.
+  After 4 hours, any request with the same `ClientToken` is treated as a new request. 
Type: String  
Length Constraints: Minimum length of 32. Maximum length of 128.  
Required: No

 ** [MaxRows](#API_query_Query_RequestSyntax) **   <a name="timestream-query_Query-request-MaxRows"></a>
 The total number of rows to be returned in the `Query` output. The initial run of `Query` with a `MaxRows` value specified will return the result set of the query in two cases:   
+ The size of the result is less than `1MB`.
+ The number of rows in the result set is less than the value of `maxRows`.
Otherwise, the initial invocation of `Query` only returns a `NextToken`, which can then be used in subsequent calls to fetch the result set. To resume pagination, provide the `NextToken` value in the subsequent command.  
If the row size is large (e.g. a row has many columns), Timestream may return fewer rows to keep the response size from exceeding the 1 MB limit. If `MaxRows` is not provided, Timestream will send the necessary number of rows to meet the 1 MB limit.  
Type: Integer  
Valid Range: Minimum value of 1. Maximum value of 1000.  
Required: No

 ** [NextToken](#API_query_Query_RequestSyntax) **   <a name="timestream-query_Query-request-NextToken"></a>
 A pagination token used to return a set of results. When the `Query` API is invoked using `NextToken`, that particular invocation is assumed to be a subsequent invocation of a prior call to `Query`, and a result set is returned. However, if the `Query` invocation only contains the `ClientToken`, that invocation of `Query` is assumed to be a new query run.   
Note the following when using NextToken in a query:  
+ A pagination token can be used for up to five `Query` invocations, OR for a duration of up to 1 hour – whichever comes first.
+ Using the same `NextToken` will return the same set of records. To keep paginating through the result set, you must to use the most recent `nextToken`.
+ Suppose a `Query` invocation returns two `NextToken` values, `TokenA` and `TokenB`. If `TokenB` is used in a subsequent `Query` invocation, then `TokenA` is invalidated and cannot be reused.
+ To request a previous result set from a query after pagination has begun, you must re-invoke the Query API.
+ The latest `NextToken` should be used to paginate until `null` is returned, at which point a new `NextToken` should be used.
+  If the IAM principal of the query initiator and the result reader are not the same and/or the query initiator and the result reader do not have the same query string in the query requests, the query will fail with an `Invalid pagination token` error. 
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: No

 ** [QueryInsights](#API_query_Query_RequestSyntax) **   <a name="timestream-query_Query-request-QueryInsights"></a>
Encapsulates settings for enabling `QueryInsights`.  
Enabling `QueryInsights` returns insights and metrics in addition to query results for the query that you executed. You can use `QueryInsights` to tune your query performance.  
Type: [QueryInsights](API_query_QueryInsights.md) object  
Required: No

 ** [QueryString](#API_query_Query_RequestSyntax) **   <a name="timestream-query_Query-request-QueryString"></a>
 The query to be run by Timestream.   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 262144.  
Required: Yes

## Response Syntax
<a name="API_query_Query_ResponseSyntax"></a>

```
{
   "ColumnInfo": [ 
      { 
         "Name": "string",
         "Type": { 
            "ArrayColumnInfo": "ColumnInfo",
            "RowColumnInfo": [ 
               "ColumnInfo"
            ],
            "ScalarType": "string",
            "TimeSeriesMeasureValueColumnInfo": "ColumnInfo"
         }
      }
   ],
   "NextToken": "string",
   "QueryId": "string",
   "QueryInsightsResponse": { 
      "OutputBytes": number,
      "OutputRows": number,
      "QuerySpatialCoverage": { 
         "Max": { 
            "PartitionKey": [ "string" ],
            "TableArn": "string",
            "Value": number
         }
      },
      "QueryTableCount": number,
      "QueryTemporalRange": { 
         "Max": { 
            "TableArn": "string",
            "Value": number
         }
      },
      "UnloadPartitionCount": number,
      "UnloadWrittenBytes": number,
      "UnloadWrittenRows": number
   },
   "QueryStatus": { 
      "CumulativeBytesMetered": number,
      "CumulativeBytesScanned": number,
      "ProgressPercentage": number
   },
   "Rows": [ 
      { 
         "Data": [ 
            { 
               "ArrayValue": [ 
                  "Datum"
               ],
               "NullValue": boolean,
               "RowValue": "Row",
               "ScalarValue": "string",
               "TimeSeriesValue": [ 
                  { 
                     "Time": "string",
                     "Value": "Datum"
                  }
               ]
            }
         ]
      }
   ]
}
```

## Response Elements
<a name="API_query_Query_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [ColumnInfo](#API_query_Query_ResponseSyntax) **   <a name="timestream-query_Query-response-ColumnInfo"></a>
 The column data types of the returned result set.   
Type: Array of [ColumnInfo](API_query_ColumnInfo.md) objects

 ** [NextToken](#API_query_Query_ResponseSyntax) **   <a name="timestream-query_Query-response-NextToken"></a>
 A pagination token that can be used again on a `Query` call to get the next set of results.   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.

 ** [QueryId](#API_query_Query_ResponseSyntax) **   <a name="timestream-query_Query-response-QueryId"></a>
 A unique ID for the given query.   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 64.  
Pattern: `[a-zA-Z0-9]+` 

 ** [QueryInsightsResponse](#API_query_Query_ResponseSyntax) **   <a name="timestream-query_Query-response-QueryInsightsResponse"></a>
Encapsulates `QueryInsights` containing insights and metrics related to the query that you executed.  
Type: [QueryInsightsResponse](API_query_QueryInsightsResponse.md) object

 ** [QueryStatus](#API_query_Query_ResponseSyntax) **   <a name="timestream-query_Query-response-QueryStatus"></a>
Information about the status of the query, including progress and bytes scanned.  
Type: [QueryStatus](API_query_QueryStatus.md) object

 ** [Rows](#API_query_Query_ResponseSyntax) **   <a name="timestream-query_Query-response-Rows"></a>
 The result set rows returned by the query.   
Type: Array of [Row](API_query_Row.md) objects

## Errors
<a name="API_query_Query_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You do not have the necessary permissions to access the account settings.  
HTTP Status Code: 400

 ** ConflictException **   
 Unable to poll results for a cancelled query.   
HTTP Status Code: 400

 ** InternalServerException **   
An internal server error occurred while processing the request.  
HTTP Status Code: 400

 ** InvalidEndpointException **   
The requested endpoint is invalid.  
HTTP Status Code: 400

 ** QueryExecutionException **   
 Timestream was unable to run the query successfully.   
HTTP Status Code: 400

 ** ThrottlingException **   
The request was throttled due to excessive requests.  
HTTP Status Code: 400

 ** ValidationException **   
 Invalid or malformed request.   
HTTP Status Code: 400

## See Also
<a name="API_query_Query_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-query-2018-11-01/Query) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-query-2018-11-01/Query) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/Query) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-query-2018-11-01/Query) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/Query) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-query-2018-11-01/Query) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-query-2018-11-01/Query) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-query-2018-11-01/Query) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-query-2018-11-01/Query) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/Query) 

# TagResource
<a name="API_query_TagResource"></a>

Associate a set of tags with a Timestream resource. You can then activate these user-defined tags so that they appear on the Billing and Cost Management console for cost allocation tracking. 

## Request Syntax
<a name="API_query_TagResource_RequestSyntax"></a>

```
{
   "ResourceARN": "string",
   "Tags": [ 
      { 
         "Key": "string",
         "Value": "string"
      }
   ]
}
```

## Request Parameters
<a name="API_query_TagResource_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [ResourceARN](#API_query_TagResource_RequestSyntax) **   <a name="timestream-query_TagResource-request-ResourceARN"></a>
Identifies the Timestream resource to which tags should be added. This value is an Amazon Resource Name (ARN).  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: Yes

 ** [Tags](#API_query_TagResource_RequestSyntax) **   <a name="timestream-query_TagResource-request-Tags"></a>
The tags to be assigned to the Timestream resource.  
Type: Array of [Tag](API_query_Tag.md) objects  
Array Members: Minimum number of 0 items. Maximum number of 200 items.  
Required: Yes

## Response Elements
<a name="API_query_TagResource_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response with an empty HTTP body.

## Errors
<a name="API_query_TagResource_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** InvalidEndpointException **   
The requested endpoint is invalid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The requested resource could not be found.    
 ** ScheduledQueryArn **   
The ARN of the scheduled query.
HTTP Status Code: 400

 ** ServiceQuotaExceededException **   
You have exceeded the service quota.  
HTTP Status Code: 400

 ** ThrottlingException **   
The request was throttled due to excessive requests.  
HTTP Status Code: 400

 ** ValidationException **   
 Invalid or malformed request.   
HTTP Status Code: 400

## See Also
<a name="API_query_TagResource_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-query-2018-11-01/TagResource) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-query-2018-11-01/TagResource) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/TagResource) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-query-2018-11-01/TagResource) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/TagResource) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-query-2018-11-01/TagResource) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-query-2018-11-01/TagResource) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-query-2018-11-01/TagResource) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-query-2018-11-01/TagResource) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/TagResource) 

# UntagResource
<a name="API_query_UntagResource"></a>

Removes the association of tags from a Timestream query resource.

## Request Syntax
<a name="API_query_UntagResource_RequestSyntax"></a>

```
{
   "ResourceARN": "string",
   "TagKeys": [ "string" ]
}
```

## Request Parameters
<a name="API_query_UntagResource_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [ResourceARN](#API_query_UntagResource_RequestSyntax) **   <a name="timestream-query_UntagResource-request-ResourceARN"></a>
The Timestream resource that the tags will be removed from. This value is an Amazon Resource Name (ARN).   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: Yes

 ** [TagKeys](#API_query_UntagResource_RequestSyntax) **   <a name="timestream-query_UntagResource-request-TagKeys"></a>
A list of tags keys. Existing tags of the resource whose keys are members of this list will be removed from the Timestream resource.   
Type: Array of strings  
Array Members: Minimum number of 0 items. Maximum number of 200 items.  
Length Constraints: Minimum length of 1. Maximum length of 128.  
Required: Yes

## Response Elements
<a name="API_query_UntagResource_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response with an empty HTTP body.

## Errors
<a name="API_query_UntagResource_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** InvalidEndpointException **   
The requested endpoint is invalid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The requested resource could not be found.    
 ** ScheduledQueryArn **   
The ARN of the scheduled query.
HTTP Status Code: 400

 ** ThrottlingException **   
The request was throttled due to excessive requests.  
HTTP Status Code: 400

 ** ValidationException **   
 Invalid or malformed request.   
HTTP Status Code: 400

## See Also
<a name="API_query_UntagResource_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-query-2018-11-01/UntagResource) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-query-2018-11-01/UntagResource) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/UntagResource) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-query-2018-11-01/UntagResource) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/UntagResource) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-query-2018-11-01/UntagResource) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-query-2018-11-01/UntagResource) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-query-2018-11-01/UntagResource) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-query-2018-11-01/UntagResource) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/UntagResource) 

# UpdateAccountSettings
<a name="API_query_UpdateAccountSettings"></a>

Transitions your account to use TCUs for query pricing and modifies the maximum query compute units that you've configured. If you reduce the value of `MaxQueryTCU` to a desired configuration, the new value can take up to 24 hours to be effective.

**Note**  
After you've transitioned your account to use TCUs for query pricing, you can't transition to using bytes scanned for query pricing.

## Request Syntax
<a name="API_query_UpdateAccountSettings_RequestSyntax"></a>

```
{
   "MaxQueryTCU": number,
   "QueryCompute": { 
      "ComputeMode": "string",
      "ProvisionedCapacity": { 
         "NotificationConfiguration": { 
            "RoleArn": "string",
            "SnsConfiguration": { 
               "TopicArn": "string"
            }
         },
         "TargetQueryTCU": number
      }
   },
   "QueryPricingModel": "string"
}
```

## Request Parameters
<a name="API_query_UpdateAccountSettings_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [MaxQueryTCU](#API_query_UpdateAccountSettings_RequestSyntax) **   <a name="timestream-query_UpdateAccountSettings-request-MaxQueryTCU"></a>
The maximum number of compute units the service will use at any point in time to serve your queries. To run queries, you must set a minimum capacity of 4 TCU. You can set the maximum number of TCU in multiples of 4, for example, 4, 8, 16, 32, and so on. The maximum value supported for `MaxQueryTCU` is 1000. To request an increase to this soft limit, contact AWS Support. For information about the default quota for maxQueryTCU, see Default quotas. This configuration is applicable only for on-demand usage of Timestream Compute Units (TCUs).  
The maximum value supported for `MaxQueryTCU` is 1000. To request an increase to this soft limit, contact AWS Support. For information about the default quota for `maxQueryTCU`, see [Default quotas](https://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html#limits.default).  
Type: Integer  
Required: No

 ** [QueryCompute](#API_query_UpdateAccountSettings_RequestSyntax) **   <a name="timestream-query_UpdateAccountSettings-request-QueryCompute"></a>
Modifies the query compute settings configured in your account, including the query pricing model and provisioned Timestream Compute Units (TCUs) in your account. QueryCompute is available only in the Asia Pacific (Mumbai) region.  
This API is idempotent, meaning that making the same request multiple times will have the same effect as making the request once.
Type: [QueryComputeRequest](API_query_QueryComputeRequest.md) object  
Required: No

 ** [QueryPricingModel](#API_query_UpdateAccountSettings_RequestSyntax) **   <a name="timestream-query_UpdateAccountSettings-request-QueryPricingModel"></a>
The pricing model for queries in an account.  
The `QueryPricingModel` parameter is used by several Timestream operations; however, the `UpdateAccountSettings` API operation doesn't recognize any values other than `COMPUTE_UNITS`.
Type: String  
Valid Values: `BYTES_SCANNED | COMPUTE_UNITS`   
Required: No

## Response Syntax
<a name="API_query_UpdateAccountSettings_ResponseSyntax"></a>

```
{
   "MaxQueryTCU": number,
   "QueryCompute": { 
      "ComputeMode": "string",
      "ProvisionedCapacity": { 
         "ActiveQueryTCU": number,
         "LastUpdate": { 
            "Status": "string",
            "StatusMessage": "string",
            "TargetQueryTCU": number
         },
         "NotificationConfiguration": { 
            "RoleArn": "string",
            "SnsConfiguration": { 
               "TopicArn": "string"
            }
         }
      }
   },
   "QueryPricingModel": "string"
}
```

## Response Elements
<a name="API_query_UpdateAccountSettings_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response.

The following data is returned in JSON format by the service.

 ** [MaxQueryTCU](#API_query_UpdateAccountSettings_ResponseSyntax) **   <a name="timestream-query_UpdateAccountSettings-response-MaxQueryTCU"></a>
The configured maximum number of compute units the service will use at any point in time to serve your queries.  
Type: Integer

 ** [QueryCompute](#API_query_UpdateAccountSettings_ResponseSyntax) **   <a name="timestream-query_UpdateAccountSettings-response-QueryCompute"></a>
Confirms the updated account settings for querying data in your account. QueryCompute is available only in the Asia Pacific (Mumbai) region.  
Type: [QueryComputeResponse](API_query_QueryComputeResponse.md) object

 ** [QueryPricingModel](#API_query_UpdateAccountSettings_ResponseSyntax) **   <a name="timestream-query_UpdateAccountSettings-response-QueryPricingModel"></a>
The pricing model for an account.  
Type: String  
Valid Values: `BYTES_SCANNED | COMPUTE_UNITS` 

## Errors
<a name="API_query_UpdateAccountSettings_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You do not have the necessary permissions to access the account settings.  
HTTP Status Code: 400

 ** InternalServerException **   
An internal server error occurred while processing the request.  
HTTP Status Code: 400

 ** InvalidEndpointException **   
The requested endpoint is invalid.  
HTTP Status Code: 400

 ** ThrottlingException **   
The request was throttled due to excessive requests.  
HTTP Status Code: 400

 ** ValidationException **   
 Invalid or malformed request.   
HTTP Status Code: 400

## See Also
<a name="API_query_UpdateAccountSettings_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-query-2018-11-01/UpdateAccountSettings) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-query-2018-11-01/UpdateAccountSettings) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/UpdateAccountSettings) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-query-2018-11-01/UpdateAccountSettings) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/UpdateAccountSettings) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-query-2018-11-01/UpdateAccountSettings) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-query-2018-11-01/UpdateAccountSettings) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-query-2018-11-01/UpdateAccountSettings) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-query-2018-11-01/UpdateAccountSettings) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/UpdateAccountSettings) 

# UpdateScheduledQuery
<a name="API_query_UpdateScheduledQuery"></a>

Update a scheduled query.

## Request Syntax
<a name="API_query_UpdateScheduledQuery_RequestSyntax"></a>

```
{
   "ScheduledQueryArn": "string",
   "State": "string"
}
```

## Request Parameters
<a name="API_query_UpdateScheduledQuery_RequestParameters"></a>

For information about the parameters that are common to all actions, see [Common Parameters](CommonParameters.md).

The request accepts the following data in JSON format.

 ** [ScheduledQueryArn](#API_query_UpdateScheduledQuery_RequestSyntax) **   <a name="timestream-query_UpdateScheduledQuery-request-ScheduledQueryArn"></a>
ARN of the scheuled query.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: Yes

 ** [State](#API_query_UpdateScheduledQuery_RequestSyntax) **   <a name="timestream-query_UpdateScheduledQuery-request-State"></a>
State of the scheduled query.   
Type: String  
Valid Values: `ENABLED | DISABLED`   
Required: Yes

## Response Elements
<a name="API_query_UpdateScheduledQuery_ResponseElements"></a>

If the action is successful, the service sends back an HTTP 200 response with an empty HTTP body.

## Errors
<a name="API_query_UpdateScheduledQuery_Errors"></a>

For information about the errors that are common to all actions, see [Common Error Types](CommonErrors.md).

 ** AccessDeniedException **   
You do not have the necessary permissions to access the account settings.  
HTTP Status Code: 400

 ** InternalServerException **   
An internal server error occurred while processing the request.  
HTTP Status Code: 400

 ** InvalidEndpointException **   
The requested endpoint is invalid.  
HTTP Status Code: 400

 ** ResourceNotFoundException **   
The requested resource could not be found.    
 ** ScheduledQueryArn **   
The ARN of the scheduled query.
HTTP Status Code: 400

 ** ThrottlingException **   
The request was throttled due to excessive requests.  
HTTP Status Code: 400

 ** ValidationException **   
 Invalid or malformed request.   
HTTP Status Code: 400

## See Also
<a name="API_query_UpdateScheduledQuery_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS Command Line Interface V2](https://docs.aws.amazon.com/goto/cli2/timestream-query-2018-11-01/UpdateScheduledQuery) 
+  [AWS SDK for .NET V4](https://docs.aws.amazon.com/goto/DotNetSDKV4/timestream-query-2018-11-01/UpdateScheduledQuery) 
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/UpdateScheduledQuery) 
+  [AWS SDK for Go v2](https://docs.aws.amazon.com/goto/SdkForGoV2/timestream-query-2018-11-01/UpdateScheduledQuery) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/UpdateScheduledQuery) 
+  [AWS SDK for JavaScript V3](https://docs.aws.amazon.com/goto/SdkForJavaScriptV3/timestream-query-2018-11-01/UpdateScheduledQuery) 
+  [AWS SDK for Kotlin](https://docs.aws.amazon.com/goto/SdkForKotlin/timestream-query-2018-11-01/UpdateScheduledQuery) 
+  [AWS SDK for PHP V3](https://docs.aws.amazon.com/goto/SdkForPHPV3/timestream-query-2018-11-01/UpdateScheduledQuery) 
+  [AWS SDK for Python](https://docs.aws.amazon.com/goto/boto3/timestream-query-2018-11-01/UpdateScheduledQuery) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/UpdateScheduledQuery) 

# Data Types
<a name="API_Types"></a>

The following data types are supported by Amazon Timestream Write:
+  [BatchLoadProgressReport](API_BatchLoadProgressReport.md) 
+  [BatchLoadTask](API_BatchLoadTask.md) 
+  [BatchLoadTaskDescription](API_BatchLoadTaskDescription.md) 
+  [CsvConfiguration](API_CsvConfiguration.md) 
+  [Database](API_Database.md) 
+  [DataModel](API_DataModel.md) 
+  [DataModelConfiguration](API_DataModelConfiguration.md) 
+  [DataModelS3Configuration](API_DataModelS3Configuration.md) 
+  [DataSourceConfiguration](API_DataSourceConfiguration.md) 
+  [DataSourceS3Configuration](API_DataSourceS3Configuration.md) 
+  [Dimension](API_Dimension.md) 
+  [DimensionMapping](API_DimensionMapping.md) 
+  [Endpoint](API_Endpoint.md) 
+  [MagneticStoreRejectedDataLocation](API_MagneticStoreRejectedDataLocation.md) 
+  [MagneticStoreWriteProperties](API_MagneticStoreWriteProperties.md) 
+  [MeasureValue](API_MeasureValue.md) 
+  [MixedMeasureMapping](API_MixedMeasureMapping.md) 
+  [MultiMeasureAttributeMapping](API_MultiMeasureAttributeMapping.md) 
+  [MultiMeasureMappings](API_MultiMeasureMappings.md) 
+  [PartitionKey](API_PartitionKey.md) 
+  [Record](API_Record.md) 
+  [RecordsIngested](API_RecordsIngested.md) 
+  [RejectedRecord](API_RejectedRecord.md) 
+  [ReportConfiguration](API_ReportConfiguration.md) 
+  [ReportS3Configuration](API_ReportS3Configuration.md) 
+  [RetentionProperties](API_RetentionProperties.md) 
+  [S3Configuration](API_S3Configuration.md) 
+  [Schema](API_Schema.md) 
+  [Table](API_Table.md) 
+  [Tag](API_Tag.md) 

The following data types are supported by Amazon Timestream Query:
+  [AccountSettingsNotificationConfiguration](API_query_AccountSettingsNotificationConfiguration.md) 
+  [ColumnInfo](API_query_ColumnInfo.md) 
+  [Datum](API_query_Datum.md) 
+  [DimensionMapping](API_query_DimensionMapping.md) 
+  [Endpoint](API_query_Endpoint.md) 
+  [ErrorReportConfiguration](API_query_ErrorReportConfiguration.md) 
+  [ErrorReportLocation](API_query_ErrorReportLocation.md) 
+  [ExecutionStats](API_query_ExecutionStats.md) 
+  [LastUpdate](API_query_LastUpdate.md) 
+  [MixedMeasureMapping](API_query_MixedMeasureMapping.md) 
+  [MultiMeasureAttributeMapping](API_query_MultiMeasureAttributeMapping.md) 
+  [MultiMeasureMappings](API_query_MultiMeasureMappings.md) 
+  [NotificationConfiguration](API_query_NotificationConfiguration.md) 
+  [ParameterMapping](API_query_ParameterMapping.md) 
+  [ProvisionedCapacityRequest](API_query_ProvisionedCapacityRequest.md) 
+  [ProvisionedCapacityResponse](API_query_ProvisionedCapacityResponse.md) 
+  [QueryComputeRequest](API_query_QueryComputeRequest.md) 
+  [QueryComputeResponse](API_query_QueryComputeResponse.md) 
+  [QueryInsights](API_query_QueryInsights.md) 
+  [QueryInsightsResponse](API_query_QueryInsightsResponse.md) 
+  [QuerySpatialCoverage](API_query_QuerySpatialCoverage.md) 
+  [QuerySpatialCoverageMax](API_query_QuerySpatialCoverageMax.md) 
+  [QueryStatus](API_query_QueryStatus.md) 
+  [QueryTemporalRange](API_query_QueryTemporalRange.md) 
+  [QueryTemporalRangeMax](API_query_QueryTemporalRangeMax.md) 
+  [Row](API_query_Row.md) 
+  [S3Configuration](API_query_S3Configuration.md) 
+  [S3ReportLocation](API_query_S3ReportLocation.md) 
+  [ScheduleConfiguration](API_query_ScheduleConfiguration.md) 
+  [ScheduledQuery](API_query_ScheduledQuery.md) 
+  [ScheduledQueryDescription](API_query_ScheduledQueryDescription.md) 
+  [ScheduledQueryInsights](API_query_ScheduledQueryInsights.md) 
+  [ScheduledQueryInsightsResponse](API_query_ScheduledQueryInsightsResponse.md) 
+  [ScheduledQueryRunSummary](API_query_ScheduledQueryRunSummary.md) 
+  [SelectColumn](API_query_SelectColumn.md) 
+  [SnsConfiguration](API_query_SnsConfiguration.md) 
+  [Tag](API_query_Tag.md) 
+  [TargetConfiguration](API_query_TargetConfiguration.md) 
+  [TargetDestination](API_query_TargetDestination.md) 
+  [TimeSeriesDataPoint](API_query_TimeSeriesDataPoint.md) 
+  [TimestreamConfiguration](API_query_TimestreamConfiguration.md) 
+  [TimestreamDestination](API_query_TimestreamDestination.md) 
+  [Type](API_query_Type.md) 

# Amazon Timestream Write
<a name="API_Types_Amazon_Timestream_Write"></a>

The following data types are supported by Amazon Timestream Write:
+  [BatchLoadProgressReport](API_BatchLoadProgressReport.md) 
+  [BatchLoadTask](API_BatchLoadTask.md) 
+  [BatchLoadTaskDescription](API_BatchLoadTaskDescription.md) 
+  [CsvConfiguration](API_CsvConfiguration.md) 
+  [Database](API_Database.md) 
+  [DataModel](API_DataModel.md) 
+  [DataModelConfiguration](API_DataModelConfiguration.md) 
+  [DataModelS3Configuration](API_DataModelS3Configuration.md) 
+  [DataSourceConfiguration](API_DataSourceConfiguration.md) 
+  [DataSourceS3Configuration](API_DataSourceS3Configuration.md) 
+  [Dimension](API_Dimension.md) 
+  [DimensionMapping](API_DimensionMapping.md) 
+  [Endpoint](API_Endpoint.md) 
+  [MagneticStoreRejectedDataLocation](API_MagneticStoreRejectedDataLocation.md) 
+  [MagneticStoreWriteProperties](API_MagneticStoreWriteProperties.md) 
+  [MeasureValue](API_MeasureValue.md) 
+  [MixedMeasureMapping](API_MixedMeasureMapping.md) 
+  [MultiMeasureAttributeMapping](API_MultiMeasureAttributeMapping.md) 
+  [MultiMeasureMappings](API_MultiMeasureMappings.md) 
+  [PartitionKey](API_PartitionKey.md) 
+  [Record](API_Record.md) 
+  [RecordsIngested](API_RecordsIngested.md) 
+  [RejectedRecord](API_RejectedRecord.md) 
+  [ReportConfiguration](API_ReportConfiguration.md) 
+  [ReportS3Configuration](API_ReportS3Configuration.md) 
+  [RetentionProperties](API_RetentionProperties.md) 
+  [S3Configuration](API_S3Configuration.md) 
+  [Schema](API_Schema.md) 
+  [Table](API_Table.md) 
+  [Tag](API_Tag.md) 

# BatchLoadProgressReport
<a name="API_BatchLoadProgressReport"></a>

Details about the progress of a batch load task.

## Contents
<a name="API_BatchLoadProgressReport_Contents"></a>

 ** BytesMetered **   <a name="timestream-Type-BatchLoadProgressReport-BytesMetered"></a>
  
Type: Long  
Required: No

 ** FileFailures **   <a name="timestream-Type-BatchLoadProgressReport-FileFailures"></a>
  
Type: Long  
Required: No

 ** ParseFailures **   <a name="timestream-Type-BatchLoadProgressReport-ParseFailures"></a>
  
Type: Long  
Required: No

 ** RecordIngestionFailures **   <a name="timestream-Type-BatchLoadProgressReport-RecordIngestionFailures"></a>
  
Type: Long  
Required: No

 ** RecordsIngested **   <a name="timestream-Type-BatchLoadProgressReport-RecordsIngested"></a>
  
Type: Long  
Required: No

 ** RecordsProcessed **   <a name="timestream-Type-BatchLoadProgressReport-RecordsProcessed"></a>
  
Type: Long  
Required: No

## See Also
<a name="API_BatchLoadProgressReport_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/BatchLoadProgressReport) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/BatchLoadProgressReport) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/BatchLoadProgressReport) 

# BatchLoadTask
<a name="API_BatchLoadTask"></a>

Details about a batch load task.

## Contents
<a name="API_BatchLoadTask_Contents"></a>

 ** CreationTime **   <a name="timestream-Type-BatchLoadTask-CreationTime"></a>
The time when the Timestream batch load task was created.  
Type: Timestamp  
Required: No

 ** DatabaseName **   <a name="timestream-Type-BatchLoadTask-DatabaseName"></a>
Database name for the database into which a batch load task loads data.  
Type: String  
Required: No

 ** LastUpdatedTime **   <a name="timestream-Type-BatchLoadTask-LastUpdatedTime"></a>
The time when the Timestream batch load task was last updated.  
Type: Timestamp  
Required: No

 ** ResumableUntil **   <a name="timestream-Type-BatchLoadTask-ResumableUntil"></a>
   
Type: Timestamp  
Required: No

 ** TableName **   <a name="timestream-Type-BatchLoadTask-TableName"></a>
Table name for the table into which a batch load task loads data.  
Type: String  
Required: No

 ** TaskId **   <a name="timestream-Type-BatchLoadTask-TaskId"></a>
The ID of the batch load task.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 32.  
Pattern: `[A-Z0-9]+`   
Required: No

 ** TaskStatus **   <a name="timestream-Type-BatchLoadTask-TaskStatus"></a>
Status of the batch load task.  
Type: String  
Valid Values: `CREATED | IN_PROGRESS | FAILED | SUCCEEDED | PROGRESS_STOPPED | PENDING_RESUME`   
Required: No

## See Also
<a name="API_BatchLoadTask_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/BatchLoadTask) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/BatchLoadTask) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/BatchLoadTask) 

# BatchLoadTaskDescription
<a name="API_BatchLoadTaskDescription"></a>

Details about a batch load task.

## Contents
<a name="API_BatchLoadTaskDescription_Contents"></a>

 ** CreationTime **   <a name="timestream-Type-BatchLoadTaskDescription-CreationTime"></a>
The time when the Timestream batch load task was created.  
Type: Timestamp  
Required: No

 ** DataModelConfiguration **   <a name="timestream-Type-BatchLoadTaskDescription-DataModelConfiguration"></a>
Data model configuration for a batch load task. This contains details about where a data model for a batch load task is stored.  
Type: [DataModelConfiguration](API_DataModelConfiguration.md) object  
Required: No

 ** DataSourceConfiguration **   <a name="timestream-Type-BatchLoadTaskDescription-DataSourceConfiguration"></a>
Configuration details about the data source for a batch load task.  
Type: [DataSourceConfiguration](API_DataSourceConfiguration.md) object  
Required: No

 ** ErrorMessage **   <a name="timestream-Type-BatchLoadTaskDescription-ErrorMessage"></a>
  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: No

 ** LastUpdatedTime **   <a name="timestream-Type-BatchLoadTaskDescription-LastUpdatedTime"></a>
The time when the Timestream batch load task was last updated.  
Type: Timestamp  
Required: No

 ** ProgressReport **   <a name="timestream-Type-BatchLoadTaskDescription-ProgressReport"></a>
  
Type: [BatchLoadProgressReport](API_BatchLoadProgressReport.md) object  
Required: No

 ** RecordVersion **   <a name="timestream-Type-BatchLoadTaskDescription-RecordVersion"></a>
  
Type: Long  
Required: No

 ** ReportConfiguration **   <a name="timestream-Type-BatchLoadTaskDescription-ReportConfiguration"></a>
Report configuration for a batch load task. This contains details about where error reports are stored.  
Type: [ReportConfiguration](API_ReportConfiguration.md) object  
Required: No

 ** ResumableUntil **   <a name="timestream-Type-BatchLoadTaskDescription-ResumableUntil"></a>
   
Type: Timestamp  
Required: No

 ** TargetDatabaseName **   <a name="timestream-Type-BatchLoadTaskDescription-TargetDatabaseName"></a>
  
Type: String  
Required: No

 ** TargetTableName **   <a name="timestream-Type-BatchLoadTaskDescription-TargetTableName"></a>
  
Type: String  
Required: No

 ** TaskId **   <a name="timestream-Type-BatchLoadTaskDescription-TaskId"></a>
The ID of the batch load task.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 32.  
Pattern: `[A-Z0-9]+`   
Required: No

 ** TaskStatus **   <a name="timestream-Type-BatchLoadTaskDescription-TaskStatus"></a>
Status of the batch load task.  
Type: String  
Valid Values: `CREATED | IN_PROGRESS | FAILED | SUCCEEDED | PROGRESS_STOPPED | PENDING_RESUME`   
Required: No

## See Also
<a name="API_BatchLoadTaskDescription_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/BatchLoadTaskDescription) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/BatchLoadTaskDescription) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/BatchLoadTaskDescription) 

# CsvConfiguration
<a name="API_CsvConfiguration"></a>

A delimited data format where the column separator can be a comma and the record separator is a newline character.

## Contents
<a name="API_CsvConfiguration_Contents"></a>

 ** ColumnSeparator **   <a name="timestream-Type-CsvConfiguration-ColumnSeparator"></a>
Column separator can be one of comma (','), pipe ('\$1), semicolon (';'), tab('/t'), or blank space (' ').   
Type: String  
Length Constraints: Fixed length of 1.  
Required: No

 ** EscapeChar **   <a name="timestream-Type-CsvConfiguration-EscapeChar"></a>
Escape character can be one of   
Type: String  
Length Constraints: Fixed length of 1.  
Required: No

 ** NullValue **   <a name="timestream-Type-CsvConfiguration-NullValue"></a>
Can be blank space (' ').  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 256.  
Required: No

 ** QuoteChar **   <a name="timestream-Type-CsvConfiguration-QuoteChar"></a>
Can be single quote (') or double quote (").  
Type: String  
Length Constraints: Fixed length of 1.  
Required: No

 ** TrimWhiteSpace **   <a name="timestream-Type-CsvConfiguration-TrimWhiteSpace"></a>
Specifies to trim leading and trailing white space.  
Type: Boolean  
Required: No

## See Also
<a name="API_CsvConfiguration_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/CsvConfiguration) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/CsvConfiguration) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/CsvConfiguration) 

# Database
<a name="API_Database"></a>

A top-level container for a table. Databases and tables are the fundamental management concepts in Amazon Timestream. All tables in a database are encrypted with the same AWS KMS key.

## Contents
<a name="API_Database_Contents"></a>

 ** Arn **   <a name="timestream-Type-Database-Arn"></a>
The Amazon Resource Name that uniquely identifies this database.  
Type: String  
Required: No

 ** CreationTime **   <a name="timestream-Type-Database-CreationTime"></a>
The time when the database was created, calculated from the Unix epoch time.  
Type: Timestamp  
Required: No

 ** DatabaseName **   <a name="timestream-Type-Database-DatabaseName"></a>
The name of the Timestream database.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 256.  
Required: No

 ** KmsKeyId **   <a name="timestream-Type-Database-KmsKeyId"></a>
The identifier of the AWS KMS key used to encrypt the data stored in the database.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: No

 ** LastUpdatedTime **   <a name="timestream-Type-Database-LastUpdatedTime"></a>
 The last time that this database was updated.   
Type: Timestamp  
Required: No

 ** TableCount **   <a name="timestream-Type-Database-TableCount"></a>
The total number of tables found within a Timestream database.   
Type: Long  
Required: No

## See Also
<a name="API_Database_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/Database) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/Database) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/Database) 

# DataModel
<a name="API_DataModel"></a>

Data model for a batch load task.

## Contents
<a name="API_DataModel_Contents"></a>

 ** DimensionMappings **   <a name="timestream-Type-DataModel-DimensionMappings"></a>
Source to target mappings for dimensions.  
Type: Array of [DimensionMapping](API_DimensionMapping.md) objects  
Array Members: Minimum number of 1 item.  
Required: Yes

 ** MeasureNameColumn **   <a name="timestream-Type-DataModel-MeasureNameColumn"></a>
  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 256.  
Required: No

 ** MixedMeasureMappings **   <a name="timestream-Type-DataModel-MixedMeasureMappings"></a>
Source to target mappings for measures.  
Type: Array of [MixedMeasureMapping](API_MixedMeasureMapping.md) objects  
Array Members: Minimum number of 1 item.  
Required: No

 ** MultiMeasureMappings **   <a name="timestream-Type-DataModel-MultiMeasureMappings"></a>
Source to target mappings for multi-measure records.  
Type: [MultiMeasureMappings](API_MultiMeasureMappings.md) object  
Required: No

 ** TimeColumn **   <a name="timestream-Type-DataModel-TimeColumn"></a>
Source column to be mapped to time.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 256.  
Required: No

 ** TimeUnit **   <a name="timestream-Type-DataModel-TimeUnit"></a>
 The granularity of the timestamp unit. It indicates if the time value is in seconds, milliseconds, nanoseconds, or other supported values. Default is `MILLISECONDS`.   
Type: String  
Valid Values: `MILLISECONDS | SECONDS | MICROSECONDS | NANOSECONDS`   
Required: No

## See Also
<a name="API_DataModel_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/DataModel) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/DataModel) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/DataModel) 

# DataModelConfiguration
<a name="API_DataModelConfiguration"></a>



## Contents
<a name="API_DataModelConfiguration_Contents"></a>

 ** DataModel **   <a name="timestream-Type-DataModelConfiguration-DataModel"></a>
  
Type: [DataModel](API_DataModel.md) object  
Required: No

 ** DataModelS3Configuration **   <a name="timestream-Type-DataModelConfiguration-DataModelS3Configuration"></a>
  
Type: [DataModelS3Configuration](API_DataModelS3Configuration.md) object  
Required: No

## See Also
<a name="API_DataModelConfiguration_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/DataModelConfiguration) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/DataModelConfiguration) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/DataModelConfiguration) 

# DataModelS3Configuration
<a name="API_DataModelS3Configuration"></a>



## Contents
<a name="API_DataModelS3Configuration_Contents"></a>

 ** BucketName **   <a name="timestream-Type-DataModelS3Configuration-BucketName"></a>
  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 63.  
Pattern: `[a-z0-9][\.\-a-z0-9]{1,61}[a-z0-9]`   
Required: No

 ** ObjectKey **   <a name="timestream-Type-DataModelS3Configuration-ObjectKey"></a>
  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 1024.  
Pattern: `[a-zA-Z0-9|!\-_*'\(\)]([a-zA-Z0-9]|[!\-_*'\(\)\/.])+`   
Required: No

## See Also
<a name="API_DataModelS3Configuration_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/DataModelS3Configuration) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/DataModelS3Configuration) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/DataModelS3Configuration) 

# DataSourceConfiguration
<a name="API_DataSourceConfiguration"></a>

Defines configuration details about the data source.

## Contents
<a name="API_DataSourceConfiguration_Contents"></a>

 ** DataFormat **   <a name="timestream-Type-DataSourceConfiguration-DataFormat"></a>
This is currently CSV.  
Type: String  
Valid Values: `CSV`   
Required: Yes

 ** DataSourceS3Configuration **   <a name="timestream-Type-DataSourceConfiguration-DataSourceS3Configuration"></a>
Configuration of an S3 location for a file which contains data to load.  
Type: [DataSourceS3Configuration](API_DataSourceS3Configuration.md) object  
Required: Yes

 ** CsvConfiguration **   <a name="timestream-Type-DataSourceConfiguration-CsvConfiguration"></a>
A delimited data format where the column separator can be a comma and the record separator is a newline character.  
Type: [CsvConfiguration](API_CsvConfiguration.md) object  
Required: No

## See Also
<a name="API_DataSourceConfiguration_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/DataSourceConfiguration) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/DataSourceConfiguration) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/DataSourceConfiguration) 

# DataSourceS3Configuration
<a name="API_DataSourceS3Configuration"></a>

 

## Contents
<a name="API_DataSourceS3Configuration_Contents"></a>

 ** BucketName **   <a name="timestream-Type-DataSourceS3Configuration-BucketName"></a>
The bucket name of the customer S3 bucket.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 63.  
Pattern: `[a-z0-9][\.\-a-z0-9]{1,61}[a-z0-9]`   
Required: Yes

 ** ObjectKeyPrefix **   <a name="timestream-Type-DataSourceS3Configuration-ObjectKeyPrefix"></a>
   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 1024.  
Pattern: `[a-zA-Z0-9|!\-_*'\(\)]([a-zA-Z0-9]|[!\-_*'\(\)\/.])+`   
Required: No

## See Also
<a name="API_DataSourceS3Configuration_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/DataSourceS3Configuration) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/DataSourceS3Configuration) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/DataSourceS3Configuration) 

# Dimension
<a name="API_Dimension"></a>

Represents the metadata attributes of the time series. For example, the name and Availability Zone of an EC2 instance or the name of the manufacturer of a wind turbine are dimensions. 

## Contents
<a name="API_Dimension_Contents"></a>

 ** Name **   <a name="timestream-Type-Dimension-Name"></a>
 Dimension represents the metadata attributes of the time series. For example, the name and Availability Zone of an EC2 instance or the name of the manufacturer of a wind turbine are dimensions.   
For constraints on dimension names, see [Naming Constraints](https://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html#limits.naming).  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 60.  
Required: Yes

 ** Value **   <a name="timestream-Type-Dimension-Value"></a>
The value of the dimension.  
Type: String  
Required: Yes

 ** DimensionValueType **   <a name="timestream-Type-Dimension-DimensionValueType"></a>
The data type of the dimension for the time-series data point.  
Type: String  
Valid Values: `VARCHAR`   
Required: No

## See Also
<a name="API_Dimension_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/Dimension) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/Dimension) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/Dimension) 

# DimensionMapping
<a name="API_DimensionMapping"></a>



## Contents
<a name="API_DimensionMapping_Contents"></a>

 ** DestinationColumn **   <a name="timestream-Type-DimensionMapping-DestinationColumn"></a>
   
Type: String  
Length Constraints: Minimum length of 1.  
Required: No

 ** SourceColumn **   <a name="timestream-Type-DimensionMapping-SourceColumn"></a>
  
Type: String  
Length Constraints: Minimum length of 1.  
Required: No

## See Also
<a name="API_DimensionMapping_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/DimensionMapping) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/DimensionMapping) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/DimensionMapping) 

# Endpoint
<a name="API_Endpoint"></a>

Represents an available endpoint against which to make API calls against, as well as the TTL for that endpoint.

## Contents
<a name="API_Endpoint_Contents"></a>

 ** Address **   <a name="timestream-Type-Endpoint-Address"></a>
An endpoint address.  
Type: String  
Required: Yes

 ** CachePeriodInMinutes **   <a name="timestream-Type-Endpoint-CachePeriodInMinutes"></a>
The TTL for the endpoint, in minutes.  
Type: Long  
Required: Yes

## See Also
<a name="API_Endpoint_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/Endpoint) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/Endpoint) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/Endpoint) 

# MagneticStoreRejectedDataLocation
<a name="API_MagneticStoreRejectedDataLocation"></a>

The location to write error reports for records rejected, asynchronously, during magnetic store writes.

## Contents
<a name="API_MagneticStoreRejectedDataLocation_Contents"></a>

 ** S3Configuration **   <a name="timestream-Type-MagneticStoreRejectedDataLocation-S3Configuration"></a>
Configuration of an S3 location to write error reports for records rejected, asynchronously, during magnetic store writes.  
Type: [S3Configuration](API_S3Configuration.md) object  
Required: No

## See Also
<a name="API_MagneticStoreRejectedDataLocation_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/MagneticStoreRejectedDataLocation) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/MagneticStoreRejectedDataLocation) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/MagneticStoreRejectedDataLocation) 

# MagneticStoreWriteProperties
<a name="API_MagneticStoreWriteProperties"></a>

The set of properties on a table for configuring magnetic store writes.

## Contents
<a name="API_MagneticStoreWriteProperties_Contents"></a>

 ** EnableMagneticStoreWrites **   <a name="timestream-Type-MagneticStoreWriteProperties-EnableMagneticStoreWrites"></a>
A flag to enable magnetic store writes.  
Type: Boolean  
Required: Yes

 ** MagneticStoreRejectedDataLocation **   <a name="timestream-Type-MagneticStoreWriteProperties-MagneticStoreRejectedDataLocation"></a>
The location to write error reports for records rejected asynchronously during magnetic store writes.  
Type: [MagneticStoreRejectedDataLocation](API_MagneticStoreRejectedDataLocation.md) object  
Required: No

## See Also
<a name="API_MagneticStoreWriteProperties_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/MagneticStoreWriteProperties) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/MagneticStoreWriteProperties) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/MagneticStoreWriteProperties) 

# MeasureValue
<a name="API_MeasureValue"></a>

 Represents the data attribute of the time series. For example, the CPU utilization of an EC2 instance or the RPM of a wind turbine are measures. MeasureValue has both name and value. 

 MeasureValue is only allowed for type `MULTI`. Using `MULTI` type, you can pass multiple data attributes associated with the same time series in a single record 

## Contents
<a name="API_MeasureValue_Contents"></a>

 ** Name **   <a name="timestream-Type-MeasureValue-Name"></a>
 The name of the MeasureValue.   
 For constraints on MeasureValue names, see [ Naming Constraints](https://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html#limits.naming) in the Amazon Timestream Developer Guide.  
Type: String  
Length Constraints: Minimum length of 1.  
Required: Yes

 ** Type **   <a name="timestream-Type-MeasureValue-Type"></a>
Contains the data type of the MeasureValue for the time-series data point.  
Type: String  
Valid Values: `DOUBLE | BIGINT | VARCHAR | BOOLEAN | TIMESTAMP | MULTI`   
Required: Yes

 ** Value **   <a name="timestream-Type-MeasureValue-Value"></a>
 The value for the MeasureValue. For information, see [Data types](https://docs.aws.amazon.com/timestream/latest/developerguide/writes.html#writes.data-types).  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: Yes

## See Also
<a name="API_MeasureValue_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/MeasureValue) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/MeasureValue) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/MeasureValue) 

# MixedMeasureMapping
<a name="API_MixedMeasureMapping"></a>



## Contents
<a name="API_MixedMeasureMapping_Contents"></a>

 ** MeasureValueType **   <a name="timestream-Type-MixedMeasureMapping-MeasureValueType"></a>
  
Type: String  
Valid Values: `DOUBLE | BIGINT | VARCHAR | BOOLEAN | TIMESTAMP | MULTI`   
Required: Yes

 ** MeasureName **   <a name="timestream-Type-MixedMeasureMapping-MeasureName"></a>
  
Type: String  
Length Constraints: Minimum length of 1.  
Required: No

 ** MultiMeasureAttributeMappings **   <a name="timestream-Type-MixedMeasureMapping-MultiMeasureAttributeMappings"></a>
  
Type: Array of [MultiMeasureAttributeMapping](API_MultiMeasureAttributeMapping.md) objects  
Array Members: Minimum number of 1 item.  
Required: No

 ** SourceColumn **   <a name="timestream-Type-MixedMeasureMapping-SourceColumn"></a>
  
Type: String  
Length Constraints: Minimum length of 1.  
Required: No

 ** TargetMeasureName **   <a name="timestream-Type-MixedMeasureMapping-TargetMeasureName"></a>
  
Type: String  
Length Constraints: Minimum length of 1.  
Required: No

## See Also
<a name="API_MixedMeasureMapping_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/MixedMeasureMapping) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/MixedMeasureMapping) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/MixedMeasureMapping) 

# MultiMeasureAttributeMapping
<a name="API_MultiMeasureAttributeMapping"></a>



## Contents
<a name="API_MultiMeasureAttributeMapping_Contents"></a>

 ** SourceColumn **   <a name="timestream-Type-MultiMeasureAttributeMapping-SourceColumn"></a>
  
Type: String  
Length Constraints: Minimum length of 1.  
Required: Yes

 ** MeasureValueType **   <a name="timestream-Type-MultiMeasureAttributeMapping-MeasureValueType"></a>
  
Type: String  
Valid Values: `DOUBLE | BIGINT | BOOLEAN | VARCHAR | TIMESTAMP`   
Required: No

 ** TargetMultiMeasureAttributeName **   <a name="timestream-Type-MultiMeasureAttributeMapping-TargetMultiMeasureAttributeName"></a>
  
Type: String  
Length Constraints: Minimum length of 1.  
Required: No

## See Also
<a name="API_MultiMeasureAttributeMapping_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/MultiMeasureAttributeMapping) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/MultiMeasureAttributeMapping) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/MultiMeasureAttributeMapping) 

# MultiMeasureMappings
<a name="API_MultiMeasureMappings"></a>



## Contents
<a name="API_MultiMeasureMappings_Contents"></a>

 ** MultiMeasureAttributeMappings **   <a name="timestream-Type-MultiMeasureMappings-MultiMeasureAttributeMappings"></a>
  
Type: Array of [MultiMeasureAttributeMapping](API_MultiMeasureAttributeMapping.md) objects  
Array Members: Minimum number of 1 item.  
Required: Yes

 ** TargetMultiMeasureName **   <a name="timestream-Type-MultiMeasureMappings-TargetMultiMeasureName"></a>
  
Type: String  
Length Constraints: Minimum length of 1.  
Required: No

## See Also
<a name="API_MultiMeasureMappings_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/MultiMeasureMappings) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/MultiMeasureMappings) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/MultiMeasureMappings) 

# PartitionKey
<a name="API_PartitionKey"></a>

 An attribute used in partitioning data in a table. A dimension key partitions data using the values of the dimension specified by the dimension-name as partition key, while a measure key partitions data using measure names (values of the 'measure\$1name' column). 

## Contents
<a name="API_PartitionKey_Contents"></a>

 ** Type **   <a name="timestream-Type-PartitionKey-Type"></a>
 The type of the partition key. Options are DIMENSION (dimension key) and MEASURE (measure key).   
Type: String  
Valid Values: `DIMENSION | MEASURE`   
Required: Yes

 ** EnforcementInRecord **   <a name="timestream-Type-PartitionKey-EnforcementInRecord"></a>
 The level of enforcement for the specification of a dimension key in ingested records. Options are REQUIRED (dimension key must be specified) and OPTIONAL (dimension key does not have to be specified).   
Type: String  
Valid Values: `REQUIRED | OPTIONAL`   
Required: No

 ** Name **   <a name="timestream-Type-PartitionKey-Name"></a>
 The name of the attribute used for a dimension key.   
Type: String  
Length Constraints: Minimum length of 1.  
Required: No

## See Also
<a name="API_PartitionKey_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/PartitionKey) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/PartitionKey) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/PartitionKey) 

# Record
<a name="API_Record"></a>

Represents a time-series data point being written into Timestream. Each record contains an array of dimensions. Dimensions represent the metadata attributes of a time-series data point, such as the instance name or Availability Zone of an EC2 instance. A record also contains the measure name, which is the name of the measure being collected (for example, the CPU utilization of an EC2 instance). Additionally, a record contains the measure value and the value type, which is the data type of the measure value. Also, the record contains the timestamp of when the measure was collected and the timestamp unit, which represents the granularity of the timestamp. 

 Records have a `Version` field, which is a 64-bit `long` that you can use for updating data points. Writes of a duplicate record with the same dimension, timestamp, and measure name but different measure value will only succeed if the `Version` attribute of the record in the write request is higher than that of the existing record. Timestream defaults to a `Version` of `1` for records without the `Version` field. 

## Contents
<a name="API_Record_Contents"></a>

 ** Dimensions **   <a name="timestream-Type-Record-Dimensions"></a>
Contains the list of dimensions for time-series data points.  
Type: Array of [Dimension](API_Dimension.md) objects  
Array Members: Maximum number of 128 items.  
Required: No

 ** MeasureName **   <a name="timestream-Type-Record-MeasureName"></a>
Measure represents the data attribute of the time series. For example, the CPU utilization of an EC2 instance or the RPM of a wind turbine are measures.   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 256.  
Required: No

 ** MeasureValue **   <a name="timestream-Type-Record-MeasureValue"></a>
 Contains the measure value for the time-series data point.   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: No

 ** MeasureValues **   <a name="timestream-Type-Record-MeasureValues"></a>
 Contains the list of MeasureValue for time-series data points.   
 This is only allowed for type `MULTI`. For scalar values, use `MeasureValue` attribute of the record directly.   
Type: Array of [MeasureValue](API_MeasureValue.md) objects  
Required: No

 ** MeasureValueType **   <a name="timestream-Type-Record-MeasureValueType"></a>
 Contains the data type of the measure value for the time-series data point. Default type is `DOUBLE`. For more information, see [Data types](https://docs.aws.amazon.com/timestream/latest/developerguide/writes.html#writes.data-types).  
Type: String  
Valid Values: `DOUBLE | BIGINT | VARCHAR | BOOLEAN | TIMESTAMP | MULTI`   
Required: No

 ** Time **   <a name="timestream-Type-Record-Time"></a>
 Contains the time at which the measure value for the data point was collected. The time value plus the unit provides the time elapsed since the epoch. For example, if the time value is `12345` and the unit is `ms`, then `12345 ms` have elapsed since the epoch.   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 256.  
Required: No

 ** TimeUnit **   <a name="timestream-Type-Record-TimeUnit"></a>
 The granularity of the timestamp unit. It indicates if the time value is in seconds, milliseconds, nanoseconds, or other supported values. Default is `MILLISECONDS`.   
Type: String  
Valid Values: `MILLISECONDS | SECONDS | MICROSECONDS | NANOSECONDS`   
Required: No

 ** Version **   <a name="timestream-Type-Record-Version"></a>
64-bit attribute used for record updates. Write requests for duplicate data with a higher version number will update the existing measure value and version. In cases where the measure value is the same, `Version` will still be updated. Default value is `1`.  
 `Version` must be `1` or greater, or you will receive a `ValidationException` error.
Type: Long  
Required: No

## See Also
<a name="API_Record_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/Record) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/Record) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/Record) 

# RecordsIngested
<a name="API_RecordsIngested"></a>

Information on the records ingested by this request.

## Contents
<a name="API_RecordsIngested_Contents"></a>

 ** MagneticStore **   <a name="timestream-Type-RecordsIngested-MagneticStore"></a>
Count of records ingested into the magnetic store.  
Type: Integer  
Required: No

 ** MemoryStore **   <a name="timestream-Type-RecordsIngested-MemoryStore"></a>
Count of records ingested into the memory store.  
Type: Integer  
Required: No

 ** Total **   <a name="timestream-Type-RecordsIngested-Total"></a>
Total count of successfully ingested records.  
Type: Integer  
Required: No

## See Also
<a name="API_RecordsIngested_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/RecordsIngested) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/RecordsIngested) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/RecordsIngested) 

# RejectedRecord
<a name="API_RejectedRecord"></a>

 Represents records that were not successfully inserted into Timestream due to data validation issues that must be resolved before reinserting time-series data into the system. 

## Contents
<a name="API_RejectedRecord_Contents"></a>

 ** ExistingVersion **   <a name="timestream-Type-RejectedRecord-ExistingVersion"></a>
The existing version of the record. This value is populated in scenarios where an identical record exists with a higher version than the version in the write request.  
Type: Long  
Required: No

 ** Reason **   <a name="timestream-Type-RejectedRecord-Reason"></a>
 The reason why a record was not successfully inserted into Timestream. Possible causes of failure include:   
+ Records with duplicate data where there are multiple records with the same dimensions, timestamps, and measure names but: 
  + Measure values are different
  + Version is not present in the request, *or* the value of version in the new record is equal to or lower than the existing value

  If Timestream rejects data for this case, the `ExistingVersion` field in the `RejectedRecords` response will indicate the current record’s version. To force an update, you can resend the request with a version for the record set to a value greater than the `ExistingVersion`.
+  Records with timestamps that lie outside the retention duration of the memory store. 
**Note**  
When the retention window is updated, you will receive a `RejectedRecords` exception if you immediately try to ingest data within the new window. To avoid a `RejectedRecords` exception, wait until the duration of the new window to ingest new data. For further information, see [ Best Practices for Configuring Timestream](https://docs.aws.amazon.com/timestream/latest/developerguide/best-practices.html#configuration) and [the explanation of how storage works in Timestream](https://docs.aws.amazon.com/timestream/latest/developerguide/storage.html).
+  Records with dimensions or measures that exceed the Timestream defined limits. 
 For more information, see [Access Management](https://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html) in the Timestream Developer Guide.   
Type: String  
Required: No

 ** RecordIndex **   <a name="timestream-Type-RejectedRecord-RecordIndex"></a>
 The index of the record in the input request for WriteRecords. Indexes begin with 0.   
Type: Integer  
Required: No

## See Also
<a name="API_RejectedRecord_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/RejectedRecord) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/RejectedRecord) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/RejectedRecord) 

# ReportConfiguration
<a name="API_ReportConfiguration"></a>

Report configuration for a batch load task. This contains details about where error reports are stored.

## Contents
<a name="API_ReportConfiguration_Contents"></a>

 ** ReportS3Configuration **   <a name="timestream-Type-ReportConfiguration-ReportS3Configuration"></a>
Configuration of an S3 location to write error reports and events for a batch load.  
Type: [ReportS3Configuration](API_ReportS3Configuration.md) object  
Required: No

## See Also
<a name="API_ReportConfiguration_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/ReportConfiguration) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/ReportConfiguration) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/ReportConfiguration) 

# ReportS3Configuration
<a name="API_ReportS3Configuration"></a>



## Contents
<a name="API_ReportS3Configuration_Contents"></a>

 ** BucketName **   <a name="timestream-Type-ReportS3Configuration-BucketName"></a>
  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 63.  
Pattern: `[a-z0-9][\.\-a-z0-9]{1,61}[a-z0-9]`   
Required: Yes

 ** EncryptionOption **   <a name="timestream-Type-ReportS3Configuration-EncryptionOption"></a>
  
Type: String  
Valid Values: `SSE_S3 | SSE_KMS`   
Required: No

 ** KmsKeyId **   <a name="timestream-Type-ReportS3Configuration-KmsKeyId"></a>
  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: No

 ** ObjectKeyPrefix **   <a name="timestream-Type-ReportS3Configuration-ObjectKeyPrefix"></a>
  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 928.  
Pattern: `[a-zA-Z0-9|!\-_*'\(\)]([a-zA-Z0-9]|[!\-_*'\(\)\/.])+`   
Required: No

## See Also
<a name="API_ReportS3Configuration_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/ReportS3Configuration) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/ReportS3Configuration) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/ReportS3Configuration) 

# RetentionProperties
<a name="API_RetentionProperties"></a>

Retention properties contain the duration for which your time-series data must be stored in the magnetic store and the memory store. 

## Contents
<a name="API_RetentionProperties_Contents"></a>

 ** MagneticStoreRetentionPeriodInDays **   <a name="timestream-Type-RetentionProperties-MagneticStoreRetentionPeriodInDays"></a>
The duration for which data must be stored in the magnetic store.   
Type: Long  
Valid Range: Minimum value of 1. Maximum value of 73000.  
Required: Yes

 ** MemoryStoreRetentionPeriodInHours **   <a name="timestream-Type-RetentionProperties-MemoryStoreRetentionPeriodInHours"></a>
The duration for which data must be stored in the memory store.   
Type: Long  
Valid Range: Minimum value of 1. Maximum value of 8766.  
Required: Yes

## See Also
<a name="API_RetentionProperties_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/RetentionProperties) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/RetentionProperties) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/RetentionProperties) 

# S3Configuration
<a name="API_S3Configuration"></a>

The configuration that specifies an S3 location.

## Contents
<a name="API_S3Configuration_Contents"></a>

 ** BucketName **   <a name="timestream-Type-S3Configuration-BucketName"></a>
The bucket name of the customer S3 bucket.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 63.  
Pattern: `[a-z0-9][\.\-a-z0-9]{1,61}[a-z0-9]`   
Required: No

 ** EncryptionOption **   <a name="timestream-Type-S3Configuration-EncryptionOption"></a>
The encryption option for the customer S3 location. Options are S3 server-side encryption with an S3 managed key or AWS managed key.  
Type: String  
Valid Values: `SSE_S3 | SSE_KMS`   
Required: No

 ** KmsKeyId **   <a name="timestream-Type-S3Configuration-KmsKeyId"></a>
The AWS KMS key ID for the customer S3 location when encrypting with an AWS managed key.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: No

 ** ObjectKeyPrefix **   <a name="timestream-Type-S3Configuration-ObjectKeyPrefix"></a>
The object key preview for the customer S3 location.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 928.  
Pattern: `[a-zA-Z0-9|!\-_*'\(\)]([a-zA-Z0-9]|[!\-_*'\(\)\/.])+`   
Required: No

## See Also
<a name="API_S3Configuration_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/S3Configuration) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/S3Configuration) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/S3Configuration) 

# Schema
<a name="API_Schema"></a>

 A Schema specifies the expected data model of the table. 

## Contents
<a name="API_Schema_Contents"></a>

 ** CompositePartitionKey **   <a name="timestream-Type-Schema-CompositePartitionKey"></a>
A non-empty list of partition keys defining the attributes used to partition the table data. The order of the list determines the partition hierarchy. The name and type of each partition key as well as the partition key order cannot be changed after the table is created. However, the enforcement level of each partition key can be changed.   
Type: Array of [PartitionKey](API_PartitionKey.md) objects  
Array Members: Minimum number of 1 item.  
Required: No

## See Also
<a name="API_Schema_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/Schema) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/Schema) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/Schema) 

# Table
<a name="API_Table"></a>

Represents a database table in Timestream. Tables contain one or more related time series. You can modify the retention duration of the memory store and the magnetic store for a table. 

## Contents
<a name="API_Table_Contents"></a>

 ** Arn **   <a name="timestream-Type-Table-Arn"></a>
The Amazon Resource Name that uniquely identifies this table.  
Type: String  
Required: No

 ** CreationTime **   <a name="timestream-Type-Table-CreationTime"></a>
The time when the Timestream table was created.   
Type: Timestamp  
Required: No

 ** DatabaseName **   <a name="timestream-Type-Table-DatabaseName"></a>
The name of the Timestream database that contains this table.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 256.  
Required: No

 ** LastUpdatedTime **   <a name="timestream-Type-Table-LastUpdatedTime"></a>
The time when the Timestream table was last updated.  
Type: Timestamp  
Required: No

 ** MagneticStoreWriteProperties **   <a name="timestream-Type-Table-MagneticStoreWriteProperties"></a>
Contains properties to set on the table when enabling magnetic store writes.  
Type: [MagneticStoreWriteProperties](API_MagneticStoreWriteProperties.md) object  
Required: No

 ** RetentionProperties **   <a name="timestream-Type-Table-RetentionProperties"></a>
The retention duration for the memory store and magnetic store.  
Type: [RetentionProperties](API_RetentionProperties.md) object  
Required: No

 ** Schema **   <a name="timestream-Type-Table-Schema"></a>
 The schema of the table.   
Type: [Schema](API_Schema.md) object  
Required: No

 ** TableName **   <a name="timestream-Type-Table-TableName"></a>
The name of the Timestream table.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 256.  
Required: No

 ** TableStatus **   <a name="timestream-Type-Table-TableStatus"></a>
The current state of the table:  
+  `DELETING` - The table is being deleted.
+  `ACTIVE` - The table is ready for use.
Type: String  
Valid Values: `ACTIVE | DELETING | RESTORING`   
Required: No

## See Also
<a name="API_Table_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/Table) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/Table) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/Table) 

# Tag
<a name="API_Tag"></a>

 A tag is a label that you assign to a Timestream database and/or table. Each tag consists of a key and an optional value, both of which you define. With tags, you can categorize databases and/or tables, for example, by purpose, owner, or environment. 

## Contents
<a name="API_Tag_Contents"></a>

 ** Key **   <a name="timestream-Type-Tag-Key"></a>
 The key of the tag. Tag keys are case sensitive.   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 128.  
Required: Yes

 ** Value **   <a name="timestream-Type-Tag-Value"></a>
 The value of the tag. Tag values are case-sensitive and can be null.   
Type: String  
Length Constraints: Minimum length of 0. Maximum length of 256.  
Required: Yes

## See Also
<a name="API_Tag_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-write-2018-11-01/Tag) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-write-2018-11-01/Tag) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-write-2018-11-01/Tag) 

# Amazon Timestream Query
<a name="API_Types_Amazon_Timestream_Query"></a>

The following data types are supported by Amazon Timestream Query:
+  [AccountSettingsNotificationConfiguration](API_query_AccountSettingsNotificationConfiguration.md) 
+  [ColumnInfo](API_query_ColumnInfo.md) 
+  [Datum](API_query_Datum.md) 
+  [DimensionMapping](API_query_DimensionMapping.md) 
+  [Endpoint](API_query_Endpoint.md) 
+  [ErrorReportConfiguration](API_query_ErrorReportConfiguration.md) 
+  [ErrorReportLocation](API_query_ErrorReportLocation.md) 
+  [ExecutionStats](API_query_ExecutionStats.md) 
+  [LastUpdate](API_query_LastUpdate.md) 
+  [MixedMeasureMapping](API_query_MixedMeasureMapping.md) 
+  [MultiMeasureAttributeMapping](API_query_MultiMeasureAttributeMapping.md) 
+  [MultiMeasureMappings](API_query_MultiMeasureMappings.md) 
+  [NotificationConfiguration](API_query_NotificationConfiguration.md) 
+  [ParameterMapping](API_query_ParameterMapping.md) 
+  [ProvisionedCapacityRequest](API_query_ProvisionedCapacityRequest.md) 
+  [ProvisionedCapacityResponse](API_query_ProvisionedCapacityResponse.md) 
+  [QueryComputeRequest](API_query_QueryComputeRequest.md) 
+  [QueryComputeResponse](API_query_QueryComputeResponse.md) 
+  [QueryInsights](API_query_QueryInsights.md) 
+  [QueryInsightsResponse](API_query_QueryInsightsResponse.md) 
+  [QuerySpatialCoverage](API_query_QuerySpatialCoverage.md) 
+  [QuerySpatialCoverageMax](API_query_QuerySpatialCoverageMax.md) 
+  [QueryStatus](API_query_QueryStatus.md) 
+  [QueryTemporalRange](API_query_QueryTemporalRange.md) 
+  [QueryTemporalRangeMax](API_query_QueryTemporalRangeMax.md) 
+  [Row](API_query_Row.md) 
+  [S3Configuration](API_query_S3Configuration.md) 
+  [S3ReportLocation](API_query_S3ReportLocation.md) 
+  [ScheduleConfiguration](API_query_ScheduleConfiguration.md) 
+  [ScheduledQuery](API_query_ScheduledQuery.md) 
+  [ScheduledQueryDescription](API_query_ScheduledQueryDescription.md) 
+  [ScheduledQueryInsights](API_query_ScheduledQueryInsights.md) 
+  [ScheduledQueryInsightsResponse](API_query_ScheduledQueryInsightsResponse.md) 
+  [ScheduledQueryRunSummary](API_query_ScheduledQueryRunSummary.md) 
+  [SelectColumn](API_query_SelectColumn.md) 
+  [SnsConfiguration](API_query_SnsConfiguration.md) 
+  [Tag](API_query_Tag.md) 
+  [TargetConfiguration](API_query_TargetConfiguration.md) 
+  [TargetDestination](API_query_TargetDestination.md) 
+  [TimeSeriesDataPoint](API_query_TimeSeriesDataPoint.md) 
+  [TimestreamConfiguration](API_query_TimestreamConfiguration.md) 
+  [TimestreamDestination](API_query_TimestreamDestination.md) 
+  [Type](API_query_Type.md) 

# AccountSettingsNotificationConfiguration
<a name="API_query_AccountSettingsNotificationConfiguration"></a>

Configuration settings for notifications related to account settings.

## Contents
<a name="API_query_AccountSettingsNotificationConfiguration_Contents"></a>

 ** RoleArn **   <a name="timestream-Type-query_AccountSettingsNotificationConfiguration-RoleArn"></a>
An Amazon Resource Name (ARN) that grants Timestream permission to publish notifications. This field is only visible if SNS Topic is provided when updating the account settings.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: Yes

 ** SnsConfiguration **   <a name="timestream-Type-query_AccountSettingsNotificationConfiguration-SnsConfiguration"></a>
Details on SNS that are required to send the notification.  
Type: [SnsConfiguration](API_query_SnsConfiguration.md) object  
Required: No

## See Also
<a name="API_query_AccountSettingsNotificationConfiguration_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/AccountSettingsNotificationConfiguration) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/AccountSettingsNotificationConfiguration) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/AccountSettingsNotificationConfiguration) 

# ColumnInfo
<a name="API_query_ColumnInfo"></a>

 Contains the metadata for query results such as the column names, data types, and other attributes. 

## Contents
<a name="API_query_ColumnInfo_Contents"></a>

 ** Type **   <a name="timestream-Type-query_ColumnInfo-Type"></a>
The data type of the result set column. The data type can be a scalar or complex. Scalar data types are integers, strings, doubles, Booleans, and others. Complex data types are types such as arrays, rows, and others.   
Type: [Type](API_query_Type.md) object  
Required: Yes

 ** Name **   <a name="timestream-Type-query_ColumnInfo-Name"></a>
 The name of the result set column. The name of the result set is available for columns of all data types except for arrays.   
Type: String  
Required: No

## See Also
<a name="API_query_ColumnInfo_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/ColumnInfo) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/ColumnInfo) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/ColumnInfo) 

# Datum
<a name="API_query_Datum"></a>

 Datum represents a single data point in a query result. 

## Contents
<a name="API_query_Datum_Contents"></a>

 ** ArrayValue **   <a name="timestream-Type-query_Datum-ArrayValue"></a>
 Indicates if the data point is an array.   
Type: Array of [Datum](#API_query_Datum) objects  
Required: No

 ** NullValue **   <a name="timestream-Type-query_Datum-NullValue"></a>
 Indicates if the data point is null.   
Type: Boolean  
Required: No

 ** RowValue **   <a name="timestream-Type-query_Datum-RowValue"></a>
 Indicates if the data point is a row.   
Type: [Row](API_query_Row.md) object  
Required: No

 ** ScalarValue **   <a name="timestream-Type-query_Datum-ScalarValue"></a>
 Indicates if the data point is a scalar value such as integer, string, double, or Boolean.   
Type: String  
Required: No

 ** TimeSeriesValue **   <a name="timestream-Type-query_Datum-TimeSeriesValue"></a>
 Indicates if the data point is a timeseries data type.   
Type: Array of [TimeSeriesDataPoint](API_query_TimeSeriesDataPoint.md) objects  
Required: No

## See Also
<a name="API_query_Datum_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/Datum) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/Datum) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/Datum) 

# DimensionMapping
<a name="API_query_DimensionMapping"></a>

This type is used to map column(s) from the query result to a dimension in the destination table.

## Contents
<a name="API_query_DimensionMapping_Contents"></a>

 ** DimensionValueType **   <a name="timestream-Type-query_DimensionMapping-DimensionValueType"></a>
Type for the dimension.   
Type: String  
Valid Values: `VARCHAR`   
Required: Yes

 ** Name **   <a name="timestream-Type-query_DimensionMapping-Name"></a>
Column name from query result.  
Type: String  
Required: Yes

## See Also
<a name="API_query_DimensionMapping_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/DimensionMapping) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/DimensionMapping) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/DimensionMapping) 

# Endpoint
<a name="API_query_Endpoint"></a>

Represents an available endpoint against which to make API calls against, as well as the TTL for that endpoint.

## Contents
<a name="API_query_Endpoint_Contents"></a>

 ** Address **   <a name="timestream-Type-query_Endpoint-Address"></a>
An endpoint address.  
Type: String  
Required: Yes

 ** CachePeriodInMinutes **   <a name="timestream-Type-query_Endpoint-CachePeriodInMinutes"></a>
The TTL for the endpoint, in minutes.  
Type: Long  
Required: Yes

## See Also
<a name="API_query_Endpoint_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/Endpoint) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/Endpoint) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/Endpoint) 

# ErrorReportConfiguration
<a name="API_query_ErrorReportConfiguration"></a>

Configuration required for error reporting.

## Contents
<a name="API_query_ErrorReportConfiguration_Contents"></a>

 ** S3Configuration **   <a name="timestream-Type-query_ErrorReportConfiguration-S3Configuration"></a>
The S3 configuration for the error reports.  
Type: [S3Configuration](API_query_S3Configuration.md) object  
Required: Yes

## See Also
<a name="API_query_ErrorReportConfiguration_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/ErrorReportConfiguration) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/ErrorReportConfiguration) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/ErrorReportConfiguration) 

# ErrorReportLocation
<a name="API_query_ErrorReportLocation"></a>

This contains the location of the error report for a single scheduled query call. 

## Contents
<a name="API_query_ErrorReportLocation_Contents"></a>

 ** S3ReportLocation **   <a name="timestream-Type-query_ErrorReportLocation-S3ReportLocation"></a>
The S3 location where error reports are written.  
Type: [S3ReportLocation](API_query_S3ReportLocation.md) object  
Required: No

## See Also
<a name="API_query_ErrorReportLocation_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/ErrorReportLocation) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/ErrorReportLocation) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/ErrorReportLocation) 

# ExecutionStats
<a name="API_query_ExecutionStats"></a>

Statistics for a single scheduled query run.

## Contents
<a name="API_query_ExecutionStats_Contents"></a>

 ** BytesMetered **   <a name="timestream-Type-query_ExecutionStats-BytesMetered"></a>
Bytes metered for a single scheduled query run.  
Type: Long  
Required: No

 ** CumulativeBytesScanned **   <a name="timestream-Type-query_ExecutionStats-CumulativeBytesScanned"></a>
Bytes scanned for a single scheduled query run.  
Type: Long  
Required: No

 ** DataWrites **   <a name="timestream-Type-query_ExecutionStats-DataWrites"></a>
Data writes metered for records ingested in a single scheduled query run.  
Type: Long  
Required: No

 ** ExecutionTimeInMillis **   <a name="timestream-Type-query_ExecutionStats-ExecutionTimeInMillis"></a>
Total time, measured in milliseconds, that was needed for the scheduled query run to complete.  
Type: Long  
Required: No

 ** QueryResultRows **   <a name="timestream-Type-query_ExecutionStats-QueryResultRows"></a>
Number of rows present in the output from running a query before ingestion to destination data source.  
Type: Long  
Required: No

 ** RecordsIngested **   <a name="timestream-Type-query_ExecutionStats-RecordsIngested"></a>
The number of records ingested for a single scheduled query run.   
Type: Long  
Required: No

## See Also
<a name="API_query_ExecutionStats_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/ExecutionStats) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/ExecutionStats) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/ExecutionStats) 

# LastUpdate
<a name="API_query_LastUpdate"></a>

Configuration object that contains the most recent account settings update, visible only if settings have been updated previously.

## Contents
<a name="API_query_LastUpdate_Contents"></a>

 ** Status **   <a name="timestream-Type-query_LastUpdate-Status"></a>
The status of the last update. Can be either `PENDING`, `FAILED`, or `SUCCEEDED`.  
Type: String  
Valid Values: `PENDING | FAILED | SUCCEEDED`   
Required: No

 ** StatusMessage **   <a name="timestream-Type-query_LastUpdate-StatusMessage"></a>
Error message describing the last account settings update status, visible only if an error occurred.  
Type: String  
Required: No

 ** TargetQueryTCU **   <a name="timestream-Type-query_LastUpdate-TargetQueryTCU"></a>
The number of TimeStream Compute Units (TCUs) requested in the last account settings update.  
Type: Integer  
Required: No

## See Also
<a name="API_query_LastUpdate_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/LastUpdate) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/LastUpdate) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/LastUpdate) 

# MixedMeasureMapping
<a name="API_query_MixedMeasureMapping"></a>

MixedMeasureMappings are mappings that can be used to ingest data into a mixture of narrow and multi measures in the derived table.

## Contents
<a name="API_query_MixedMeasureMapping_Contents"></a>

 ** MeasureValueType **   <a name="timestream-Type-query_MixedMeasureMapping-MeasureValueType"></a>
Type of the value that is to be read from sourceColumn. If the mapping is for MULTI, use MeasureValueType.MULTI.  
Type: String  
Valid Values: `BIGINT | BOOLEAN | DOUBLE | VARCHAR | MULTI`   
Required: Yes

 ** MeasureName **   <a name="timestream-Type-query_MixedMeasureMapping-MeasureName"></a>
Refers to the value of measure\$1name in a result row. This field is required if MeasureNameColumn is provided.  
Type: String  
Required: No

 ** MultiMeasureAttributeMappings **   <a name="timestream-Type-query_MixedMeasureMapping-MultiMeasureAttributeMappings"></a>
Required when measureValueType is MULTI. Attribute mappings for MULTI value measures.  
Type: Array of [MultiMeasureAttributeMapping](API_query_MultiMeasureAttributeMapping.md) objects  
Array Members: Minimum number of 1 item.  
Required: No

 ** SourceColumn **   <a name="timestream-Type-query_MixedMeasureMapping-SourceColumn"></a>
This field refers to the source column from which measure-value is to be read for result materialization.  
Type: String  
Required: No

 ** TargetMeasureName **   <a name="timestream-Type-query_MixedMeasureMapping-TargetMeasureName"></a>
Target measure name to be used. If not provided, the target measure name by default would be measure-name if provided, or sourceColumn otherwise.   
Type: String  
Required: No

## See Also
<a name="API_query_MixedMeasureMapping_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/MixedMeasureMapping) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/MixedMeasureMapping) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/MixedMeasureMapping) 

# MultiMeasureAttributeMapping
<a name="API_query_MultiMeasureAttributeMapping"></a>

Attribute mapping for MULTI value measures.

## Contents
<a name="API_query_MultiMeasureAttributeMapping_Contents"></a>

 ** MeasureValueType **   <a name="timestream-Type-query_MultiMeasureAttributeMapping-MeasureValueType"></a>
Type of the attribute to be read from the source column.  
Type: String  
Valid Values: `BIGINT | BOOLEAN | DOUBLE | VARCHAR | TIMESTAMP`   
Required: Yes

 ** SourceColumn **   <a name="timestream-Type-query_MultiMeasureAttributeMapping-SourceColumn"></a>
Source column from where the attribute value is to be read.  
Type: String  
Required: Yes

 ** TargetMultiMeasureAttributeName **   <a name="timestream-Type-query_MultiMeasureAttributeMapping-TargetMultiMeasureAttributeName"></a>
Custom name to be used for attribute name in derived table. If not provided, source column name would be used.  
Type: String  
Required: No

## See Also
<a name="API_query_MultiMeasureAttributeMapping_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/MultiMeasureAttributeMapping) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/MultiMeasureAttributeMapping) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/MultiMeasureAttributeMapping) 

# MultiMeasureMappings
<a name="API_query_MultiMeasureMappings"></a>

Only one of MixedMeasureMappings or MultiMeasureMappings is to be provided. MultiMeasureMappings can be used to ingest data as multi measures in the derived table.

## Contents
<a name="API_query_MultiMeasureMappings_Contents"></a>

 ** MultiMeasureAttributeMappings **   <a name="timestream-Type-query_MultiMeasureMappings-MultiMeasureAttributeMappings"></a>
Required. Attribute mappings to be used for mapping query results to ingest data for multi-measure attributes.  
Type: Array of [MultiMeasureAttributeMapping](API_query_MultiMeasureAttributeMapping.md) objects  
Array Members: Minimum number of 1 item.  
Required: Yes

 ** TargetMultiMeasureName **   <a name="timestream-Type-query_MultiMeasureMappings-TargetMultiMeasureName"></a>
The name of the target multi-measure name in the derived table. This input is required when measureNameColumn is not provided. If MeasureNameColumn is provided, then value from that column will be used as multi-measure name.  
Type: String  
Required: No

## See Also
<a name="API_query_MultiMeasureMappings_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/MultiMeasureMappings) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/MultiMeasureMappings) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/MultiMeasureMappings) 

# NotificationConfiguration
<a name="API_query_NotificationConfiguration"></a>

Notification configuration for a scheduled query. A notification is sent by Timestream when a scheduled query is created, its state is updated or when it is deleted. 

## Contents
<a name="API_query_NotificationConfiguration_Contents"></a>

 ** SnsConfiguration **   <a name="timestream-Type-query_NotificationConfiguration-SnsConfiguration"></a>
Details about the Amazon Simple Notification Service (SNS) configuration. This field is visible only when SNS Topic is provided when updating the account settings.   
Type: [SnsConfiguration](API_query_SnsConfiguration.md) object  
Required: Yes

## See Also
<a name="API_query_NotificationConfiguration_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/NotificationConfiguration) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/NotificationConfiguration) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/NotificationConfiguration) 

# ParameterMapping
<a name="API_query_ParameterMapping"></a>

Mapping for named parameters.

## Contents
<a name="API_query_ParameterMapping_Contents"></a>

 ** Name **   <a name="timestream-Type-query_ParameterMapping-Name"></a>
Parameter name.  
Type: String  
Required: Yes

 ** Type **   <a name="timestream-Type-query_ParameterMapping-Type"></a>
Contains the data type of a column in a query result set. The data type can be scalar or complex. The supported scalar data types are integers, Boolean, string, double, timestamp, date, time, and intervals. The supported complex data types are arrays, rows, and timeseries.  
Type: [Type](API_query_Type.md) object  
Required: Yes

## See Also
<a name="API_query_ParameterMapping_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/ParameterMapping) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/ParameterMapping) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/ParameterMapping) 

# ProvisionedCapacityRequest
<a name="API_query_ProvisionedCapacityRequest"></a>

A request to update the provisioned capacity settings for querying data.

## Contents
<a name="API_query_ProvisionedCapacityRequest_Contents"></a>

 ** TargetQueryTCU **   <a name="timestream-Type-query_ProvisionedCapacityRequest-TargetQueryTCU"></a>
The target compute capacity for querying data, specified in Timestream Compute Units (TCUs).  
Type: Integer  
Required: Yes

 ** NotificationConfiguration **   <a name="timestream-Type-query_ProvisionedCapacityRequest-NotificationConfiguration"></a>
Configuration settings for notifications related to the provisioned capacity update.  
Type: [AccountSettingsNotificationConfiguration](API_query_AccountSettingsNotificationConfiguration.md) object  
Required: No

## See Also
<a name="API_query_ProvisionedCapacityRequest_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/ProvisionedCapacityRequest) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/ProvisionedCapacityRequest) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/ProvisionedCapacityRequest) 

# ProvisionedCapacityResponse
<a name="API_query_ProvisionedCapacityResponse"></a>

The response to a request to update the provisioned capacity settings for querying data.

## Contents
<a name="API_query_ProvisionedCapacityResponse_Contents"></a>

 ** ActiveQueryTCU **   <a name="timestream-Type-query_ProvisionedCapacityResponse-ActiveQueryTCU"></a>
The number of Timestream Compute Units (TCUs) provisioned in the account. This field is only visible when the compute mode is `PROVISIONED`.  
Type: Integer  
Required: No

 ** LastUpdate **   <a name="timestream-Type-query_ProvisionedCapacityResponse-LastUpdate"></a>
Information about the last update to the provisioned capacity settings.  
Type: [LastUpdate](API_query_LastUpdate.md) object  
Required: No

 ** NotificationConfiguration **   <a name="timestream-Type-query_ProvisionedCapacityResponse-NotificationConfiguration"></a>
An object that contains settings for notifications that are sent whenever the provisioned capacity settings are modified. This field is only visible when the compute mode is `PROVISIONED`.  
Type: [AccountSettingsNotificationConfiguration](API_query_AccountSettingsNotificationConfiguration.md) object  
Required: No

## See Also
<a name="API_query_ProvisionedCapacityResponse_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/ProvisionedCapacityResponse) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/ProvisionedCapacityResponse) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/ProvisionedCapacityResponse) 

# QueryComputeRequest
<a name="API_query_QueryComputeRequest"></a>

A request to retrieve or update the compute capacity settings for querying data. QueryCompute is available only in the Asia Pacific (Mumbai) region.

## Contents
<a name="API_query_QueryComputeRequest_Contents"></a>

 ** ComputeMode **   <a name="timestream-Type-query_QueryComputeRequest-ComputeMode"></a>
The mode in which Timestream Compute Units (TCUs) are allocated and utilized within an account. Note that in the Asia Pacific (Mumbai) region, the API operation only recognizes the value `PROVISIONED`. QueryCompute is available only in the Asia Pacific (Mumbai) region.  
Type: String  
Valid Values: `ON_DEMAND | PROVISIONED`   
Required: No

 ** ProvisionedCapacity **   <a name="timestream-Type-query_QueryComputeRequest-ProvisionedCapacity"></a>
Configuration object that contains settings for provisioned Timestream Compute Units (TCUs) in your account. QueryCompute is available only in the Asia Pacific (Mumbai) region.  
Type: [ProvisionedCapacityRequest](API_query_ProvisionedCapacityRequest.md) object  
Required: No

## See Also
<a name="API_query_QueryComputeRequest_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/QueryComputeRequest) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/QueryComputeRequest) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/QueryComputeRequest) 

# QueryComputeResponse
<a name="API_query_QueryComputeResponse"></a>

The response to a request to retrieve or update the compute capacity settings for querying data. QueryCompute is available only in the Asia Pacific (Mumbai) region.

## Contents
<a name="API_query_QueryComputeResponse_Contents"></a>

 ** ComputeMode **   <a name="timestream-Type-query_QueryComputeResponse-ComputeMode"></a>
The mode in which Timestream Compute Units (TCUs) are allocated and utilized within an account. Note that in the Asia Pacific (Mumbai) region, the API operation only recognizes the value `PROVISIONED`. QueryCompute is available only in the Asia Pacific (Mumbai) region.  
Type: String  
Valid Values: `ON_DEMAND | PROVISIONED`   
Required: No

 ** ProvisionedCapacity **   <a name="timestream-Type-query_QueryComputeResponse-ProvisionedCapacity"></a>
Configuration object that contains settings for provisioned Timestream Compute Units (TCUs) in your account. QueryCompute is available only in the Asia Pacific (Mumbai) region.  
Type: [ProvisionedCapacityResponse](API_query_ProvisionedCapacityResponse.md) object  
Required: No

## See Also
<a name="API_query_QueryComputeResponse_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/QueryComputeResponse) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/QueryComputeResponse) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/QueryComputeResponse) 

# QueryInsights
<a name="API_query_QueryInsights"></a>

 `QueryInsights` is a performance tuning feature that helps you optimize your queries, reducing costs and improving performance. With `QueryInsights`, you can assess the pruning efficiency of your queries and identify areas for improvement to enhance query performance. With `QueryInsights`, you can also analyze the effectiveness of your queries in terms of temporal and spatial pruning, and identify opportunities to improve performance. Specifically, you can evaluate how well your queries use time-based and partition key-based indexing strategies to optimize data retrieval. To optimize query performance, it's essential that you fine-tune both the temporal and spatial parameters that govern query execution.

The key metrics provided by `QueryInsights` are `QuerySpatialCoverage` and `QueryTemporalRange`. `QuerySpatialCoverage` indicates how much of the spatial axis the query scans, with lower values being more efficient. `QueryTemporalRange` shows the time range scanned, with narrower ranges being more performant.

 **Benefits of QueryInsights** 

The following are the key benefits of using `QueryInsights`:
+  **Identifying inefficient queries** – `QueryInsights` provides information on the time-based and attribute-based pruning of the tables accessed by the query. This information helps you identify the tables that are sub-optimally accessed.
+  **Optimizing your data model and partitioning** – You can use the `QueryInsights` information to access and fine-tune your data model and partitioning strategy.
+  **Tuning queries** – `QueryInsights` highlights opportunities to use indexes more effectively.

**Note**  
The maximum number of `Query` API requests you're allowed to make with `QueryInsights` enabled is 1 query per second (QPS). If you exceed this query rate, it might result in throttling.

## Contents
<a name="API_query_QueryInsights_Contents"></a>

 ** Mode **   <a name="timestream-Type-query_QueryInsights-Mode"></a>
Provides the following modes to enable `QueryInsights`:  
+  `ENABLED_WITH_RATE_CONTROL` – Enables `QueryInsights` for the queries being processed. This mode also includes a rate control mechanism, which limits the `QueryInsights` feature to 1 query per second (QPS).
+  `DISABLED` – Disables `QueryInsights`.
Type: String  
Valid Values: `ENABLED_WITH_RATE_CONTROL | DISABLED`   
Required: Yes

## See Also
<a name="API_query_QueryInsights_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/QueryInsights) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/QueryInsights) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/QueryInsights) 

# QueryInsightsResponse
<a name="API_query_QueryInsightsResponse"></a>

Provides various insights and metrics related to the query that you executed.

## Contents
<a name="API_query_QueryInsightsResponse_Contents"></a>

 ** OutputBytes **   <a name="timestream-Type-query_QueryInsightsResponse-OutputBytes"></a>
Indicates the size of query result set in bytes. You can use this data to validate if the result set has changed as part of the query tuning exercise.  
Type: Long  
Required: No

 ** OutputRows **   <a name="timestream-Type-query_QueryInsightsResponse-OutputRows"></a>
Indicates the total number of rows returned as part of the query result set. You can use this data to validate if the number of rows in the result set have changed as part of the query tuning exercise.  
Type: Long  
Required: No

 ** QuerySpatialCoverage **   <a name="timestream-Type-query_QueryInsightsResponse-QuerySpatialCoverage"></a>
Provides insights into the spatial coverage of the query, including the table with sub-optimal (max) spatial pruning. This information can help you identify areas for improvement in your partitioning strategy to enhance spatial pruning.   
Type: [QuerySpatialCoverage](API_query_QuerySpatialCoverage.md) object  
Required: No

 ** QueryTableCount **   <a name="timestream-Type-query_QueryInsightsResponse-QueryTableCount"></a>
Indicates the number of tables in the query.  
Type: Long  
Required: No

 ** QueryTemporalRange **   <a name="timestream-Type-query_QueryInsightsResponse-QueryTemporalRange"></a>
Provides insights into the temporal range of the query, including the table with the largest (max) time range. Following are some of the potential options for optimizing time-based pruning:  
+ Add missing time-predicates.
+ Remove functions around the time predicates.
+ Add time predicates to all the sub-queries.
Type: [QueryTemporalRange](API_query_QueryTemporalRange.md) object  
Required: No

 ** UnloadPartitionCount **   <a name="timestream-Type-query_QueryInsightsResponse-UnloadPartitionCount"></a>
Indicates the partitions created by the `Unload` operation.  
Type: Long  
Required: No

 ** UnloadWrittenBytes **   <a name="timestream-Type-query_QueryInsightsResponse-UnloadWrittenBytes"></a>
Indicates the size, in bytes, written by the `Unload` operation.  
Type: Long  
Required: No

 ** UnloadWrittenRows **   <a name="timestream-Type-query_QueryInsightsResponse-UnloadWrittenRows"></a>
Indicates the rows written by the `Unload` query.  
Type: Long  
Required: No

## See Also
<a name="API_query_QueryInsightsResponse_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/QueryInsightsResponse) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/QueryInsightsResponse) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/QueryInsightsResponse) 

# QuerySpatialCoverage
<a name="API_query_QuerySpatialCoverage"></a>

Provides insights into the spatial coverage of the query, including the table with sub-optimal (max) spatial pruning. This information can help you identify areas for improvement in your partitioning strategy to enhance spatial pruning

For example, you can do the following with the `QuerySpatialCoverage` information:
+ Add measure\$1name or use [customer-defined partition key](https://docs.aws.amazon.com/timestream/latest/developerguide/customer-defined-partition-keys.html) (CDPK) predicates.
+ If you've already done the preceding action, remove functions around them or clauses, such as `LIKE`.

## Contents
<a name="API_query_QuerySpatialCoverage_Contents"></a>

 ** Max **   <a name="timestream-Type-query_QuerySpatialCoverage-Max"></a>
Provides insights into the spatial coverage of the executed query and the table with the most inefficient spatial pruning.  
+  `Value` – The maximum ratio of spatial coverage.
+  `TableArn` – The Amazon Resource Name (ARN) of the table with sub-optimal spatial pruning.
+  `PartitionKey` – The partition key used for partitioning, which can be a default `measure_name` or a CDPK.
Type: [QuerySpatialCoverageMax](API_query_QuerySpatialCoverageMax.md) object  
Required: No

## See Also
<a name="API_query_QuerySpatialCoverage_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/QuerySpatialCoverage) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/QuerySpatialCoverage) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/QuerySpatialCoverage) 

# QuerySpatialCoverageMax
<a name="API_query_QuerySpatialCoverageMax"></a>

Provides insights into the table with the most sub-optimal spatial range scanned by your query.

## Contents
<a name="API_query_QuerySpatialCoverageMax_Contents"></a>

 ** PartitionKey **   <a name="timestream-Type-query_QuerySpatialCoverageMax-PartitionKey"></a>
The partition key used for partitioning, which can be a default `measure_name` or a [customer defined partition key](https://docs.aws.amazon.com/timestream/latest/developerguide/customer-defined-partition-keys.html).  
Type: Array of strings  
Required: No

 ** TableArn **   <a name="timestream-Type-query_QuerySpatialCoverageMax-TableArn"></a>
The Amazon Resource Name (ARN) of the table with the most sub-optimal spatial pruning.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: No

 ** Value **   <a name="timestream-Type-query_QuerySpatialCoverageMax-Value"></a>
The maximum ratio of spatial coverage.  
Type: Double  
Required: No

## See Also
<a name="API_query_QuerySpatialCoverageMax_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/QuerySpatialCoverageMax) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/QuerySpatialCoverageMax) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/QuerySpatialCoverageMax) 

# QueryStatus
<a name="API_query_QueryStatus"></a>

Information about the status of the query, including progress and bytes scanned.

## Contents
<a name="API_query_QueryStatus_Contents"></a>

 ** CumulativeBytesMetered **   <a name="timestream-Type-query_QueryStatus-CumulativeBytesMetered"></a>
The amount of data scanned by the query in bytes that you will be charged for. This is a cumulative sum and represents the total amount of data that you will be charged for since the query was started. The charge is applied only once and is either applied when the query completes running or when the query is cancelled.   
Type: Long  
Required: No

 ** CumulativeBytesScanned **   <a name="timestream-Type-query_QueryStatus-CumulativeBytesScanned"></a>
The amount of data scanned by the query in bytes. This is a cumulative sum and represents the total amount of bytes scanned since the query was started.   
Type: Long  
Required: No

 ** ProgressPercentage **   <a name="timestream-Type-query_QueryStatus-ProgressPercentage"></a>
The progress of the query, expressed as a percentage.  
Type: Double  
Required: No

## See Also
<a name="API_query_QueryStatus_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/QueryStatus) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/QueryStatus) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/QueryStatus) 

# QueryTemporalRange
<a name="API_query_QueryTemporalRange"></a>

Provides insights into the temporal range of the query, including the table with the largest (max) time range.

## Contents
<a name="API_query_QueryTemporalRange_Contents"></a>

 ** Max **   <a name="timestream-Type-query_QueryTemporalRange-Max"></a>
Encapsulates the following properties that provide insights into the most sub-optimal performing table on the temporal axis:  
+  `Value` – The maximum duration in nanoseconds between the start and end of the query.
+  `TableArn` – The Amazon Resource Name (ARN) of the table which is queried with the largest time range.
Type: [QueryTemporalRangeMax](API_query_QueryTemporalRangeMax.md) object  
Required: No

## See Also
<a name="API_query_QueryTemporalRange_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/QueryTemporalRange) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/QueryTemporalRange) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/QueryTemporalRange) 

# QueryTemporalRangeMax
<a name="API_query_QueryTemporalRangeMax"></a>

Provides insights into the table with the most sub-optimal temporal pruning scanned by your query.

## Contents
<a name="API_query_QueryTemporalRangeMax_Contents"></a>

 ** TableArn **   <a name="timestream-Type-query_QueryTemporalRangeMax-TableArn"></a>
The Amazon Resource Name (ARN) of the table which is queried with the largest time range.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: No

 ** Value **   <a name="timestream-Type-query_QueryTemporalRangeMax-Value"></a>
The maximum duration in nanoseconds between the start and end of the query.  
Type: Long  
Required: No

## See Also
<a name="API_query_QueryTemporalRangeMax_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/QueryTemporalRangeMax) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/QueryTemporalRangeMax) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/QueryTemporalRangeMax) 

# Row
<a name="API_query_Row"></a>

Represents a single row in the query results.

## Contents
<a name="API_query_Row_Contents"></a>

 ** Data **   <a name="timestream-Type-query_Row-Data"></a>
List of data points in a single row of the result set.  
Type: Array of [Datum](API_query_Datum.md) objects  
Required: Yes

## See Also
<a name="API_query_Row_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/Row) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/Row) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/Row) 

# S3Configuration
<a name="API_query_S3Configuration"></a>

Details on S3 location for error reports that result from running a query. 

## Contents
<a name="API_query_S3Configuration_Contents"></a>

 ** BucketName **   <a name="timestream-Type-query_S3Configuration-BucketName"></a>
 Name of the S3 bucket under which error reports will be created.  
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 63.  
Pattern: `[a-z0-9][\.\-a-z0-9]{1,61}[a-z0-9]`   
Required: Yes

 ** EncryptionOption **   <a name="timestream-Type-query_S3Configuration-EncryptionOption"></a>
 Encryption at rest options for the error reports. If no encryption option is specified, Timestream will choose SSE\$1S3 as default.   
Type: String  
Valid Values: `SSE_S3 | SSE_KMS`   
Required: No

 ** ObjectKeyPrefix **   <a name="timestream-Type-query_S3Configuration-ObjectKeyPrefix"></a>
 Prefix for the error report key. Timestream by default adds the following prefix to the error report path.   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 896.  
Pattern: `[a-zA-Z0-9|!\-_*'\(\)]([a-zA-Z0-9]|[!\-_*'\(\)\/.])+`   
Required: No

## See Also
<a name="API_query_S3Configuration_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/S3Configuration) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/S3Configuration) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/S3Configuration) 

# S3ReportLocation
<a name="API_query_S3ReportLocation"></a>

 S3 report location for the scheduled query run.

## Contents
<a name="API_query_S3ReportLocation_Contents"></a>

 ** BucketName **   <a name="timestream-Type-query_S3ReportLocation-BucketName"></a>
 S3 bucket name.   
Type: String  
Length Constraints: Minimum length of 3. Maximum length of 63.  
Pattern: `[a-z0-9][\.\-a-z0-9]{1,61}[a-z0-9]`   
Required: No

 ** ObjectKey **   <a name="timestream-Type-query_S3ReportLocation-ObjectKey"></a>
S3 key.   
Type: String  
Required: No

## See Also
<a name="API_query_S3ReportLocation_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/S3ReportLocation) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/S3ReportLocation) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/S3ReportLocation) 

# ScheduleConfiguration
<a name="API_query_ScheduleConfiguration"></a>

Configuration of the schedule of the query.

## Contents
<a name="API_query_ScheduleConfiguration_Contents"></a>

 ** ScheduleExpression **   <a name="timestream-Type-query_ScheduleConfiguration-ScheduleExpression"></a>
An expression that denotes when to trigger the scheduled query run. This can be a cron expression or a rate expression.   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 256.  
Required: Yes

## See Also
<a name="API_query_ScheduleConfiguration_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/ScheduleConfiguration) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/ScheduleConfiguration) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/ScheduleConfiguration) 

# ScheduledQuery
<a name="API_query_ScheduledQuery"></a>

Scheduled Query

## Contents
<a name="API_query_ScheduledQuery_Contents"></a>

 ** Arn **   <a name="timestream-Type-query_ScheduledQuery-Arn"></a>
The Amazon Resource Name.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: Yes

 ** Name **   <a name="timestream-Type-query_ScheduledQuery-Name"></a>
The name of the scheduled query.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 64.  
Pattern: `[a-zA-Z0-9|!\-_*'\(\)]([a-zA-Z0-9]|[!\-_*'\(\)\/.])+`   
Required: Yes

 ** State **   <a name="timestream-Type-query_ScheduledQuery-State"></a>
State of scheduled query.   
Type: String  
Valid Values: `ENABLED | DISABLED`   
Required: Yes

 ** CreationTime **   <a name="timestream-Type-query_ScheduledQuery-CreationTime"></a>
The creation time of the scheduled query.  
Type: Timestamp  
Required: No

 ** ErrorReportConfiguration **   <a name="timestream-Type-query_ScheduledQuery-ErrorReportConfiguration"></a>
Configuration for scheduled query error reporting.  
Type: [ErrorReportConfiguration](API_query_ErrorReportConfiguration.md) object  
Required: No

 ** LastRunStatus **   <a name="timestream-Type-query_ScheduledQuery-LastRunStatus"></a>
Status of the last scheduled query run.  
Type: String  
Valid Values: `AUTO_TRIGGER_SUCCESS | AUTO_TRIGGER_FAILURE | MANUAL_TRIGGER_SUCCESS | MANUAL_TRIGGER_FAILURE`   
Required: No

 ** NextInvocationTime **   <a name="timestream-Type-query_ScheduledQuery-NextInvocationTime"></a>
The next time the scheduled query is to be run.  
Type: Timestamp  
Required: No

 ** PreviousInvocationTime **   <a name="timestream-Type-query_ScheduledQuery-PreviousInvocationTime"></a>
The last time the scheduled query was run.  
Type: Timestamp  
Required: No

 ** TargetDestination **   <a name="timestream-Type-query_ScheduledQuery-TargetDestination"></a>
Target data source where final scheduled query result will be written.  
Type: [TargetDestination](API_query_TargetDestination.md) object  
Required: No

## See Also
<a name="API_query_ScheduledQuery_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/ScheduledQuery) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/ScheduledQuery) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/ScheduledQuery) 

# ScheduledQueryDescription
<a name="API_query_ScheduledQueryDescription"></a>

Structure that describes scheduled query.

## Contents
<a name="API_query_ScheduledQueryDescription_Contents"></a>

 ** Arn **   <a name="timestream-Type-query_ScheduledQueryDescription-Arn"></a>
Scheduled query ARN.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: Yes

 ** Name **   <a name="timestream-Type-query_ScheduledQueryDescription-Name"></a>
Name of the scheduled query.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 64.  
Pattern: `[a-zA-Z0-9|!\-_*'\(\)]([a-zA-Z0-9]|[!\-_*'\(\)\/.])+`   
Required: Yes

 ** NotificationConfiguration **   <a name="timestream-Type-query_ScheduledQueryDescription-NotificationConfiguration"></a>
Notification configuration.  
Type: [NotificationConfiguration](API_query_NotificationConfiguration.md) object  
Required: Yes

 ** QueryString **   <a name="timestream-Type-query_ScheduledQueryDescription-QueryString"></a>
The query to be run.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 262144.  
Required: Yes

 ** ScheduleConfiguration **   <a name="timestream-Type-query_ScheduledQueryDescription-ScheduleConfiguration"></a>
Schedule configuration.  
Type: [ScheduleConfiguration](API_query_ScheduleConfiguration.md) object  
Required: Yes

 ** State **   <a name="timestream-Type-query_ScheduledQueryDescription-State"></a>
State of the scheduled query.   
Type: String  
Valid Values: `ENABLED | DISABLED`   
Required: Yes

 ** CreationTime **   <a name="timestream-Type-query_ScheduledQueryDescription-CreationTime"></a>
Creation time of the scheduled query.  
Type: Timestamp  
Required: No

 ** ErrorReportConfiguration **   <a name="timestream-Type-query_ScheduledQueryDescription-ErrorReportConfiguration"></a>
Error-reporting configuration for the scheduled query.  
Type: [ErrorReportConfiguration](API_query_ErrorReportConfiguration.md) object  
Required: No

 ** KmsKeyId **   <a name="timestream-Type-query_ScheduledQueryDescription-KmsKeyId"></a>
A customer provided KMS key used to encrypt the scheduled query resource.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: No

 ** LastRunSummary **   <a name="timestream-Type-query_ScheduledQueryDescription-LastRunSummary"></a>
Runtime summary for the last scheduled query run.   
Type: [ScheduledQueryRunSummary](API_query_ScheduledQueryRunSummary.md) object  
Required: No

 ** NextInvocationTime **   <a name="timestream-Type-query_ScheduledQueryDescription-NextInvocationTime"></a>
The next time the scheduled query is scheduled to run.  
Type: Timestamp  
Required: No

 ** PreviousInvocationTime **   <a name="timestream-Type-query_ScheduledQueryDescription-PreviousInvocationTime"></a>
Last time the query was run.  
Type: Timestamp  
Required: No

 ** RecentlyFailedRuns **   <a name="timestream-Type-query_ScheduledQueryDescription-RecentlyFailedRuns"></a>
Runtime summary for the last five failed scheduled query runs.  
Type: Array of [ScheduledQueryRunSummary](API_query_ScheduledQueryRunSummary.md) objects  
Required: No

 ** ScheduledQueryExecutionRoleArn **   <a name="timestream-Type-query_ScheduledQueryDescription-ScheduledQueryExecutionRoleArn"></a>
IAM role that Timestream uses to run the schedule query.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: No

 ** TargetConfiguration **   <a name="timestream-Type-query_ScheduledQueryDescription-TargetConfiguration"></a>
Scheduled query target store configuration.  
Type: [TargetConfiguration](API_query_TargetConfiguration.md) object  
Required: No

## See Also
<a name="API_query_ScheduledQueryDescription_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/ScheduledQueryDescription) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/ScheduledQueryDescription) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/ScheduledQueryDescription) 

# ScheduledQueryInsights
<a name="API_query_ScheduledQueryInsights"></a>

Encapsulates settings for enabling `QueryInsights` on an `ExecuteScheduledQueryRequest`.

## Contents
<a name="API_query_ScheduledQueryInsights_Contents"></a>

 ** Mode **   <a name="timestream-Type-query_ScheduledQueryInsights-Mode"></a>
Provides the following modes to enable `ScheduledQueryInsights`:  
+  `ENABLED_WITH_RATE_CONTROL` – Enables `ScheduledQueryInsights` for the queries being processed. This mode also includes a rate control mechanism, which limits the `QueryInsights` feature to 1 query per second (QPS).
+  `DISABLED` – Disables `ScheduledQueryInsights`.
Type: String  
Valid Values: `ENABLED_WITH_RATE_CONTROL | DISABLED`   
Required: Yes

## See Also
<a name="API_query_ScheduledQueryInsights_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/ScheduledQueryInsights) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/ScheduledQueryInsights) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/ScheduledQueryInsights) 

# ScheduledQueryInsightsResponse
<a name="API_query_ScheduledQueryInsightsResponse"></a>

Provides various insights and metrics related to the `ExecuteScheduledQueryRequest` that was executed.

## Contents
<a name="API_query_ScheduledQueryInsightsResponse_Contents"></a>

 ** OutputBytes **   <a name="timestream-Type-query_ScheduledQueryInsightsResponse-OutputBytes"></a>
Indicates the size of query result set in bytes. You can use this data to validate if the result set has changed as part of the query tuning exercise.  
Type: Long  
Required: No

 ** OutputRows **   <a name="timestream-Type-query_ScheduledQueryInsightsResponse-OutputRows"></a>
Indicates the total number of rows returned as part of the query result set. You can use this data to validate if the number of rows in the result set have changed as part of the query tuning exercise.  
Type: Long  
Required: No

 ** QuerySpatialCoverage **   <a name="timestream-Type-query_ScheduledQueryInsightsResponse-QuerySpatialCoverage"></a>
Provides insights into the spatial coverage of the query, including the table with sub-optimal (max) spatial pruning. This information can help you identify areas for improvement in your partitioning strategy to enhance spatial pruning.  
Type: [QuerySpatialCoverage](API_query_QuerySpatialCoverage.md) object  
Required: No

 ** QueryTableCount **   <a name="timestream-Type-query_ScheduledQueryInsightsResponse-QueryTableCount"></a>
Indicates the number of tables in the query.  
Type: Long  
Required: No

 ** QueryTemporalRange **   <a name="timestream-Type-query_ScheduledQueryInsightsResponse-QueryTemporalRange"></a>
Provides insights into the temporal range of the query, including the table with the largest (max) time range. Following are some of the potential options for optimizing time-based pruning:  
+ Add missing time-predicates.
+ Remove functions around the time predicates.
+ Add time predicates to all the sub-queries.
Type: [QueryTemporalRange](API_query_QueryTemporalRange.md) object  
Required: No

## See Also
<a name="API_query_ScheduledQueryInsightsResponse_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/ScheduledQueryInsightsResponse) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/ScheduledQueryInsightsResponse) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/ScheduledQueryInsightsResponse) 

# ScheduledQueryRunSummary
<a name="API_query_ScheduledQueryRunSummary"></a>

Run summary for the scheduled query

## Contents
<a name="API_query_ScheduledQueryRunSummary_Contents"></a>

 ** ErrorReportLocation **   <a name="timestream-Type-query_ScheduledQueryRunSummary-ErrorReportLocation"></a>
S3 location for error report.  
Type: [ErrorReportLocation](API_query_ErrorReportLocation.md) object  
Required: No

 ** ExecutionStats **   <a name="timestream-Type-query_ScheduledQueryRunSummary-ExecutionStats"></a>
Runtime statistics for a scheduled run.  
Type: [ExecutionStats](API_query_ExecutionStats.md) object  
Required: No

 ** FailureReason **   <a name="timestream-Type-query_ScheduledQueryRunSummary-FailureReason"></a>
Error message for the scheduled query in case of failure. You might have to look at the error report to get more detailed error reasons.   
Type: String  
Required: No

 ** InvocationTime **   <a name="timestream-Type-query_ScheduledQueryRunSummary-InvocationTime"></a>
InvocationTime for this run. This is the time at which the query is scheduled to run. Parameter `@scheduled_runtime` can be used in the query to get the value.   
Type: Timestamp  
Required: No

 ** QueryInsightsResponse **   <a name="timestream-Type-query_ScheduledQueryRunSummary-QueryInsightsResponse"></a>
Provides various insights and metrics related to the run summary of the scheduled query.  
Type: [ScheduledQueryInsightsResponse](API_query_ScheduledQueryInsightsResponse.md) object  
Required: No

 ** RunStatus **   <a name="timestream-Type-query_ScheduledQueryRunSummary-RunStatus"></a>
The status of a scheduled query run.  
Type: String  
Valid Values: `AUTO_TRIGGER_SUCCESS | AUTO_TRIGGER_FAILURE | MANUAL_TRIGGER_SUCCESS | MANUAL_TRIGGER_FAILURE`   
Required: No

 ** TriggerTime **   <a name="timestream-Type-query_ScheduledQueryRunSummary-TriggerTime"></a>
The actual time when the query was run.  
Type: Timestamp  
Required: No

## See Also
<a name="API_query_ScheduledQueryRunSummary_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/ScheduledQueryRunSummary) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/ScheduledQueryRunSummary) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/ScheduledQueryRunSummary) 

# SelectColumn
<a name="API_query_SelectColumn"></a>

Details of the column that is returned by the query. 

## Contents
<a name="API_query_SelectColumn_Contents"></a>

 ** Aliased **   <a name="timestream-Type-query_SelectColumn-Aliased"></a>
True, if the column name was aliased by the query. False otherwise.  
Type: Boolean  
Required: No

 ** DatabaseName **   <a name="timestream-Type-query_SelectColumn-DatabaseName"></a>
 Database that has this column.  
Type: String  
Required: No

 ** Name **   <a name="timestream-Type-query_SelectColumn-Name"></a>
Name of the column.  
Type: String  
Required: No

 ** TableName **   <a name="timestream-Type-query_SelectColumn-TableName"></a>
Table within the database that has this column.   
Type: String  
Required: No

 ** Type **   <a name="timestream-Type-query_SelectColumn-Type"></a>
Contains the data type of a column in a query result set. The data type can be scalar or complex. The supported scalar data types are integers, Boolean, string, double, timestamp, date, time, and intervals. The supported complex data types are arrays, rows, and timeseries.  
Type: [Type](API_query_Type.md) object  
Required: No

## See Also
<a name="API_query_SelectColumn_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/SelectColumn) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/SelectColumn) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/SelectColumn) 

# SnsConfiguration
<a name="API_query_SnsConfiguration"></a>

Details on SNS that are required to send the notification.

## Contents
<a name="API_query_SnsConfiguration_Contents"></a>

 ** TopicArn **   <a name="timestream-Type-query_SnsConfiguration-TopicArn"></a>
SNS topic ARN that the scheduled query status notifications will be sent to.  
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 2048.  
Required: Yes

## See Also
<a name="API_query_SnsConfiguration_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/SnsConfiguration) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/SnsConfiguration) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/SnsConfiguration) 

# Tag
<a name="API_query_Tag"></a>

A tag is a label that you assign to a Timestream database and/or table. Each tag consists of a key and an optional value, both of which you define. Tags enable you to categorize databases and/or tables, for example, by purpose, owner, or environment. 

## Contents
<a name="API_query_Tag_Contents"></a>

 ** Key **   <a name="timestream-Type-query_Tag-Key"></a>
The key of the tag. Tag keys are case sensitive.   
Type: String  
Length Constraints: Minimum length of 1. Maximum length of 128.  
Required: Yes

 ** Value **   <a name="timestream-Type-query_Tag-Value"></a>
The value of the tag. Tag values are case sensitive and can be null.   
Type: String  
Length Constraints: Minimum length of 0. Maximum length of 256.  
Required: Yes

## See Also
<a name="API_query_Tag_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/Tag) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/Tag) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/Tag) 

# TargetConfiguration
<a name="API_query_TargetConfiguration"></a>

Configuration used for writing the output of a query.

## Contents
<a name="API_query_TargetConfiguration_Contents"></a>

 ** TimestreamConfiguration **   <a name="timestream-Type-query_TargetConfiguration-TimestreamConfiguration"></a>
Configuration needed to write data into the Timestream database and table.  
Type: [TimestreamConfiguration](API_query_TimestreamConfiguration.md) object  
Required: Yes

## See Also
<a name="API_query_TargetConfiguration_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/TargetConfiguration) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/TargetConfiguration) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/TargetConfiguration) 

# TargetDestination
<a name="API_query_TargetDestination"></a>

Destination details to write data for a target data source. Current supported data source is Timestream.

## Contents
<a name="API_query_TargetDestination_Contents"></a>

 ** TimestreamDestination **   <a name="timestream-Type-query_TargetDestination-TimestreamDestination"></a>
Query result destination details for Timestream data source.  
Type: [TimestreamDestination](API_query_TimestreamDestination.md) object  
Required: No

## See Also
<a name="API_query_TargetDestination_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/TargetDestination) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/TargetDestination) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/TargetDestination) 

# TimeSeriesDataPoint
<a name="API_query_TimeSeriesDataPoint"></a>

The timeseries data type represents the values of a measure over time. A time series is an array of rows of timestamps and measure values, with rows sorted in ascending order of time. A TimeSeriesDataPoint is a single data point in the time series. It represents a tuple of (time, measure value) in a time series. 

## Contents
<a name="API_query_TimeSeriesDataPoint_Contents"></a>

 ** Time **   <a name="timestream-Type-query_TimeSeriesDataPoint-Time"></a>
The timestamp when the measure value was collected.  
Type: String  
Required: Yes

 ** Value **   <a name="timestream-Type-query_TimeSeriesDataPoint-Value"></a>
The measure value for the data point.  
Type: [Datum](API_query_Datum.md) object  
Required: Yes

## See Also
<a name="API_query_TimeSeriesDataPoint_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/TimeSeriesDataPoint) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/TimeSeriesDataPoint) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/TimeSeriesDataPoint) 

# TimestreamConfiguration
<a name="API_query_TimestreamConfiguration"></a>

 Configuration to write data into Timestream database and table. This configuration allows the user to map the query result select columns into the destination table columns. 

## Contents
<a name="API_query_TimestreamConfiguration_Contents"></a>

 ** DatabaseName **   <a name="timestream-Type-query_TimestreamConfiguration-DatabaseName"></a>
Name of Timestream database to which the query result will be written.  
Type: String  
Required: Yes

 ** DimensionMappings **   <a name="timestream-Type-query_TimestreamConfiguration-DimensionMappings"></a>
 This is to allow mapping column(s) from the query result to the dimension in the destination table.   
Type: Array of [DimensionMapping](API_query_DimensionMapping.md) objects  
Required: Yes

 ** TableName **   <a name="timestream-Type-query_TimestreamConfiguration-TableName"></a>
Name of Timestream table that the query result will be written to. The table should be within the same database that is provided in Timestream configuration.  
Type: String  
Required: Yes

 ** TimeColumn **   <a name="timestream-Type-query_TimestreamConfiguration-TimeColumn"></a>
Column from query result that should be used as the time column in destination table. Column type for this should be TIMESTAMP.  
Type: String  
Required: Yes

 ** MeasureNameColumn **   <a name="timestream-Type-query_TimestreamConfiguration-MeasureNameColumn"></a>
Name of the measure column.  
Type: String  
Required: No

 ** MixedMeasureMappings **   <a name="timestream-Type-query_TimestreamConfiguration-MixedMeasureMappings"></a>
Specifies how to map measures to multi-measure records.  
Type: Array of [MixedMeasureMapping](API_query_MixedMeasureMapping.md) objects  
Array Members: Minimum number of 1 item.  
Required: No

 ** MultiMeasureMappings **   <a name="timestream-Type-query_TimestreamConfiguration-MultiMeasureMappings"></a>
Multi-measure mappings.  
Type: [MultiMeasureMappings](API_query_MultiMeasureMappings.md) object  
Required: No

## See Also
<a name="API_query_TimestreamConfiguration_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/TimestreamConfiguration) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/TimestreamConfiguration) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/TimestreamConfiguration) 

# TimestreamDestination
<a name="API_query_TimestreamDestination"></a>

Destination for scheduled query.

## Contents
<a name="API_query_TimestreamDestination_Contents"></a>

 ** DatabaseName **   <a name="timestream-Type-query_TimestreamDestination-DatabaseName"></a>
Timestream database name.   
Type: String  
Required: No

 ** TableName **   <a name="timestream-Type-query_TimestreamDestination-TableName"></a>
Timestream table name.   
Type: String  
Required: No

## See Also
<a name="API_query_TimestreamDestination_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/TimestreamDestination) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/TimestreamDestination) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/TimestreamDestination) 

# Type
<a name="API_query_Type"></a>

Contains the data type of a column in a query result set. The data type can be scalar or complex. The supported scalar data types are integers, Boolean, string, double, timestamp, date, time, and intervals. The supported complex data types are arrays, rows, and timeseries.

## Contents
<a name="API_query_Type_Contents"></a>

 ** ArrayColumnInfo **   <a name="timestream-Type-query_Type-ArrayColumnInfo"></a>
Indicates if the column is an array.  
Type: [ColumnInfo](API_query_ColumnInfo.md) object  
Required: No

 ** RowColumnInfo **   <a name="timestream-Type-query_Type-RowColumnInfo"></a>
Indicates if the column is a row.  
Type: Array of [ColumnInfo](API_query_ColumnInfo.md) objects  
Required: No

 ** ScalarType **   <a name="timestream-Type-query_Type-ScalarType"></a>
Indicates if the column is of type string, integer, Boolean, double, timestamp, date, time. For more information, see [Supported data types](https://docs.aws.amazon.com/timestream/latest/developerguide/supported-data-types.html).  
Type: String  
Valid Values: `VARCHAR | BOOLEAN | BIGINT | DOUBLE | TIMESTAMP | DATE | TIME | INTERVAL_DAY_TO_SECOND | INTERVAL_YEAR_TO_MONTH | UNKNOWN | INTEGER`   
Required: No

 ** TimeSeriesMeasureValueColumnInfo **   <a name="timestream-Type-query_Type-TimeSeriesMeasureValueColumnInfo"></a>
Indicates if the column is a timeseries data type.  
Type: [ColumnInfo](API_query_ColumnInfo.md) object  
Required: No

## See Also
<a name="API_query_Type_SeeAlso"></a>

For more information about using this API in one of the language-specific AWS SDKs, see the following:
+  [AWS SDK for C\$1\$1](https://docs.aws.amazon.com/goto/SdkForCpp/timestream-query-2018-11-01/Type) 
+  [AWS SDK for Java V2](https://docs.aws.amazon.com/goto/SdkForJavaV2/timestream-query-2018-11-01/Type) 
+  [AWS SDK for Ruby V3](https://docs.aws.amazon.com/goto/SdkForRubyV3/timestream-query-2018-11-01/Type) 

# Common Error Types
<a name="CommonErrors"></a>

This section lists common error types that this AWS service may return. Not all services return all error types listed here. For errors specific to an API action for this service, see the topic for that API action.

 **AccessDeniedException**   <a name="CommonErrors-AccessDeniedException"></a>
You don't have permission to perform this action. Verify that your IAM policy includes the required permissions.  
HTTP Status Code: 403

 **ExpiredTokenException**   <a name="CommonErrors-ExpiredTokenException"></a>
The security token included in the request has expired. Request a new security token and try again.  
HTTP Status Code: 403

 **IncompleteSignature**   <a name="CommonErrors-IncompleteSignature"></a>
The request signature doesn't conform to AWS standards. Verify that you're using valid AWS credentials and that your request is properly formatted. If you're using an SDK, ensure it's up to date.  
HTTP Status Code: 403

 **InternalFailure**   <a name="CommonErrors-InternalFailure"></a>
The request can't be processed right now because of an internal server issue. Try again later. If the problem persists, contact AWS Support.  
HTTP Status Code: 500

 **MalformedHttpRequestException**   <a name="CommonErrors-MalformedHttpRequestException"></a>
The request body can't be processed. This typically happens when the request body can't be decompressed using the specified content encoding algorithm. Verify that the content encoding header matches the compression format used.  
HTTP Status Code: 400

 **NotAuthorized**   <a name="CommonErrors-NotAuthorized"></a>
You don't have permissions to perform this action. Verify that your IAM policy includes the required permissions.  
HTTP Status Code: 401

 **OptInRequired**   <a name="CommonErrors-OptInRequired"></a>
Your AWS account needs a subscription for this service. Verify that you've enabled the service in your account.  
HTTP Status Code: 403

 **RequestAbortedException**   <a name="CommonErrors-RequestAbortedException"></a>
The request was aborted before a response could be returned. This typically happens when the client closes the connection.  
HTTP Status Code: 400

 **RequestEntityTooLargeException**   <a name="CommonErrors-RequestEntityTooLargeException"></a>
The request entity is too large. Reduce the size of the request body and try again.  
HTTP Status Code: 413

 **RequestTimeoutException**   <a name="CommonErrors-RequestTimeoutException"></a>
The request timed out. The server didn't receive the complete request within the expected time frame. Try again.  
HTTP Status Code: 408

 **ServiceUnavailable**   <a name="CommonErrors-ServiceUnavailable"></a>
The service is temporarily unavailable. Try again later.  
HTTP Status Code: 503

 **ThrottlingException**   <a name="CommonErrors-ThrottlingException"></a>
Your request rate is too high. The AWS SDKs automatically retry requests that receive this exception. Reduce the frequency of requests.  
HTTP Status Code: 400

 **UnknownOperationException**   <a name="CommonErrors-UnknownOperationException"></a>
The action or operation isn't recognized. Verify that the action name is spelled correctly and that it's supported by the API version you're using.  
HTTP Status Code: 404

 **UnrecognizedClientException**   <a name="CommonErrors-UnrecognizedClientException"></a>
The X.509 certificate or AWS access key ID you provided doesn't exist in our records. Verify that you're using valid credentials and that they haven't expired.  
HTTP Status Code: 403

 **ValidationError**   <a name="CommonErrors-ValidationError"></a>
The input doesn't meet the required format or constraints. Check that all required parameters are included and that values are valid.  
HTTP Status Code: 400

# Common Parameters
<a name="CommonParameters"></a>

The following list contains the parameters that all actions use for signing Signature Version 4 requests with a query string. Any action-specific parameters are listed in the topic for that action. For more information about Signature Version 4, see [Signing AWS API requests](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html) in the *IAM User Guide*.

 **X-Amz-Algorithm**   <a name="CommonParameters-X-Amz-Algorithm"></a>
The hash algorithm that you used to create the request signature.  
Condition: Specify this parameter when you include authentication information in a query string instead of in the HTTP authorization header.  
Type: string  
Valid Values: `AWS4-HMAC-SHA256`   
Required: Conditional

 **X-Amz-Credential**   <a name="CommonParameters-X-Amz-Credential"></a>
The credential scope value, which is a string that includes your access key, the date, the region you are targeting, the service you are requesting, and a termination string ("aws4\$1request"). The value is expressed in the following format: *access\$1key*/*YYYYMMDD*/*region*/*service*/aws4\$1request.  
For more information, see [Create a signed AWS API request](https://docs.aws.amazon.com/IAM/latest/UserGuide/create-signed-request.html) in the *IAM User Guide*.  
Condition: Specify this parameter when you include authentication information in a query string instead of in the HTTP authorization header.  
Type: string  
Required: Conditional

 **X-Amz-Date**   <a name="CommonParameters-X-Amz-Date"></a>
The date that is used to create the signature. The format must be ISO 8601 basic format (YYYYMMDD'T'HHMMSS'Z'). For example, the following date time is a valid X-Amz-Date value: `20120325T120000Z`.  
Condition: X-Amz-Date is optional for all requests; it can be used to override the date used for signing requests. If the Date header is specified in the ISO 8601 basic format, X-Amz-Date is not required. When X-Amz-Date is used, it always overrides the value of the Date header. For more information, see [Elements of an AWS API request signature](https://docs.aws.amazon.com/IAM/latest/UserGuide/signing-elements.html) in the *IAM User Guide*.  
Type: string  
Required: Conditional

 **X-Amz-Security-Token**   <a name="CommonParameters-X-Amz-Security-Token"></a>
The temporary security token that was obtained through a call to AWS Security Token Service (AWS STS). For a list of services that support temporary security credentials from AWS STS, see [AWS services that work with IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html) in the *IAM User Guide*.  
Condition: If you're using temporary security credentials from AWS STS, you must include the security token.  
Type: string  
Required: Conditional

 **X-Amz-Signature**   <a name="CommonParameters-X-Amz-Signature"></a>
Specifies the hex-encoded signature that was calculated from the string to sign and the derived signing key.  
Condition: Specify this parameter when you include authentication information in a query string instead of in the HTTP authorization header.  
Type: string  
Required: Conditional

 **X-Amz-SignedHeaders**   <a name="CommonParameters-X-Amz-SignedHeaders"></a>
Specifies all the HTTP headers that were included as part of the canonical request. For more information about specifying signed headers, see [Create a signed AWS API request](https://docs.aws.amazon.com/IAM/latest/UserGuide/create-signed-request.html) in the *IAM User Guide*.  
Condition: Specify this parameter when you include authentication information in a query string instead of in the HTTP authorization header.  
Type: string  
Required: Conditional

# Document history
<a name="doc-history"></a>

| Change | Description | Date | 
| --- |--- |--- |
| [`AmazonTimestreamInfluxDBFullAccessWithoutMarketplaceAccess` – Update to an existing policy](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol.html#security-iam-awsmanpol-AmazonTimestreamInfluxDBFullAccessWithoutMarketplaceAccess) | Amazon Timestream for InfluxDB has added the `RebootDbInstance` and `RebootDbCluster` actions to the existing `AmazonTimestreamInfluxDBFullAccessWithoutMarketplaceAccess` managed policy for rebooting Amazon Timestream InfluxDB resources. For more information, see [AWS managed policies for Amazon Timestream for InfluxDB](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol-influxdb.html).  | December 17, 2025 | 
| [`AmazonTimestreamInfluxDBFullAccess` – Update to an existing policy](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol.html#security-iam-awsmanpol-AmazonTimestreamInfluxDBFullAccess) | Amazon Timestream for InfluxDB has added the `RebootDbInstance` and `RebootDbCluster` actions to the existing `AmazonTimestreamInfluxDBFullAccess` managed policy for rebooting Amazon Timestream InfluxDB resources. For more information, see [AWS managed policies for Amazon Timestream for InfluxDB](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol-influxdb.html).  | December 17, 2025 | 
| [`AmazonTimestreamInfluxDBFullAccessWithoutMarketplaceAccess` – Update to an existing policy](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol.html#security-iam-awsmanpol-AmazonTimestreamInfluxDBFullAccessWithoutMarketplaceAccess) | Amazon Timestream for InfluxDB has added the `ec2:DescribeVpcEndpoints` action to the existing `AmazonTimestreamInfluxDBFullAccessWithoutMarketplaceAccess` managed policy for describing the VPC endpoints. For more information, see [AWS managed policies for Amazon Timestream for InfluxDB](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol-influxdb.html).  | November 13, 2025 | 
| [`AmazonTimestreamInfluxDBFullAccess` – Update to an existing policy](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol.html#security-iam-awsmanpol-AmazonTimestreamInfluxDBFullAccess) | Amazon Timestream for InfluxDB has added the `ec2:DescribeVpcEndpoints` action to the existing `AmazonTimestreamInfluxDBFullAccess` managed policy for describing the VPC endpoints. For more information, see [AWS managed policies for Amazon Timestream for InfluxDB](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol-influxdb.html).  | November 13, 2025 | 
| [`AmazonTimestreamInfluxDBFullAccess` – Update to an existing policy](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol.html#security-iam-awsmanpol-AmazonTimestreamInfluxDBFullAccess) | Amazon Timestream for InfluxDB has added Influx Enterprise marketplace product ID to the existing `AmazonTimestreamInfluxDBFullAccess` managed policy to support subscription to enterprise marketplace offerings. See [AmazonTimestreamInfluxDBFullAccess](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol-influxdb.html#iam.identitybasedpolicies.predefinedpolicies). | October 17, 2025 | 
| [`AmazonTimestreamConsoleFullAccess` – Update to an existing policy](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol.html#security-iam-awsmanpol-AmazonTimestreamConsoleFullAccess) | Timestream for LiveAnalytics has added the AWS Marketplace permissions to the `AmazonTimestreamConsoleFullAccess` managed policy to access marketplace resources and create agreements for InfluxDB Cluster with Read Replicas creation. | August 20, 2025 | 
| [`AmazonTimestreamConsoleFullAccess` – Update to an existing policy](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol.html#security-iam-awsmanpol-AmazonTimestreamConsoleFullAccess) | Timestream for InfluxDB has added the AWS Marketplace permissions to the `AmazonTimestreamConsoleFullAccess` managed policy to access marketplace resources and create agreements for InfluxDB Cluster with Read Replicas creation. | August 20, 2025 | 
| [`AmazonTimestreamConsoleFullAccess` – Update to an existing policy](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol.html#security-iam-awsmanpol-AmazonTimestreamConsoleFullAccess) | Amazon Timestream for InfluxDB has added the `pricing:GetProducts` permission to the `AmazonTimestreamConsoleFullAccess` managed policy to provide pricing estimations for InfluxDB resource configurations during creation. | June 10, 2025 | 
| [Amazon Timestream for LiveAnalytics will no longer be open to new customers starting June 20, 2025.](AmazonTimestreamForLiveAnalytics-availability-change.md) | For similar capabilities to Amazon Timestream for LiveAnalytics, consider Amazon Timestream for InfluxDB. It offers simplified data ingestion and single-digit millisecond query response times for real-time analytics. Learn more [here](https://docs.aws.amazon.com//timestream/latest/developerguide/timestream-for-influxdb.html). | May 20, 2025 | 
| [`AmazonTimestreamInfluxDBFullAccessWithoutMarketplaceAccess` – New policy](doc-history-influxdb.md) | This policy grants administrative permissions that allow full access to all Timestream for InfluxDB resources, excluding any marketplace-related actions. For more information see [AWS managed policies for Amazon Timestream for InfluxDB](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol-influxdb.html). | April 16, 2025 | 
| [`AmazonTimestreamInfluxDBFullAccess` – Update to an existing policy](doc-history-influxdb.md) | Amazon Timestream for InfluxDB has added to the existing `AmazonTimestreamInfluxDBFullAccess` managed policy. For more information, see [AWS managed policies for Amazon Timestream for InfluxDB](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol-influxdb.html). | April 16, 2025 | 
| [`AmazonTimestreamInfluxDBFullAccess` – Update to an existing policy](doc-history-influxdb.md) | Amazon Timestream for InfluxDB has added access to create, update, delete, and list Amazon Timestream InfluxDB clusters to the existing `AmazonTimestreamInfluxDBFullAccess` managed policy. For more information, see [AWS managed policies for Amazon Timestream for InfluxDB](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol-influxdb.html). | February 17, 2025 | 
| [Documentation-only update](https://docs.aws.amazon.com/timestream/latest/developerguide/ts-limits.html) | Updated the Quotas topic to segregate the default quotas and system limits. | October 22, 2024 | 
| [Amazon Timestream now supports query insights](https://docs.aws.amazon.com/timestream/latest/developerguide/using-query-insights.html) | Timestream now includes support for the query insights feature that helps you optimize your queries, improve their performance, and reduce costs. | October 22, 2024 | 
| [Amazon Timestream for InfluxDB update to an existing policy.](doc-history-influxdb.md) | Amazon Timestream for InfluxDB has added the `ec2:DescribeRouteTables` action to the existing `AmazonTimestreamInfluxDBFullAccess` managed policy for describing your route tables. For more information, see [AWS managed policies for Amazon Timestream for InfluxDB](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol-influxdb.html).  | October 8, 2024 | 
| [`AmazonTimestreamInfluxDBFullAccess` – Update to an existing policy](doc-history-influxdb.md) | Amazon Timestream for InfluxDB has added the `ec2:DescribeRouteTables` action to the existing `AmazonTimestreamInfluxDBFullAccess` managed policy. This action is used for describing your route tables. See [AmazonTimestreamInfluxDBFullAccess](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol-influxdb.html#iam.identitybasedpolicies.predefinedpolicies). | September 12, 2024 | 
| [`AmazonTimestreamReadOnlyAccess` – Update to an existing policy](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol.html#security-iam-awsmanpol-AmazonTimestreamReadOnlyAccess) | Timestream for LiveAnalytics has added the `DescribeAccountSettings` permission to the `AmazonTimestreamReadOnlyAccess` managed policy for describing AWS account settings. | June 3, 2024 | 
| [Amazon Timestream for LiveAnalytics now supports Timestream Compute Units (TCUs)](https://docs.aws.amazon.com/timestream/latest/developerguide/tcu.html) | Amazon Timestream for LiveAnalytics now includes support for Timestream Compute Units (TCUs) to measure the compute capacity allocated for your query needs. | April 29, 2024 | 
| [New policies added](doc-history-influxdb.md) | Amazon Timestream for InfluxDB added two new policies: One that allows the service to manage network interfaces and security groups in your account. For more information, see [AmazonTimestreamInfluxDBServiceRolePolicy](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol-influxdb.html#security-iam-awsmanpol-timestreamforinfluxdbServiceRolePolicy). Another that provide full administrative access to create, update, delete and list Amazon Timestream InfluxDB instances and create and list parameter groups. For more information, see [AmazonTimestreamInfluxDBFullAccess](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol-influxdb.html#iam.identitybasedpolicies.predefinedpolicies). | March 14, 2024 | 
| [Amazon Timestream for InfluxDB is now generally available.](https://docs.aws.amazon.com/timestream/latest/developerguide/timestream-for-influxdb.html) | This documentation covers the initial release of Amazon Timestream for InfluxDB. | March 14, 2024 | 
| [Amazon Timestream for LiveAnalytics Query events are available in AWS CloudTrail](https://docs.aws.amazon.com/timestream/latest/developerguide/logging-using-cloudtrail.html) | Amazon Timestream for LiveAnalytics now publishes Query API data events to AWS CloudTrail. Customers can audit all Query API requests made in their AWS accounts, and see information such as which IAM User/Role made the request, when the request was made, which databases and tables were queried, and the request's Query ID. | September 12, 2023 | 
| [Amazon Timestream for LiveAnalytics UNLOAD](https://docs.aws.amazon.com/timestream/latest/developerguide/export-unload.html) | Amazon Timestream for LiveAnalytics now supports UNLOAD to export query results to S3. | May 12, 2023 | 
| [Amazon Timestream for LiveAnalytics update to an existing policy.](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol.html) | Batch load permissions added to a managed policy. | February 24, 2023 | 
| [Amazon Timestream for LiveAnalytics batch load.](https://docs.aws.amazon.com/timestream/latest/developerguide/batch-load.html) | Amazon Timestream for LiveAnalytics now supports batch load functionality. | February 24, 2023 | 
| [Amazon Timestream for LiveAnalytics now supports AWS Backup.](https://docs.aws.amazon.com/timestream/latest/developerguide/backups.html) | Amazon Timestream for LiveAnalytics now supports AWS Backup. | December 14, 2022 | 
| [Amazon Timestream for LiveAnalytics updates to AWS managed policies](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol.html) | New information about AWS managed policies and Amazon Timestream for LiveAnalytics, including updates to existing managed policies. | November 29, 2021 | 
| [Amazon Timestream for LiveAnalytics supports scheduled queries](https://docs.aws.amazon.com/timestream/latest/developerguide/scheduledqueries.html) | Amazon Timestream for LiveAnalytics now supports running a query on your behalf, based on a schedule.  | November 29, 2021 | 
| [Amazon Timestream for LiveAnalytics supports magnetic store.](https://docs.aws.amazon.com/timestream/latest/developerguide/writes.html) | Amazon Timestream for LiveAnalytics now supports using magnetic storage for your table writes. | November 29, 2021 | 
| [Amazon Timestream for LiveAnalytics multi-measure records.](https://docs.aws.amazon.com/timestream/latest/developerguide/writes.html#writes.writing-data-multi-measure) | Amazon Timestream for LiveAnalytics now supports a more compact format for storing your time-series data. | November 29, 2021 | 
| [Amazon Timestream for LiveAnalytics updates to AWS managed policies](https://docs.aws.amazon.com/timestream/latest/developerguide/security-iam-awsmanpol.html) | New information about AWS managed policies and Amazon Timestream for LiveAnalytics, including updates to existing managed policies. | May 24, 2021 | 
| [Amazon Timestream for LiveAnalytics is now available in the Europe (Frankfurt) region.](https://docs.aws.amazon.com/timestream/latest/developerguide/what-is-timestream.html) | Amazon Timestream for LiveAnalytics is now generally available in the Europe (Frankfurt) region (`eu-central-1`). | April 23, 2021 | 
| [Amazon Timestream for LiveAnalytics now supports VPC endpoints (AWS PrivateLink).](https://docs.aws.amazon.com/timestream/latest/developerguide/VPCEndpoints.html) | Amazon Timestream for LiveAnalytics now supports the use of VPC endpoints (AWS PrivateLink). | March 23, 2021 | 
| [Amazon Timestream now supports cross table queries.](https://docs.aws.amazon.com/timestream/latest/developerguide/supported-sql-constructs.SELECT.html) | You can use Amazon Timestream for LiveAnalytics to run cross table queries.  | February 10, 2021 | 
| [Amazon Timestream for LiveAnalytics now supports enhanced query execution statistics.](https://docs.aws.amazon.com/timestream/latest/developerguide/API_query_Query.html) | Amazon Timestream for LiveAnalytics now supports enhanced query execution statistics, such as amount of data scanned.  | February 10, 2021 | 
| [Amazon Timestream for LiveAnalytics now supports advanced time series functions.](https://docs.aws.amazon.com/timestream/latest/developerguide/timeseries-specific-constructs.functions.html) | You can use Amazon Timestream for LiveAnalytics to run SQL queries with advanced time series functions, such as derivatives, integrals, and correlations.  | February 10, 2021 | 
| [Amazon Timestream for LiveAnalytics is now HIPAA, ISO, and PCI compliant.](https://docs.aws.amazon.com/timestream/latest/developerguide/what-is-timestream.html) | You can now use Amazon Timestream for LiveAnalytics for workloads that require HIPAA, ISO, and PCI-compliant infrastructure.  | January 27, 2021 | 
| [Amazon Timestream for LiveAnalytics now supports open-source Telegraf and Grafana.](https://docs.aws.amazon.com/timestream/latest/developerguide/OtherServices.html) | You can now use Telegraf, the open-source, plugin-driven server agent for collecting and reporting metrics, and Grafana, the open-source analytics and monitoring platform for databases, with Amazon Timestream for LiveAnalytics.  | November 25, 2020 | 
| [Amazon Timestream for LiveAnalytics is now generally available.](https://docs.aws.amazon.com/timestream/latest/developerguide/what-is-timestream.html) | This documentation covers the initial release of Amazon Timestream for LiveAnalytics. | September 30, 2020 | 