Delta Lake Optimize
ํ์ฌ์์ Databricks๋ฅผ ํตํด Spark Cluster๋ฅผ ์ด์ํ๊ณ ์์ต๋๋ค. ๋ณธ ๊ธ์ Databricks๋ฅผ ๊ธฐ์ค์ผ๋ก ์์ฑํ์์ ๋ฏธ๋ฆฌ ๋ฐํ๋๋ค.
Compaction
Parquet ํ ์ด๋ธ์ ์ฟผ๋ฆฌ ์๊ฐ์ ํ ์ด๋ธ์ ์ฌ์ด์ฆ์๋ ์ํฅ์ ๋ฐ์ง๋ง, ํ ์ด๋ธ์ด ์ผ๋ง๋ ์๊ฒ ์ชผ๊ฐ์ด์ ธ ์๋์ง์๋ ์ํฅ์ ๋ฐ๋๋ค. ์๋ฅผ ๋ค์ด, ์์ ํฌ๊ธฐ์ Parquet ํ์ผ ๋ช ์ฒ๊ฐ๋ก ๊ตฌ์ฑ ๋์ด ์๋ ๊ฒฝ์ฐ๋ผ๋ฉด ์ฟผ๋ฆฌ๊ฐ ๋๋ ๊ฒ์ ๊ฐ๋ฅํ์ง๋ง, ์ฟผ๋ฆฌ๊ฐ ๋งค์ฐ ๋๋ฆฌ๊ฒ ์คํ๋๋ค๊ณ ํ๋ค. ์ด๊ฒ์ ํ๋์ ํ ์ด๋ธ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด ์ํด์ ๋ง์ ๊ฐฏ์์ ํ์ผ์ ๋ฆฌ์คํ (listing)ํ๊ณ , ๋ ๋ง์ ํ์ผ์ ์ด์๋ค ๋ซ์๋ค ํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ค๋ฒํค๋๊ฐ ๋ฐ์ํ๋ค. Delta Lake์ ๊ณต์ ๋ธ๋ก๊ทธ์์๋ ์ด๊ฒ์ โthe Small File Problemโ๋ผ๊ณ ๋ถ๋ฅธ๋ค.
์ค์ ๋ก 30๋ง ๊ฑด ์ ๋ ๋๋ ํ ์ด๋ธ์ 1000๊ฐ์ parquet ํ์ผ๋ก repartition ํ์ฌ ์ ์ฅํ์ฌ ๋น๊ตํด๋ณด๋ ์๋์ ๊ฐ์ ์ฐจ์ด๊ฐ ์์๋ค.
rows | repartition | size | query time |
---|---|---|---|
30๋ง | 8 | 73 MB | 9 sec |
30๋ง | 1000 | 100 MB | 42 sec |
1000๊ฐ์ Parquet ํ์ผ๋ก ๋๋ ์ง ๊ฒฝ์ฐ๊ฐ ์ฟผ๋ฆฌ ์๋๋ ๋๋ฆฌ๊ณ , ๋ฐ์ดํฐ ํฌ๊ธฐ๋ ๋ ํฐ ๋ชจ์ต์ ๋ณผ ์ ์๋ค.
์ด๋ฐ Parquet ์กฐ๊ฐ ๋ฌธ์ ๋ฅผ ์ฝ๊ฒ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ์๊ฒ ์ชผ๊ฐ์ง Parquet ํ์ผ์ ํ๋์ ํฐ ํ์ผ๋ก ๋ณํฉํ๋ โCompactionโ ์์
์ ํด์ฃผ๋ฉฐ๋ฉด ๋๋ค. Delta์ OPTIMIZE
๋ช
๋ น์ด๋ ์์ ํฌ๊ธฐ์ ํ์ผ์ ๋ํ Compaction์ ์ํํ๋ค.
ย | rows | repartition | size | query time |
---|---|---|---|---|
Compaction ์ | 30๋ง | 1000 | 100 MB | 42 sec |
Compaction ํ | 30๋ง | 1 | 73 MB | 15 sec |
Compaction ์์
์ด ํ์ผ๋ค์ ์ผ๋งํผ ๋ณํฉํ ์ง๋ spark ์ต์
์ค, spark.databricks.delta.optimize.maxFileSize
์ ์ํด ๊ฒฐ์ ๋๋ค. ๊ธฐ๋ณธ๊ฐ์ 1 GB
๋ก ์ธํ
๋์ด ์๋ค. ๊ทธ๋์ ์์ ์คํ์์ 1000๊ฐ๋ก ๋๋ ์ง Parquet ํ์ผ์ด ํ๋์ Parquet ํ์ผ๋ก ๋ณํฉ๋ ๊ฒ์ด๋ค. (Delta Lake๋ ๋ถ๋ช
์คํ์์ค์ธ๋ฐ spark.databricks.
๋ผ๊ณ ์ ํ์๊ตฌ๋จผโฆ?) Delta์ compaction ์์
์ ํ์ผ ์ฌ์ด์ฆ๋ฅผ evenly-balanced ํ๊ฒ ๋ถ๋ฐฐํ๋ค๊ณ ํ๋ค. ๋ง์ฝ ๋ฐ์ดํฐ ํฌ๊ธฐ๊ฐ 1.2 GB
์๋ค๋ฉด, ์์ maxFileSize
์ ๋ฐ๋ผ 1 GB
์ 0.2 GB
์ ํ์ผ๋ก ๋๋๋๊ฒ ์๋๋ผ 0.6 GB
ํ์ผ 2๊ฐ๋ก ์์ถ ๋๋ค.
Delta์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ํ์๋ ๋ชจ๋ Snapshot Isolation์ผ๋ก ๊ฒฉ๋ฆฌ ๋์ด ์๊ธฐ ๋๋ฌธ์, ๋๊ตฐ๊ฐ๊ฐ Delta Lake์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ๋์ค์ OPTIMIZE
์์
์ด ์ผ์ด๋๋, ๋๋ OPTIMIZE
๋์ค์ ๋๊ตฐ๊ฐ๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ฝ๋๋ผ๋ ์์
์ด ์ค๋จ๋์ง ์๊ณ ๋๋ค ๋์์ ์ํ ๋ ์ ์๋ค.
Delta์ Compaction ์์
์ ๋ฉฑ๋ฑ์ฑ(idempotent)์ ๊ฐ์ง๋ค. ๋ฐ๋ผ์ ๊ฐ์ ๊ฒฝ๋ก, ๊ฐ์ ํ
์ด๋ธ์ ๋ํด ๋ ๋ฒ ์ด์ OPTIMIZE
์ฐ์ฐ์ ์คํํ๋๋ผ๋ ๋ฐ์ดํฐ๋ ์ํฅ์ด ์๋ค. ์ฌ์ค 2nd optimize ์์
๋ถํฐ๋ ์๋ฌด๋ฐ ์ต์ ํ๊ฐ ์ด๋ค์ง์ง ์๋๋ค.
If there are only a few small files, then you donโt need to run
OPTIMIZE
. The small file overhead only starts to become a performance issue where there are lots of small files. You also donโt need to runOPTIMIZE
on data thatโs already been compacted. If you have an incremental update job, make sure to specify predicates to only compact the newly added data.
Delta์ ๊ณต์ ๋ธ๋ก๊ทธ์์๋ โthe Small File Problemโ์ด ๋ฐ์ํด์ ์ฟผ๋ฆฌ ํผํฌ๋จผ์ค์ ๋ฌธ์ ๊ฐ ์๊ธฐ๋๊ฒ ์๋๋ผ๋ฉด, ๊ตณ์ด OPTIMIZE
๋ฅผ ์์ฃผ ๋๋ฆด ํ์ ์๋ค๊ณ ํ๋ค. ๋ง์ฝ ๋ฐ์ดํฐ๊ฐ ์ด๋ฏธ ์ถฉ๋ถํ ์์ถ๋ ์ํฉ์ด๋ผ๋ฉด OPTIMIZE
์ ํ ํฐ ์ฐจ์ด๊ฐ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๋, ๋ฐ์ดํฐ๊ฐ ์ฆ๋ถ(incremental)ํ๊ฒ ์ถ๊ฐ๋๋ ๊ฒฝ์ฐ์๋ ์ ์ฒด ๋ฒ์์ ๋ํด ์์ถํ ํ์ ์๊ณ , ์๋์ ๊ฐ์ด ๋ฒ์๋ฅผ ์ง์ ํด์ ์์ถํ๋ ๊ฑธ ๊ถ์ฅํ๋ค.
OPTIMIZE <TABLE_NAME> WHERE `date` >= '2024-01-01'
Auto Compaction
Delta Lake์ ๋ฐ์ดํฐ๋ฅผ ์ฐ๋ ์์ ์ด ์ฑ๊ณตํ๋ฉด, ๋ฐ๋ก ์งํ์ Compaction์ ์ํํด์ฃผ๋ ์ต์ ์ด๋ค. Auto-compaction์ ์ด์ ์ ์์ถ๋ ์ ์ด ์๋ ํ์ผ์ ๋ํด์๋ง ์ํ๋๋ค๊ณ ํ๋ค.
๋ง์ฝ ๋งค๋ฒ ์ฐ๊ธฐ ์์
๋ง๋ค Compaction ์์
์ด ์ผ์ด๋๋ค๋ฉด, ์ฐ๊ธฐ ์์
์ด ๋๋ ค์ง ์๋ ์์ผ๋ฏ๋ก ํ์ผ์ด ์ผ๋งํผ ์์ฌ์ผ Auto-compaction์ ์ํํ ์ง ๊ฒฐ์ ํ ์ ์๋ค. Spark์ spark.databricks.delta.autoCompact.minNumFiles
์ต์
์ ํตํด ๋น๋๋ฅผ ์กฐ์ ํ ์ ์์ผ๋ฉฐ, ๊ธฐ๋ณธ๊ฐ์ 50
์ด๋ค.
๊ธฐ๋ฅ์ ํ์ฑํ ์ํค๋ ๋ฐฉ๋ฒ์ 2๊ฐ์ง ์ธ๋ฐ, Spark Session Config๋ก๋ ํ ์ ์๊ณ , Table Property๋ก๋ ์ ์ดํ ์ ์๋ค.
- Table Property:
delta.autoOptimize.autoCompact
- SparkSession Config:
spark.databricks.delta.autoCompact.enabled
Data Skipping
Delta Lake์์ ์ฟผ๋ฆฌ ์๋ ํฅ์์ ์ํด ์ฟผ๋ฆฌ์ WHERE
์กฐ๊ฑด์ ๋ฐ๋ผ ์ฝ์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ณ ๋๋ ์คํต ํ๋ ๋ก์ง์ด ๊ตฌํ๋์ด ์์ด ์ด๋ค ์ฟผ๋ฆฌ์์๋ Parquet ํ์ผ์์ ์ฟผ๋ฆฌํ๋ ๊ฒ๋ณด๋ค ๋ ๋น ๋ฅด๊ฒ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ ์ ์๋ค.
Delta Statistics Columns
Delta์ Data skpping ์ ๋ณด๋ Delta ํ ์ด๋ธ์ ๋ฐ์ดํฐ ์ฐ๊ธฐ ์์ ์ ํ ๋ ์๋์ผ๋ก ์์งํ๋ค. ์ด ์ ๋ณด์๋ ์๋ ๋ด์ฉ๋ค์ด ๋ด๊ฒจ ์๋๋ฐ
- min/max values per columns
- null counts per columns
- total records
์ด๋ฐ ํต๊ณ ์ ๋ณด๋ _delta_log/
์ ํด๋น ๋ฒ์ ์ฐ๊ธฐ์ ๋ก๊ทธ ํ์ผ์ ์๋ก ์ถ๊ฐ๋๋ Parquet ํ์ผ ๋ณ๋ก ๋ด๊ฒจ์ ์ ์ฅ ๋๋ค. ์๋ฅผ ๋ค์ด, ์ฐ๊ธฐ ๋ฒ์ ์ด 4
๋ฒ์ ์ด์๋ค๋ฉด, _delta_log/000...0004.json
ํ์ผ์ ์๋์ ๊ฐ์ด ๊ธฐ๋ก๋๋ค.
// https://delta-io.github.io/delta-rs/how-delta-lake-works/architecture-of-delta-table/
{
"add": {
"path": "2-95ef2108-480c-4b89-96f0-ff9185dab9ad-0.parquet",
"size": 2204,
"partitionValues": {},
"modificationTime": 1701740465102,
"dataChange": true,
"stats": "{
\"numRecords\": 2,
\"minValues\": {\"num\": 11, \"letter\": \"aa\"},
\"maxValues\": {\"num\": 22, \"letter\": \"bb\"},
\"nullCount\": {\"num\": 0, \"letter\": 0}
}"
}
}
{
"remove": {
"path": "0-62dffa23-bbe1-4496-8fb5-bff6724dc677-0.parquet",
"deletionTimestamp": 1701740465102,
"dataChange": true,
"extendedFileMetadata": false,
"partitionValues": {},
"size": 2208
}
}
{
"commitInfo": {
"timestamp": 1701740465102,
"operation": "WRITE",
"operationParameters": {
"mode": "Overwrite",
"partitionBy": "[]"
},
"clientVersion": "delta-rs.0.17.0"
}
}
๊ฐ์ ๋ณด๋ฉด, add
์ฐ์ฐ์ ๋ํ ๋ถ๋ถ์ stats
ํ๋์ numRecords
, minValues
, maxValues
, nullCount
์ ๋ํ ์ ๋ณด๊ฐ ๋ด๊ฒจ ์๋ค. ์ด๋ฐ ์ ๋ณด๋ค์ ํ์ฉํด Delta๋ Parquet์์ ์ฟผ๋ฆฌํ๋ ๊ฒ๋ณด๋ค ๋ ๋น ๋ฅด๊ฒ ๊ฐ์ ์กฐํํ๊ณ ๋ฐํํด์ค๋ค.
์๋ฅผ ๋ค์ด, ์ ์ฒด ๋ฒ์์ ๋ํ ํ ๊ฐฏ์๋ฅผ ํ์
ํ๋ SELECT COUNT(*) FROM <TABLE_NAME>
๊ฐ์ ์ฟผ๋ฆฌ๋ฅผ ์ํํ๋ค๋ฉด, delta๊ฐ ์ฝ๋ ๊ฐ Parquet ํ์ผ๋ค์ ๋ํด ๊ธฐ๋กํ stats
์ numRecords
๊ฐ๋ง ๋ชจ๋ ๋ํด์ฃผ๋ฉด ๋๋ค. ์ฆ, Parquet ํ์ผ์ ์๋ณธ์ ์ ํ ๋ค์ฌ๋ค ๋ณผ ํ์๊ฐ ์๋ ๊ฒ์ด๋ค.
๋จ, ์ด๋ฐ ํต๊ณ ์ ๋ณด๋ฅผ ๊ณ์ฐํ๋ ๊ฒ์ Parquet์์์ ์ฐ๊ธฐ ์์ ๊ณผ ๋น๊ตํด ์ค๋ฒํค๋๊ฐ ๋ฐ์ํ๋ค. ๋, min/max๋ฅผ ๊ณ์ฐํ๊ธฐ ๋ถ๋ด์ค๋ฌ์ด ๋ฐ์ดํฐ ํ์ ๋ค(์๋ฅผ ๋ค๋ฉด textual ๋ฐ์ดํฐ)์ ์ด๋ฐ ํต๊ณ ์ ๋ณด๋ฅผ ๊ณ์ฐํ์ง ์๋๋ก ํ๊ณ ์ถ์ ์๋ ์๋ค. ๊ทธ๋ด ๊ฒฝ์ฐ ์๋์ ๋ Spark Session Config๋ฅผ ํ์ฉํ์.
spark.databricks.delta.properties.defaults.dataSkippingNumIndexedCols
spark.databricks.delta.properties.defaults.dataSkippingStatsColumns
dataSkippingNumIndexedCols
๊ฐ์๋ stats๋ฅผ ์์งํ ์ปฌ๋ผ ๊ฐฏ์๋ฅผ ์ ๋๋ค. ๊ธฐ๋ณธ๊ฐ์ 32
๋ก ์ฒซ 32๊ฐ ์ปฌ๋ผ์ ๋ํด์ stats๋ฅผ ๊ณ์ฐํ๋ค. ๋ง์ฝ -1
์ ์ ์ด์ฃผ๋ฉด ๋ชจ๋ ์ปฌ๋ผ์ ๋ํด stats ์ ๋ณด๋ฅผ ์์งํ๋ค.
dataSkippingStatsColumns
๋ stats๋ฅผ ์์งํ ์ปฌ๋ผ ์ด๋ฆ์ comma-separated๋ก ์ ์ด์ค๋ค.
๋๋ Table Property๋ก๋ ์ ์ดํ ์ ์๋๋ฐ ์๋์ ๋ ์์ฑ์ผ๋ก ์ง์ ํ ์ ์์ผ๋ฉฐ, ์์ Spark Session Config์ ๊ธฐ๋ฅ์ ์ผ๋ก ๋์ํ๋ค.
delta.dataSkippingNumIndexedCols
delta.dataSkippingStatsColumns
Get Column Statistics
Delta ์ฐ๊ธฐ์์ ์์งํ ์ปฌ๋ผ์ Stats ์ ๋ณด๋ ์๋์ ์ฟผ๋ฆฌ๋ฅผ ํตํด์ ํ์ธํ ์ ์๋ค.
> DESC EXTENDED <TABLE_NAME> <COLUMN_NAME>
info_name info_value
-------------- ----------
col_name name
data_type string
comment NULL
min NULL
max NULL
num_nulls 0
distinct_count 2
avg_col_len 4
max_col_len 4
histogram NULL
Z-Ordering
Delta์ ๊ฒฝ์ฐ OPTIMIZE
๋ฅผ ์ํํ ๋, ZORDER BY
๋ผ๋ ์ (clause)๋ฅผ ์ถ๊ฐํ์ฌ Parquet ํํฐ์
์ ๋ฐ์ดํฐ๊ฐ ์ ๋ ฌ๋๋ ์์๋ฅผ ๊ฒฐ์ ํ ์ ์๋ค. ์์๋ฅผ ํตํด ์ข๋ ์ดํด๋ณด์.
// https://delta.io/blog/2023-06-03-delta-lake-z-order/
+-----+-----+------------+---+---+------+---+---+---------+
| id1| id2| id3|id4|id5| id6| v1| v2| v3|
+-----+-----+------------+---+---+------+---+---+---------+
|id016|id046|id0000109363| 88| 13|146094| 4| 6|18.837686|
|id039|id087|id0000466766| 14| 30|111330| 4| 14|46.797328|
|id095|id078|id0000584803| 56| 92|213320| 1| 9|63.464315|
+-----+-----+------------+---+---+------+---+---+---------+
์๋ฅผ ๋ค์ด ์์ ๊ฐ์ ํ์์ ๋ฐ์ดํฐ๊ฐ 1๋ฐฑ๋ง ํ ์ ๋ ๋๋ค๊ณ ๊ฐ์ ํด๋ณด์. ์ด๋ฐ ๋ฐ์ดํฐ์ id1
์ปฌ๋ผ์ ํน์ ๊ฐ์ ๊ธฐ์ค์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ฝ์ ์ฟผ๋ฆฌ๋ฅผ ๋๋ฆฌ๊ณ ์ ํ๋ค.
SELECT
COUNT(*)
FROM
<TABLE_NAME>
WHERE
id1 = 'id016'
๋ง์ฝ ํ
์ด๋ธ์ด 100๊ฐ์ Parquet ํ์ผ๋ก ํํฐ์
๋ ๋์ด ์๊ณ , ๋ id1='id016'
๋ผ๋ ๊ฒ์ด 100๊ฐ ํ์ผ ์ด๊ณณ์ ๊ณณ์ ํฉ์ด์ง ์ํฉ์ด๋ผ๋ฉด, ์์ ์ฟผ๋ฆฌ๋ 100๊ฐ์ Parquet ํ์ผ์ ๋ชจ๋ ํ์ํ ๊ฒ์ด๋ค.
๊ทธ๋ฐ๋ฐ, ๋ง์ฝ 100๊ฐ์ Parquet์ ๋ฐ์ดํฐ๊ฐ id1
์ปฌ๋ผ์ ๊ธฐ์ค์ผ๋ก ์ ๋ ฌ๋์ด ์ ์ฅ๋์ด์ ์ด ์ข๊ฒ id1='id016'
์ ๋ฐ์ดํฐ๋ฅผ ํ๋์ Parquet ํ์ผ์ ๋ชจ์ ์ ์๋ค๋ฉด, ๊ทธ๋ฐ ์ํฉ์์ ์์ ์ฟผ๋ฆฌ๋ ์ค์ง ํ๋์ Parquet ํ์ผ๋ง์ ํ์ํ ๊ฒ์ด๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ Parquet ํ์ผ์ ๋ํ Delta Stats๋ ์๋์ ๊ฐ์ด ๊ธฐ๋ก๋ ๊ฒ์ด๋ค.
์ฆ, ๋น์ทํ ์ฑ์ง์ ๋ฐ์ดํฐ๋ฅผ (์ฌ๊ธฐ์๋ ๊ฐ์ id๋ฅผ ๊ฐ์ง) ๋ฐ์ดํฐ๋ฅผ ํ๋์ ํ์ผ์ ๋ฌถ์ด ์ง์ญ์ฑ(Locality)๋ฅผ ๊ฐ์ถ๋๋ก ๋ง๋๋ ์ต์ ํ ํ ํฌ๋์ด๋ค.
์ด๋ ๊ฒ Delta๋ฅผ ๊ตฌ์ฑํ๋ Parquet ํํฐ์
์ ํน์ ์ปฌ๋ผ์ ์ ๋ ฌํด ์ ์ฅํ๋ ๋ฐฉ๋ฒ์ Z-Ordering์ผ๋ก ์ํํ ์ ์๋ค. ํด๋น ์์
์ OPTIMIZE
์์
๊ณผ ํจ๊ป ์ํ๋๋ฉฐ ์๋์ ๊ฐ์ ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
OPTIMIZE <TABLE_NAME> ZORDER BY id1
Delta์ ๋ธ๋ก๊ทธ ์ํฐํด์ ๋ณด๋ฉด, ํ์คํ Z-Ordering์ ์ค ์ปฌ๋ผ์ ๋ํ ์ฟผ๋ฆฌ๊ฐ ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ๋ณด๋ค ํจ์ฌ ํฐ ํฅ์์ ๋ณด์ด๋ ๊ฑธ ๋ณผ ์ ์๋ค.
Z-Ordering์ ๋์ ์ด์์ ์ปฌ๋ผ์ ๋ํด์๋ ์ํํ ์ ์๋ค. ํ์ง๋ง, Z-Ordering ์ปฌ๋ผ ์๊ฐ ๋ง์์ง์๋ก ์ฌ๋ฌ ์ปฌ๋ผ์ ๋ํด ์ข๋ ๋น ๋ฅธ ์ฟผ๋ฆฌ๋ฅผ ์ป๊ฒ ์ง๋ง, ๊ทธ๋งํผ OPTIMIZE
๊ณผ์ ์์ ๋ฐ์ดํฐ ์ ๋ ฌ์ด ๋ ํ์ํ๊ณ , ๋, ๋ฐ์ดํฐ์ ์ง์ญ์ฑ์ผ๋ก ์ป๋ ์ด์ ์ด ์ ํ๋ ์๋ ์๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ํด๋น ๋ฐ์ดํฐ๋ฅผ ์ฟผ๋ฆฌํ๋ ํจํด์ ๋ฉด๋ฐํ ๋ถ์ํ๊ณ , ๊ทธ์ ๋ง์ถฐ Z-Orderingํ ์ปฌ๋ผ์ ๊ฒฐ์ ํ๋ ๊ฒ์ด ์ค์ํ๋ค.
๋ํ ์ด๋ฐ Z-ordering์ ๊ธฐ๋ฐํ ํํฐ์
์ ์ ์ฒด ๋ฐ์ดํฐ๊ฐ 1 TB
์ดํ, ํํฐ์
๋ณ ๋ฐ์ดํฐ๊ฐ 1 GB
์ดํ๋ผ๋ฉด ๋ณ๋ก ์ถ์ฒํ์ง ์๋๋ค๋ ๋ด์ฉ๋ Delta ๋ธ๋ก๊ทธ ํฌ์คํธ์ ๊ธฐ์ ๋์ด ์๋ค.
You should not be partitioning tables under one terabyte in general. You also shouldnโt partition by a column that will have partitions with less than 1 GB of data.
Compare to Hive-style partitioning
Delta์ Z-Ordering๊ณผ Hive-style partitioning ๋๋ค ๋น์ทํ ์ข ๋ฅ์ ๋ฐ์ดํฐ๋ฅผ ํ๋์ ํ์ผ ํ๋์ ํ์ผ ์ฒญํฌ๋ก ๋ฌถ๊ธฐ ์ํ ํ ํฌ๋์ด๋ค. ์ด๋ฅผ ํตํด ํน์ ์ฟผ๋ฆฌ๋ฅผ ์ํํ ๋, ์ ์ฒด ๋ฐ์ดํฐ๊ฐ ์๋ ์ผ๋ถ ๋ฐ์ดํฐ๋ง ์ฝ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ ์ ์๋ค.
๋จ, ์ฐจ์ด์ ์ ๋ฌผ๋ฆฌ์ ์ธ ๊ตฌ์กฐ์ ์๋ค. Hive-style partitioning์ ๋น์ทํ ์ข ๋ฅ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ๋๋ ํ ๋ฆฌ(directory)์ ๋ฐฐ์นํ๋ค. ๊ทธ๋ฌ๋, Delta์ Z-Ordering์ ๋น์ทํ ๋ฐ์ดํฐ๋ฅผ ๋๋ ํ ๋ฆฌ ๋ถ๋ฆฌ ์์ด ํ๋์ ๋๋ ํ ๋ฆฌ์ ๋ค๋ฅธ ์ข ๋ฅ์ ๋ฐ์ดํฐ์ ํจ๊ป ๋ชจ๋ ๋ฐฐ์นํ๋ค.
Partition ๋ผ๋ฆฌ ์๋ฒฝํ๊ฒ ๋ถ๋ฆฌํ๋ Hive-style์ด ์ด๋ค ๋๋ ๊ฐ์ ์ ๊ฐ์ง ์ ์๋ค. ๊ทธ๋ฌ๋ ๋๋ ํ ๋ฆฌ ๋ถ๋ฆฌ๋ฅผ ์ฑ ์์ด ๋ฐ๋ฅด๋๋ฐ, ๋ง์ฝ ํํฐ์ ์ปฌ๋ผ์ ๋๋ฌด ๋ง์ Distinct ๊ฐ๋ค์ด ์์ ๋๋ ํํฐ์ ๋๋ ํ ๋ฆฌ๊ฐ ๋-๋ฌด ๋ง์ด ์๊ธธ ๊ฒ์ด๊ณ , ํํฐ์ ์ปฌ๋ผ์ ํ๋ฒ ์ง์ ํ๋ฉด ๊ทธ๊ฒ์ ๋ฐ๊พธ๊ธฐ๋ ์ ๋ง ์ด๋ ต๊ณ , ๋ ํํฐ์ ์ปฌ๋ผ์ ์ฌ๋ฌ ๊ฐ ์ง์ ํ๋ฉด ๊ทธ๋งํผ ํํฐ์ ๋๋ ํ ๋ฆฌ์ ๊น์ด(depth)๊ฐ ๊น์ด์ง๋ค.
๋จ, Z-Ordering๊ณผ Hive-style Partition์ ๋ฒ ํ์ ์ธ ์กด์ฌ๊ฐ ์๋๋ค. Delta์์๋ Hive-style Partitioning์ ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
Analyze
์์์ Delta๋ ์ฐ๊ธฐ ์์
์ ์๋์ผ๋ก ์ปฌ๋ผ์ Stats ์ ๋ณด๋ฅผ ์์งํ๋ค๊ณ ํ์๋ค. ๊ทธ๋ฐ๋ฐ, ์ด๊ฒ์ ์ง์ ์ฟผ๋ฆฌ๋ฅผ ์คํํด ์ํํ ์ ์์ผ๋ ๊ทธ๊ฒ์ด ANALYZE
๋ช
๋ น์ด๋ค.
-- need DBR 14.x above
ANALYZE TABLE <TABLE_NAME> COMPUTE DELTA STATISTICS
Delta์ ์ต์ ๋ฒ์ ์ด ๊ฐ๋ฆฌํค๋ Parquet ํ์ผ๋ค์ ๋ชจ๋ ์ฝ์ด์ Stats ์ ๋ณด๋ฅผ ๋ค์ ๊ณ์ฐํ๋ค. Stats ์ ๋ณด๋ฅผ ๋ค์ ๊ณ์ฐํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ _delta_log/
์ ์ปค๋ฐ๋ ์๋ก ์์ฑ๋๋ฉฐ, COMPUTE STATS
๋ผ๋ ์ฐ์ฐ์ผ๋ก ๊ธฐ๋ก๋๋ค. ๋จ, ์๋ก์ด Parquet ํ์ผ์ด ์๊ธฐ๊ฑฐ๋ ์ญ์ ๋๋ ๊ฒ์ ์๋๋ค.
๊ทธ์ธ์๋ ๋ช๊ฐ์ง ์ต์
๊ณผ ํจ๊ป ANALYZE
๋ฅผ ์ํํ ์ ์๋๋ฐ,
ANALYZE ... COMPUTE STATISTICS NOSCAN
- Delta ํ ์ด๋ธ์ ์ฌ์ด์ฆ๋ง ์๋ก ๊ณ์ฐํ๋ค.
ANALYZE ... COMPUTE STATISTICS FOR COLUMNS ...
- ์ผ๋ถ ์ปฌ๋ผ์ ๋ํด์ Stats ์ ๋ณด ๋ค์ ๊ฒ์ฐ
ANALYZE ... COMPUTE STATISTICS FOR ALL COLUMNS
- ์ ์ฒด ์ปฌ๋ผ์ ๋ํด์ Stats ์ ๋ณด ๋ค์ ๊ณ์ฐ
์ ํ์ํ๊ฐ??
์ฌ์ค Delta ์ฐ๊ธฐ ๋๋ง๋ค Stats ์ ๋ณด๋ฅผ ์์งํ๊ณ , ๋ OPTIMIZE ZORDER
๋๋ Stats ๋ฐ์ดํฐ๋ฅผ ๊ณ์ฐํ ํ
๋ฐ ANALYZE
๋ช
๋ น์ด๊ฐ ๊ผญ ํ์ํ ๊ฑธ๊น?? ์ด ๋ช
๋ น์ด๋ฅผ ์ธ์ ์คํํด์ค์ผ ํ๋ ๊ฑธ๊น??
์ด๊ฒ์ ๊ณณ ์ฐพ์๋ณด๋ Databricks Community์ ์ด๋ฐ ๋ต๋ณ์ด ์์๋ค: โWhatโs the best practice on running ANALYZE on Delta Tables for query performance optimization?โ
ANALYZE
whenever the data has changed by about 10%- Make sure when you use
ANALYZE
, you are specifying theCOLUMNS
orPARTITIONS
you want to collect statistics for. Otherwise, as you have noted, it will re-analyze the entire table
์ํผ ํ ์ด๋ธ์ ๋ฐ์ดํฐ ๋ณํ ์ข(ex: 10%) ์์๋ค๊ฑฐ๋ Stats ์ ๋ณด ์์ง ์์ฒด๋ฅผ ์๋์ผ๋ก ์ปจํธ๋กค ํ๊ณ ์ถ์ ๋, Stats ์์ง์ Delta ์ฐ๊ธฐ์ ๋ณ๋๋ก ์ํํ๊ณ ์ถ์ ์ฉ๋๋ก ๋ช ๋ น์ด๊ฐ ๋ถ๋ฆฌ๋๊ฒ ์๋๊น ์ถ๋ค.
Write Performance Compare
Delta์ ๊ฒฝ์ฐ ์ฐ๊ธฐ ์์ ์ ํ ๋๋ง๋ค Stats ๋ฐ์ดํฐ๋ฅผ ์์งํ๋ค. ์ด๊ฒ์ Parquet ์ฐ๊ธฐ ์์ ์์ ์๋ ์ถ๊ฐ์ ์ธ ์์ ์ด๋ค. ์ด๋ฐ Stats๊ฐ ๋ช๋ช ๋ฐ์ดํฐ ์ฝ๊ธฐ ์ฟผ๋ฆฌ๋ฅผ ํ์คํ ๋์์ด ๋๊ฒ ์ง๋ง, ๊ณผ์ฐ ๋ฐ์ดํฐ ์ฐ๊ธฐ ๋ Stats ์ ๋ณด ์์ง ๋๋ฌธ์ ์๊ธฐ๋ ์ค๋ฒํค๋๋ก ์ฐ๊ธฐ ํผํฌ๋จผ์ค๊ฐ ๋จ์ด์ง๋๊ฒ ์๋์ง ๊ฑฑ์ ์ด ๋์๋ค.
Databricks์์ ์ถ์ํ 2020๋ ์ โDelta Lake: High-Performance ACID Table Storage over Cloud Object Storesโ ๋ ผ๋ฌธ์ ๋ฐ๋ฅด๋ฉด, Delta ์ฐ๊ธฐ์ ๊ฒฝ์ฐ Stats ์์ง์ด ์์ง๋ง, ๊ทธ ์ค๋ฒํค๋๊ฐ Parquet ์ฐ๊ธฐ์ ๋น๊ตํด ๋ฏธ๋ฏธํ ์์ค์ด๋ผ๊ณ ํ๋ค. ์๋๋ ๋ ผ๋ฌธ์ ํด๋น ๋ฌธ๋จ์ ๋ด์ฉ์ ๋ฐ์ท๋ค.
We also evaluated the performance of loading a large dataset into Delta Lake as opposed to Parquet to test whether Deltaโs statistics collection adds significant overhead. Figure 7 shows the time to load a 400 GB TPC-DS store_sales
table, initially formatted as CSV,
on a cluster with one i3.2xlarge
master and eight i3.2xlarge
workers (with results averaged over 3 runs). Sparkโs performance writing to Delta Lake is similar to writing to Parquet, showing that statistics collection does not add a significant overhead over the other data loading work.
๋งบ์๋ง
Delta์ Data Skipping ๊ธฐ๋ฒ์ SELECT * FROM <TABLE_NAME>
์ผ๋ก ์ ์ฒด ๋ฐ์ดํฐ๋ฅผ ์กฐํํ๋ค๋ฉด ๋ฌด์ฉ์ง๋ฌผ ์ผ ์๋ ์๋ค. ๊ทธ๋ฌ๋ ์ธ์์ ๋ชจ๋ ์ฟผ๋ฆฌ๊ฐ Full Scan ์ฟผ๋ฆฌ๊ฐ ์๋ ๊ฒ์ด๊ณ , ๊ทธ๋ฐ ํน์ ์ฟผ๋ฆฌ์ ๋ํด์ ์ด๋ป๊ฒ ํผํฌ๋จผ์ค๋ฅผ ํฅ์ ์ํฌ์ง ๊ณ ๋ฏผํ๋๊ฒ Delta Lake๋ฅผ ๋์
ํ ์ธ์์ ๋ฐ์ดํฐ ์์ง๋์ด๊ฐ ํด์ผ ํ ์ผ์ธ ๊ฒ ๊ฐ๋ค.
์ด๋ค ํ๋ ์์ํฌ๋ฅผ ๊น๊ฒ ๊ณต๋ถํ๋ ๊ฑด, ๊ทธ ํ๋ ์์ํฌ์ ๋ํ ์ ๋ฌธ์ฑ์ ๊ฐ์ถ๋ ๊ฒ ๋ฟ๋ง ์๋๋ผ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๊ทธ๊ฒ์ด ์ฑํํ ๊ธฐ์ ๋ ํจ๊ป ๊ณต๋ถํ๊ฒ ๋๋ ๊ฒ ๊ฐ๋ค. ์ข ์ข โ๋จ์ฝ ๋ด๊ฐ ๋๊ท๋ชจ ๋ถ์ฐ์ฒ๋ฆฌ ์์คํ ์ ๋ค์ ์ค๊ณ ํ๋ค๋ฉด?โ ๊ฐ์ ๋ฌผ์์ ๋๋์ด๋ฉฐ ๊ทธ๋ฐ ์๊ฐ์ด ์์ ๋ ์ด๋ค ํ ํฌ๋๋ค์ ์จ์ผ ํ๋์ง ์ตํ๋ ๊ณผ์ ์ด๋ผ๊ณ ์๊ฐํ๋ค. ๋, ์ด๋ค ๊ธฐ์ ์ ์ธ ์ธ๋ถ์ฌํญ ๋ณด๋ค๋ ๊ทธ ํ ํฌ๋์ด ๋ฌธ์ ๋ฅผ ํฉ๋ฆฌ์ ์ผ๋ก ์ ๊ทผํ๊ณ , ์ค๊ณ๋์๋์ง๋ฅผ ๊ณ ๋ฏผํ๋ ๊ฒ ์์ฒด๊ฐ ๊ฐ์น ์๋ ์๊ฐ๋ค์ธ ๊ฒ ๊ฐ๋ค.
Reference
- Databricks
- Delta Lake
- Delta Lake Official Blog