와일드카드 테이블은 BigQuery에서 특별히 제공하는 기능으로, 여러 테이블을 한 번에 참조할 수 있게 해줍니다. FROM절에서 특정한 이름 패턴을 가진 여러 테이블을 선택하거나 조회할 때 사용되며, 정확한 테이블 이름 대신 패턴으로 테이블을 지정할 수 있습니다. 이는 특히 여러 테이블에 나눠져 저장된 데이터를 효과적으로 조회할 때 유용합니다.
11.1.1. Wildcard Table의 사용
즉, 테이블 이름에 공통된 부분이 있을 때, 그 공통된 부분의 패턴을 이용하여 여러 테이블을 한꺼번에 검색할 수 있게 해줍니다. 특정한 일자 패턴을 가진 테이블 혹은 특정 접두사를 가진 테이블들에 대한 데이터를 한 번에 조회할 수 있습니다.
월간 기사를 게시하는 블로그 데이터가 다음과 같이 매월 각각의 테이블로 저장된다고 가정해 보겠습니다.
user_blog_202212 (2022년 12월)
user_blog_202301 (2023년 01월)
user_blog_202302 (2023년 02월)
user_blog_202303 (2023년 03월)
11장 이전에 소개한 방법으로 2023년의 모든 사용자 블로그 데이터를 한 번에 조회하려면 모든 테이블을 UNION을 통해 합쳐야 합니다. 하지만 BigQuery의 와일드카드 테이블을 사용하면, 모든 월의 데이터를 간단하게 조회할 수 있습니다.
따라서, 2023년의 모든 데이터를 한 번에 보고 싶을 때 user_blog_2023*처럼 Asterisk(별표, *) 기호를 사용하여 검색하면 그 달의 모든 데이터를 한 번에 볼 수 있습니다.
11.1.2. 데이터 불러오기
BigQuery의 공개 데이터셋 중, Google Merchandise Store에 대한 내용이 포함된 Google Analytics Sample 데이터셋을 불러오도록 하겠습니다.
탐색기의 “+추가” 버튼 클릭 후, 공개 데이터셋을 선택합니다.
“google analytics sample”을 검색하고 데이터를 선택합니다.
데이터세트 보기를 클릭하여 공개 데이터셋을 불러옵니다.
4. 데이터셋 내 테이블의 스키마와 미리 보기 등 정보를 확인할 수 있으며, 쿼리를 통한 작업이 가능합니다.
11.1.3. Wildcard Table 문법
SELECT *
FROM `<project-id>.<dataset-id>.<table-prefix>*`
WHERE bool_expression
<project-id>: BigQuery에서 사용자의 데이터와 관련 설정을 저장하는 고유한 식별자입니다. GCP(Google Cloud Platform) 프로젝트에는 고유한 ID가 있으며, 이 ID를 통해 특정 데이터나 리소스에 액세스할 수 있습니다.
<dataset-id>: 데이터셋의 이름 또는 고유 ID입니다.
<table-prefix>: 테이블 이름의 접두사 또는 패턴을 지정하는 부분입니다. 여기에서 와일드카드 문자 '*'를 사용하여 특정 패턴을 가진 여러 테이블을 선택합니다.
* (Wildcard Character): 여러 테이블을 동시에 참조하기 위해 이름의 일부를 대체하는 문자입니다. 와일드카드 문자는 테이블 이름의 마지막 문자로만 사용될 수 있으며, 이를 통해 이름이 특정 패턴으로 시작하는 여러 테이블을 동시에 참조할 수 있습니다. '*'는 특수 문자로 간주하므로 와일드카드 테이블 이름을 백틱(`) 문자로 묶어야 합니다.
BigQuery의 Google Merchandise Store 데이터셋을 통해 예시를 확인해 보겠습니다. 이 데이터셋은 웹사이트 트래픽 소스, 콘텐츠 사용자 행동 및 거래 정보를 포함한 전자상거래 웹사이트의 일반적인 사용자 활동을 나타냅니다.
해당 데이터는 2016년 08월 01일부터 2017년 08월 01일까지 총 1년간의 일자별 테이블로 구성되어 있으며, 모두 "ga_sessions_”라는 prefix(접두어)를 공유합니다. 2017년 01월 01일의 테이블은 "bigquery-public-data.google_analytics_sample.ga_sessions_20170101"과 같이 표현할 수 있습니다.
이러한 테이블 그룹을 조회하기 위해 FROM 문에서 _TABLE_SUFFIX다음에 와일드카드 문자 '*'를 사용합니다.
Google Merchandise Store 데이터셋에서 2017년 1월 1일 자 테이블인 “ga_sessions_20170701”에서 방문자 ID, 날짜, 방문 횟수를 조회해 보겠습니다.
SELECT
fullVisitorId,
date,
visitNumber,
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_20170701`;
조회한 테이블의 최소 날짜와 최대 날짜를 추출해 보면 당연히 2017년 07월 01일인 것을 확인할 수 있습니다.
WITH GA AS (
SELECT
fullVisitorId,
date,
visitNumber,
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_20170101`
)
SELECT
MIN(date) AS min_date
, MAX(date) AS max_date
FROM GA;
이제 와일드카드 테이블을 사용해서 2017년 7월 모든 일자의 테이블을 한 번에 조회해 보겠습니다. 즉, FROM 절의 테이블 이름이 “ga_sessions_20170101”에서 “ga_sessions_201707*”로, 날짜 범위인 [1-31] 부분을 와일드카드 문자인 “*” 기호로 변경합니다. 조회한 테이블의 최소 날짜와 최대 날짜를 추출하면 2017년 7월 01일부터 2017년 7월 31일인 것을 확인할 수 있습니다.
WITH GA AS (
SELECT
fullVisitorId
, date
, visitNumber
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_201707*`
)
SELECT
MIN(date) AS min_date
, MAX(date) AS max_date
FROM GA;
아래의 예시에서는 2017년 7월 동안의 방문자("fullVisitorId")와 방문 횟수("visitCount")를 계산하고, 방문 횟수가 가장 많은 상위 10명의 방문자를 반환합니다.
SELECT
fullVisitorId
, COUNT(DISTINCT visitId) AS visitCount
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_201707*`
GROUP BY fullVisitorId
ORDER BY visitCount DESC
LIMIT 10;
와일드카드 테이블을 활용할 때는 여러 가지 주의해야 할 사항이 있습니다. 이 기능을 효과적으로 사용하기 위해서는 다음의 점들을 주의해야 합니다.
쿼리 범위 설정: 와일드카드를 사용할 때는 _TABLE_SUFFIX와 같은 필터를 사용하여 조회할 테이블의 범위를 명확하게 설정해야 합니다. 그렇지 않으면 예상치 못한 데이터양과 비용이 발생할 수 있습니다.
비용 관리: 와일드카드 쿼리는 많은 양의 데이터를 스캔할 수 있으므로 쿼리 비용이 상승할 수 있습니다. BigQuery의 가격 정책을 이해하고 쿼리 전에 예상 비용을 계산하는 것이 중요합니다.
성능 최적화: 가능한 한 필요한 데이터만 스캔하도록 쿼리를 정밀하게 조정합니다. 불필요한 데이터 스캔은 비용 증가뿐만 아니라 쿼리 성능 저하로도 이어질 수 있습니다.
패턴 일치: 와일드카드는 매우 유연하기 때문에 예상치 못한 테이블이 포함될 수 있습니다. 따라서 쿼리를 실행하기 전에 매칭되는 테이블 목록을 확인하는 것이 좋습니다.
11.2. 테이블 필터링
11.2.1. _TABLE_SUFFIX
BigQuery 와일드카드 테이블에서 _TABLE_SUFFIX는 쿼리가 참조하는 여러 테이블 중에서 특정한 테이블을 선별적으로 조회할 때 사용되는 가상의 컬럼입니다. 이 가상 컬럼을 활용하면 테이블의 접미사, 즉 와일드카드에 의해 동적으로 선택되는 테이블 이름의 일부를 기준으로 쿼리의 범위를 좁힐 수 있습니다. 또한, 자동으로 해당 범위 내의 테이블만을 스캔하게 되므로, 필요 없는 데이터를 스캔하여 발생하는 비용을 줄일 수 있습니다.
Google Merchandise Store 데이터셋에서 2017년 07월의 모든 테이블을 스캔하는 쿼리는 아래와 같습니다.
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_201707*`
해당 패턴에서 와일드카드 문자 ‘*’는 01부터 31까지의 범위에 있는 값이며, ”ga_sessions_20170701”부터 ”ga_sessions_20170731”까지를 나타냅니다. 하지만 7월 10일부터 7월 20일까지의 데이터만 검색하고 싶다면, _TABLE_SUFFIX를 사용하여 WHERE _TABLE_SUFFIX BETWEEN '10' AND '20' 과 같은 조건을 쿼리에 추가할 수 있습니다. 해당 WHERE 절과 조건을 추가하여 조회한 테이블의 최소 날짜와 최대 날짜를 추출하면 2017년 7월 10일부터 2017년 7월 20일까지인 것을 확인할 수 있습니다.
WITH GA AS (
SELECT
fullVisitorId,
date,
visitNumber,
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_201707*`
WHERE _TABLE_SUFFIX BETWEEN "10" AND "20"
)
SELECT
MIN(date) AS min_date
, MAX(date) AS max_date
FROM GA;
아래의 예시는 2017년 07월 10일에서 2017년 07월 20일 사이에 가장 많은 금액을 지불한 고객의 아이디와 금액을 출력합니다.
SELECT
fullVisitorId AS customer_id
, MAX(totals.totalTransactionRevenue) AS max_revenue
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_201707*`
WHERE _TABLE_SUFFIX BETWEEN '10' AND '20'
AND totals.transactions IS NOT NULL
GROUP BY customer_id
ORDER BY max_revenue DESC
LIMIT 1;
11.2.2. 모든 테이블 스캔
데이터셋의 모든 테이블을 스캔하려면 prefix(접두어)를 별도로 지정하지 않은 상태에서 와일드카드 테이블을 사용합니다. 즉, 테이블 이름의 시작 부분에 어떠한 특정 문자열이 없는 상태에서 와일드카드 문자 “*”를 사용합니다. 아래의 예시는 Google Merchandise Store 데이터셋의 모든 테이블을 스캔합니다.
FROM `bigquery-public-data.google_analytics_sample.*`
위의 예시처럼 prefix(접두어)를 사용하는 경우와 사용하지 않는 경우, 두 가지 방법으로 동일한 결과를 출력하는 쿼리를 비교하고자 합니다. 두 쿼리 모두 2017년 7월 10일에서 2017년 7월 20일 사이에 가장 많은 금액을 지불한 고객의 아이디와 금액을 출력합니다.
Prefix(접두어)를 사용하는 예시에서는 "ga_sessions_201707"와 같은 접두어를 사용하며, WHERE 절에서 _TABLE_SUFFIX BETWEEN '10' AND '20'와 같은 조건을 활용하여 해당 월의 여러 테이블을 선택합니다.
반면에 prefix(접두어)를 사용하지 않는 예시에서는 접두어를 따로 지정하지 않고, WHERE 절에서 _TABLE_SUFFIX BETWEEN 'ga_sessions_20170710' AND 'ga_sessions_20170720'와 같이 전체 테이블 이름을 사용하여 특정 날짜 범위의 데이터만 선택합니다.
💡
BigQuery 공식 문서에 따르면 긴 프리픽스가 짧은 프리픽스보다 일반적으로 성능이 우수합니다.
# Prefix 사용
SELECT
fullVisitorId AS customer_id
, MAX(totals.totalTransactionRevenue) AS max_revenue
FROM `bigquery-public-data.google_analytics_sample.ga_sessions_201707*`
WHERE _TABLE_SUFFIX BETWEEN '10' AND '20'
AND totals.transactions IS NOT NULL
GROUP BY customer_id
ORDER BY max_revenue DESC
LIMIT 1;
#-----------------------------------------------------------------------------
# Prefix 미사용 (빈 접두어를 사용하기 때문에 일반적으로 성능이 더 낮음)
SELECT
fullVisitorId AS customer_id
, MAX(totals.totalTransactionRevenue) AS max_revenue
FROM `bigquery-public-data.google_analytics_sample.*`
WHERE _TABLE_SUFFIX BETWEEN 'ga_sessions_20170710' AND 'ga_sessions_20170720'
AND totals.transactions IS NOT NULL
GROUP BY customer_id
ORDER BY max_revenue DESC
LIMIT 1;