DynamoDB PartiQL 대 SQL: 무엇이 깨지나
DynamoDB PartiQL을 둘러싼 가장 큰 혼란의 근원은 — 사람이든 AI 어시스턴트든 마찬가지로 — 그것을 관계형 SQL로 여기는 것입니다. 그렇지 않습니다. PartiQL은 DynamoDB의 기존 연산 위에 얹힌 SQL 호환 표면이지, 조인하거나 그룹화하거나 집계할 수 있는 쿼리 엔진이 아닙니다. 익숙한 키워드가 아래의 아주 다른 기계를 감추고 있습니다.
DynamoDB PartiQL은 SQL과 어떻게 다른가요?
PartiQL은 SQL의 문법은 빌려오지만 그 엔진은 빌려오지 않습니다. DynamoDB에서 모든 문은 단일 네이티브 연산 — GetItem, Query, Scan, PutItem, UpdateItem, DeleteItem — 으로 매핑되므로 JOIN, GROUP BY, 서브쿼리, 집계가 없습니다. SQL처럼 읽히지만 그 키-값 연산들이 이미 할 수 있는 것만 할 수 있습니다.
모든 PartiQL 문은 DynamoDB의 네이티브 연산 중 하나로 컴파일됩니다.
| 여러분이 쓰는 것 | DynamoDB가 실행하는 것 |
|---|---|
SELECT … WHERE PK = … | GetItem 또는 Query |
SELECT … (PK 없음) | Scan (테이블 전체를 읽음) |
INSERT INTO … | PutItem |
UPDATE … WHERE PK=… AND SK=… | UpdateItem (항목 하나) |
DELETE … WHERE PK=… AND SK=… | DeleteItem (항목 하나) |
두 테이블에서 읽거나, 해시 조인을 만들거나, 행을 COUNT로 접을 수 있는 플래너는
없습니다. 연산이 단일 Get/Query/Scan/Put/Update/Delete로 매핑되지 않으면 PartiQL은
그것을 표현할 수 없습니다. 그게 전부입니다 — 아래의 모든 것은 이 한 가지 사실의
결과입니다.
같은 매핑을 흐름으로 본 것 — WHERE 절이 SELECT가 저렴한 Query인지 테이블 전체
Scan인지를 결정합니다.
각 문은 정확히 하나의 네이티브 연산으로 귀결됩니다 — 그 일대일 매핑이 PartiQL이 조인·그룹화·집계를 못 하는 이유입니다.
무엇이 다른가 — 기능별로
Workbench 열이 PartiQL의 아니요에 맞서 예라고 말하는 곳마다, 그것이 DynoTable의 SQL 가 메우는 격차입니다. Workbench는 여러분의 테이블을 DynamoDB의 실제 쿼리 런타임을 통해 구체화하고 그 위에서 진짜 SQL을 실행합니다 — DynamoDB의 액세스 패턴 규칙 안에서의 SQL.
| 기능 | 표준 SQL | DynamoDB PartiQL | DynoTable Workbench |
|---|---|---|---|
JOIN … ON … | 예 | 아니요 | 예 — INNER / LEFT (PK 또는 GSI 파티션 키 대상) |
RIGHT / FULL / CROSS / 콤마 조인 | 예 | 아니요 | 아니요 |
| 셀프 조인 | 예 | 아니요 | 아니요 (아직) |
| 서브쿼리 / 파생 테이블 | 예 | 아니요 | 아니요 |
CTE (WITH …) | 예 | 아니요 | 아니요 |
UNION / INTERSECT / EXCEPT | 예 | 아니요 | 아니요 |
GROUP BY / HAVING | 예 | 아니요 | 예 |
집계 (COUNT/SUM/AVG/MIN/MAX) | 예 | 아니요 | 예 |
DISTINCT | 예 | 아니요 | 예 |
CASE / CAST | 예 | 아니요 | 예 |
| 윈도우 함수 | 예 | 아니요 | 아니요 |
ORDER BY | 예, 임의 열 | 부분적 — 정렬 키만 (파티션 키 WHERE 필요) | 예, 임의 열 |
LIMIT | 예 | 인라인 불가 (요청의 limit 파라미터 사용) | 예 |
LIKE | 예 | 아니요 (contains / begins_with 사용) | 예 |
IS NULL / IS NOT NULL | 예 | 예 (없는 속성은 NULL이 아니라 MISSING — IS MISSING 사용) | 예 |
PK 없는 SELECT * | 스캔함 | 부분적 — 조용한 테이블 전체 Scan | 예 (비용 가시성 포함) |
무엇이 깨지고, 왜
이들은 쿼리가 전선에 닿기도 전에 DynoTable의 PartiQL 검증기가 표시하는 실패들입니다 — 각각은 실제 DynamoDB 제약으로 거슬러 올라갑니다.
- 없는
SELECT *는 숨은Scan입니다. PartiQL은 오류를 내지 않습니다. 그저 모든 항목을 읽고 나중에 필터링하는데, 이것이 친근한 문법 뒤에 숨은 고전적인 Query 대 Scan 비용 함정입니다. UPDATE/DELETE는 전체 기본 키가 필요합니다. 이들은 단일 항목UpdateItem/DeleteItem으로 매핑되므로,WHERE가 파티션 키(그리고 테이블에서는 정렬 키)를 고정해야 합니다. "status = 'open'인 모든 행 업데이트"를 한 문으로 할 수 없습니다.- 큰따옴표는 문자열이 아니라 식별자입니다. DynamoDB PartiQL은 여기서 SQL 표준을
따릅니다.
"name"은 열/테이블 이름이고,'name'은 문자열 값입니다. 값을 큰따옴표로 감싸는 것이 가장 흔한 초보자 실수입니다 — 검증기의 메시지는 문자 그대로 "큰따옴표는 DynamoDB PartiQL에서 문자열이 아니라 식별자를 구분합니다. 문자열 값에는 작은따옴표를 쓰세요." 입니다. IN은 괄호가 아니라 대괄호를 씁니다:WHERE pk IN ['a','b'], PK 값 50개 / 비키 값 100개로 제한됩니다.JOIN없음, 집계 없음. 테이블을 결합하거나 행을 접을 엔진이 없습니다. 이것이 단일 테이블 설계의 트레이드오프입니다. 쿼리 계층이 사후에 데이터를 재구성할 수 없으므로 액세스 패턴에 맞춰 미리 모델링합니다.
왜 AI 어시스턴트가 이걸 틀리나
LLM은 바다처럼 방대한 관계형 SQL로 훈련되므로, DynamoDB에 대해 JOIN, GROUP BY,
LIKE, 인라인 LIMIT, 큰따옴표 문자열 리터럴을 자신 있게 내뱉습니다 — 전부 DynamoDB가
거부하는 것들이죠. DynoTable 자체의 모델-쿼리 자동 수정이 존재하는 이유가 바로
저렴한 모델들이 이 패턴을 어김없이 만들어 내기 때문입니다. 이 기능은 이중 이스케이프된
따옴표를 벗기고, LIKE '%x%' → contains, IS NULL → attribute_not_exists로
다시 쓰며, 인라인 LIMIT을 요청 파라미터로 끌어올립니다. AI가 Postgres처럼 읽히는
"PartiQL"을 생성하고 있다면, 그게 신호입니다.
DynoTable의 SQL Workbench: PartiQL이 못 돌리는 쿼리
정말로 JOIN이나 GROUP BY가 필요할 때, DynoTable의 SQL Workbench가 답입니다.
각 JOIN의 대상 쪽을 파티션 키에 대해 검증하고, 조인된 행을 DynamoDB의 실제
Query/Scan 런타임을 통해 구체화한 다음, 그 위에서 단일 SELECT(집계, GROUP BY,
DISTINCT, CASE, CAST)를 실행합니다 —
DynamoDB의 액세스 패턴 규칙 안에서의 SQL.
-- Runs in the DynoTable Workbench (NOT in PartiQL):
SELECT c.country, COUNT(*) AS orders, SUM(o.total) AS revenue
FROM orders o
INNER JOIN customers c ON o.customerId = c.PK
GROUP BY c.country
ORDER BY revenue DESC정직한 제약(Workbench는 DynamoDB의 액세스 모델을 강제하며, Postgres인 척하지 않습니다):
INNER JOIN과LEFT JOIN만 —ON의 대상 속성은 파티션 키나 GSI 파티션 키여야 합니다.RIGHT/FULL/CROSS/ 콤마 조인은 없습니다.- 아직 셀프 조인 없음, 서브쿼리 없음, 파생 테이블 없음, 윈도우 함수 없음.
- 조인과 프로젝션은 스칼라 속성에 대해 작동합니다.
원시 API를 위한 조건과 키 표현식만 구성하면 된다면,
DynamoDB Expression Builder가 PartiQL 표면 없이도
올바른 FilterExpression / KeyConditionExpression을 생성합니다. PartiQL을 제대로
쓰는 법은 실습한 PartiQL 예제를 보세요. 어떤 쿼리든 비용을
가늠하려면 항목 크기 계산기를 쓰세요. PartiQL은
전선 형식을 결코 바꾸지 않습니다 — 값은 여전히 DynamoDB-JSON으로
이동합니다. 클라이언트를 고르는 중인가요? Workbench가
일반 DynamoDB GUI나 Dynobase에
견줘 어디에 서는지 보세요.
FAQ
PartiQL은 SQL과 같나요?
아니요. PartiQL은 SQL 호환 쿼리 언어이지만, DynamoDB에서는 단일
Get/Query/Scan/Put/Update/Delete로 매핑되는 연산만 노출합니다. 조인, 집계, 서브쿼리,
GROUP BY가 없습니다.
DynamoDB PartiQL로 JOIN을 할 수 있나요?
아니요. DynamoDB PartiQL은 테이블을 조인할 수 없습니다. DynoTable의 SQL Workbench는
데이터를 DynamoDB의 실제 쿼리 런타임을 통해 구체화하여 INNER/LEFT JOIN(파티션 키
또는 GSI 파티션 키 대상)을 실행할 수 있습니다.
DynamoDB PartiQL은 GROUP BY나 COUNT를 지원하나요?
아니요 — DynamoDB PartiQL에는 집계나 GROUP BY가 없습니다.
COUNT/SUM/AVG/GROUP BY/HAVING 쿼리에는 DynoTable의 SQL Workbench를 쓰세요.
왜 제 SELECT *가 이렇게 비싼가요?
WHERE에 파티션 키가 없으면 PartiQL은 테이블 전체 Scan을 실행하고 필터가 적용되기
전에 읽힌 모든 항목을 계측합니다. 파티션 키 조건을 추가해 Query로 바꾸세요.
PartiQL에서 작은따옴표를 써야 하나요, 큰따옴표를 써야 하나요?
문자열 값에는 작은따옴표('CUSTOMER#42'), 테이블·속성 이름 같은 식별자에는
큰따옴표("AppData")를 쓰세요. 값을 큰따옴표로 감싸는 것이 가장 흔한 PartiQL
실수입니다.
DynamoDB에 진짜 SQL을 돌릴 준비가 되셨나요? DynoTable을 다운로드하고 Workbench 탭을 여세요.