Athena выполняет запросы по JSON или JSON использовался только для описания схемы
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
# Amazon Athena и JSON
Это хороший вопрос, который проверяет понимание работы Athena с различными форматами данных. Дам полный ответ.
Краткий ответ
JSON использовался ТОЛЬКО для описания схемы. Athena выполняет запросы по самим данным, которые хранятся в S3 в определённом формате (Parquet, CSV, JSON и т.д.), но схема может быть определена разными способами, включая JSON.
Как это работает
Способ 1: Сразу же создание таблицы с JSON данными
CREATE EXTERNAL TABLE users (
id INT,
name STRING,
email STRING,
age INT
)
STORED AS JSONLINES
LOCATION 's3://my-bucket/users/'
Что это означает:
- STORED AS JSONLINES — данные в S3 хранятся в JSON-формате (newline-delimited JSON)
- Каждая строка — отдельный JSON объект
- Athena выполняет запросы прямо по этим JSON файлам в S3
- Схема определена в SQL CREATE TABLE
{"id": 1, "name": "Alice", "email": "alice@example.com", "age": 30}
{"id": 2, "name": "Bob", "email": "bob@example.com", "age": 25}
{"id": 3, "name": "Charlie", "email": "charlie@example.com", "age": 35}
SELECT * FROM users WHERE age > 30;
-- Результат:
-- id=1, name=Alice, email=alice@example.com, age=30
-- id=3, name=Charlie, email=charlie@example.com, age=35
Athena читает JSON файлы из S3 и выполняет запросы по ним.
Способ 2: Использование Glue Catalog
# AWS Glue создает схему в JSON-подобном формате
{
"Name": "users",
"StorageDescriptor": {
"Columns": [
{"Name": "id", "Type": "int"},
{"Name": "name", "Type": "string"},
{"Name": "email", "Type": "string"},
{"Name": "age", "Type": "int"}
],
"Location": "s3://my-bucket/users/",
"InputFormat": "org.apache.hadoop.mapred.TextInputFormat",
"OutputFormat": "org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat",
"SerdeInfo": {
"SerializationLibrary": "org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe"
}
}
}
Это JSON используется только для ОПИСАНИЯ схемы в Glue Catalog. Athena использует эту информацию для понимания структуры таблицы, но сами данные в S3 могут быть в любом формате (JSON, Parquet, CSV, ORC и т.д.).
Различие между форматом данных и схемой
ВАЖНО: format != schema definition
┌──────────────────────────────────┐
│ SCHEMA DEFINITION (SQL или JSON) │
│ ┌─────────────────────────────┐ │
│ │ id INT │ │
│ │ name STRING │ │
│ │ email STRING │ │
│ │ age INT │ │
│ └─────────────────────────────┘ │
└──────────────────────────────────┘
↓
┌──────────────────────────────────┐
│ DATA FORMAT IN S3 │
│ ┌─────────────────────────────┐ │
│ │ JSON, CSV, Parquet, │ │
│ │ ORC, или другой формат │ │
│ └─────────────────────────────┘ │
└──────────────────────────────────┘
Поддерживаемые форматы в Athena
1 JSON / JSONLINES (Newline-delimited JSON)
CREATE EXTERNAL TABLE logs (
timestamp STRING,
level STRING,
message STRING
)
STORED AS JSONLINES
LOCATION 's3://my-bucket/logs/'
Данные в S3:
{"timestamp": "2024-01-01T10:00:00Z", "level": "INFO", "message": "System started"}
{"timestamp": "2024-01-01T10:00:01Z", "level": "ERROR", "message": "Connection failed"}
2 Parquet (рекомендуется для Athena)
CREATE EXTERNAL TABLE events (
event_id STRING,
event_name STRING,
timestamp BIGINT
)
STORED AS PARQUET
LOCATION 's3://my-bucket/events/'
Плюсы Parquet:
- Columnar формат (быстрее для аналитики)
- Сжатие (меньше места в S3)
- Более быстрые запросы
- Дешевле (Athena считает по объёму отсканированных данных)
3 CSV
CREATE EXTERNAL TABLE orders (
order_id INT,
customer_id INT,
total DECIMAL(10, 2)
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LOCATION 's3://my-bucket/orders/'
4 ORC (Optimized Row Columnar)
CREATE EXTERNAL TABLE products (
product_id INT,
product_name STRING,
price DECIMAL(10, 2)
)
STORED AS ORC
LOCATION 's3://my-bucket/products/'
Пример: Athena выполняет запросы по JSON
import boto3
import time
athena = boto3.client('athena')
# S3 содержит JSON файлы
# s3://my-bucket/users/part-00000.json с содержимым:
# {"id": 1, "name": "Alice", "email": "alice@example.com", "age": 30}
# {"id": 2, "name": "Bob", "email": "bob@example.com", "age": 25}
# Сначала создаем таблицу
create_table_query = """
CREATE EXTERNAL TABLE IF NOT EXISTS users (
id INT,
name STRING,
email STRING,
age INT
)
STORED AS JSONLINES
LOCATION 's3://my-bucket/users/'
"""
athena.start_query_execution(
QueryString=create_table_query,
QueryExecutionContext={'Database': 'default'},
ResultConfiguration={'OutputLocation': 's3://my-bucket/athena-results/'}
)
time.sleep(5) # Ждем создания таблицы
# Теперь выполняем запрос прямо по JSON данным
select_query = "SELECT * FROM users WHERE age > 28"
response = athena.start_query_execution(
QueryString=select_query,
QueryExecutionContext={'Database': 'default'},
ResultConfiguration={'OutputLocation': 's3://my-bucket/athena-results/'}
)
query_execution_id = response['QueryExecutionId']
# Ждем результаты
while True:
result = athena.get_query_execution(QueryExecutionId=query_execution_id)
if result['QueryExecution']['Status']['State'] == 'SUCCEEDED':
break
time.sleep(1)
# Получаем результаты
results = athena.get_query_results(QueryExecutionId=query_execution_id)
for row in results['ResultSet']['Rows']:
print(row) # Результаты запроса по JSON данным
JSON для сложных типов
Athena может работать с вложенными JSON структурами:
CREATE EXTERNAL TABLE orders (
order_id INT,
customer STRUCT<id: INT, name: STRING, email: STRING>,
items ARRAY<STRUCT<product_id: INT, quantity: INT, price: DECIMAL(10, 2)>>,
metadata MAP<STRING, STRING>
)
STORED AS JSONLINES
LOCATION 's3://my-bucket/orders/'
Данные:
{
"order_id": 1,
"customer": {"id": 100, "name": "Alice", "email": "alice@example.com"},
"items": [
{"product_id": 1, "quantity": 2, "price": 50.00},
{"product_id": 2, "quantity": 1, "price": 100.00}
],
"metadata": {"source": "web", "campaign": "summer_sale"}
}
Запросы:
-- Доступ к полям struct
SELECT order_id, customer.name FROM orders;
-- Работа с массивами
SELECT order_id, items[0].product_id FROM orders;
-- Функции для работы с массивами
SELECT order_id, size(items) as item_count FROM orders;
Ответ на исходный вопрос
Вариант 1 (правильный)
JSON использовался ТОЛЬКО для описания схемы — это верно, если речь идёт о JSON как о способе определения структуры таблицы (например, в AWS Glue Catalog или CloudFormation).
Вариант 2 (тоже верно, но в другом контексте)
Athena выполняет запросы по JSON — это верно, если речь идёт о хранении данных в JSON-формате в S3 (JSONLINES). Athena может читать и выполнять запросы по JSON файлам напрямую.
Правильный полный ответ
"Athena может работать с JSON двумя способами:
- JSON как формат данных: Athena выполняет запросы по JSON файлам, хранящимся в S3 (STORED AS JSONLINES)
- JSON как описание схемы: JSON используется для определения структуры таблицы (например, в AWS Glue Catalog или при создании таблицы через AWS Console)
Они не взаимоисключающие — оба способа используются одновременно. Athena использует JSON описание схемы, чтобы понять, как интерпретировать JSON (или другие) данные в S3."
Рекомендация
Для лучшей производительности в Athena используй Parquet вместо JSON:
- Parquet быстрее (columnar format)
- Дешевле (меньше данных для сканирования)
- Лучше сжимается
# Преобразование JSON в Parquet
import pandas as pd
import pyarrow.parquet as pq
# Читаем JSON
df = pd.read_json('s3://my-bucket/users.jsonl', lines=True)
# Сохраняем в Parquet
df.to_parquet('s3://my-bucket/users-parquet/')