Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HIVE-28793: Expire query history snapshots #5666

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

abstractdog
Copy link
Contributor

@abstractdog abstractdog commented Mar 1, 2025

What changes were proposed in this pull request?

Introduce a periodic snapshot expiry for query history iceberg table.

Why are the changes needed?

To expire snapshots to delete data files that are no longer needed, and to reduce the size of table metadata. Each write to an Iceberg table from Hive creates a new snapshot, or version, of a table. Snapshots can be used for time-travel queries, or for rollbacks, but for query history table in particular, that use-case is not typical.

Does this PR introduce any user-facing change?

No.

Is the change a dependency upgrade?

No.

How was this patch tested?

Local MiniHS2 with low expiry time and checked periodicity and filesystem.

  1. changed snapshot expiryInterval to 10s for easy testing
  2. set the table property to 30 for the same reason
  3. started MiniHS2 with local fs and ran some commands
mvn clean install -Dtest=StartMiniHS2Cluster -DminiHS2.clusterType=llap -DminiHS2.conf="target/testconf/llap/hive-site.xml"  -DminiHS2.run=true -DminiHS2.usePortsFromConf=true -pl itests/hive-unit -Pitests -DminiHS2.queryHistory -pl itests/util -DminiHS2.clusterType=LOCALFS_ONLY
  1. snapshots weren't cleaned for a certain time
 laszlobodor@lbodor-MBP16  ~   master ±  ls -la /Users/laszlobodor/apache/hive/itests/hive-unit/target/tmp/local_base/warehouse/sys.db/query_history/metadata | grep snap-
-rw-r--r--   1 laszlobodor  staff     44 Már  5 14:59 .snap-2906772874642777236-1-4164aa00-e426-408b-8cbe-3a58d4f52691.avro.crc
-rw-r--r--   1 laszlobodor  staff     48 Már  5 14:59 .snap-4248315275281594920-1-249b01bc-0822-459e-92cf-fecc27a91a97.avro.crc
-rw-r--r--   1 laszlobodor  staff     44 Már  5 14:59 .snap-810909350656151221-1-c1f2ca62-f1f3-4ef2-af14-77bc8f503f65.avro.crc
-rw-r--r--   1 laszlobodor  staff     48 Már  5 14:59 .snap-8615467046748337991-1-5510283a-054e-4f5f-82ee-1aedcf9f8316.avro.crc
-rw-r--r--   1 laszlobodor  staff     48 Már  5 14:59 .snap-8995774032769229357-1-519fe9ca-7602-421b-88f1-82718cdef6b9.avro.crc
-rw-r--r--   1 laszlobodor  staff     48 Már  5 14:59 .snap-9124228608853510592-1-188f39cd-ddb1-48c3-a2b8-d9a20828a694.avro.crc
-rw-r--r--   1 laszlobodor  staff   4521 Már  5 14:59 snap-2906772874642777236-1-4164aa00-e426-408b-8cbe-3a58d4f52691.avro
-rw-r--r--   1 laszlobodor  staff   4692 Már  5 14:59 snap-4248315275281594920-1-249b01bc-0822-459e-92cf-fecc27a91a97.avro
-rw-r--r--   1 laszlobodor  staff   4594 Már  5 14:59 snap-810909350656151221-1-c1f2ca62-f1f3-4ef2-af14-77bc8f503f65.avro
-rw-r--r--   1 laszlobodor  staff   4789 Már  5 14:59 snap-8615467046748337991-1-5510283a-054e-4f5f-82ee-1aedcf9f8316.avro
-rw-r--r--   1 laszlobodor  staff   4648 Már  5 14:59 snap-8995774032769229357-1-519fe9ca-7602-421b-88f1-82718cdef6b9.avro
-rw-r--r--   1 laszlobodor  staff   4746 Már  5 14:59 snap-9124228608853510592-1-188f39cd-ddb1-48c3-a2b8-d9a20828a694.avro
  1. then cleanup happened, in HS2 logs:
2025-03-05T05:59:53,113  INFO [IcebergRepository periodic snapshot expiry] iceberg.RemoveSnapshots: Cleaning up expired files (local, incremental)

2025-03-05T05:59:53,113  INFO [IcebergRepository periodic snapshot expiry] iceberg.IncrementalFileCleanup: Expired snapshot: BaseSnapshot{id=8995774032769229357, timestamp_ms=1741183153679, operation=append, summary={added-data-files=1, added-records=1, added-files-size=6561, changed-partition-count=1, total-records=3, total-files-size=19671, total-data-files=3, total-delete-files=0, total-position-deletes=0, total-equality-deletes=0, iceberg-version=Apache Iceberg 1.6.1 (commit 8e9d59d299be42b0bca9461457cd1e95dbaad086)}, manifest-list=file:/Users/laszlobodor/apache/hive/itests/hive-unit/target/tmp/local_base/warehouse/sys.db/query_history/metadata/snap-8995774032769229357-1-519fe9ca-7602-421b-88f1-82718cdef6b9.avro, schema-id=0}
2025-03-05T05:59:53,113  INFO [IcebergRepository periodic snapshot expiry] iceberg.IncrementalFileCleanup: Expired snapshot: BaseSnapshot{id=4248315275281594920, timestamp_ms=1741183154284, operation=append, summary={added-data-files=1, added-records=1, added-files-size=6552, changed-partition-count=1, total-records=4, total-files-size=26223, total-data-files=4, total-delete-files=0, total-position-deletes=0, total-equality-deletes=0, iceberg-version=Apache Iceberg 1.6.1 (commit 8e9d59d299be42b0bca9461457cd1e95dbaad086)}, manifest-list=file:/Users/laszlobodor/apache/hive/itests/hive-unit/target/tmp/local_base/warehouse/sys.db/query_history/metadata/snap-4248315275281594920-1-249b01bc-0822-459e-92cf-fecc27a91a97.avro, schema-id=0}
2025-03-05T05:59:53,113  INFO [IcebergRepository periodic snapshot expiry] iceberg.IncrementalFileCleanup: Expired snapshot: BaseSnapshot{id=9124228608853510592, timestamp_ms=1741183154970, operation=append, summary={added-data-files=1, added-records=1, added-files-size=6556, changed-partition-count=1, total-records=5, total-files-size=32779, total-data-files=5, total-delete-files=0, total-position-deletes=0, total-equality-deletes=0, iceberg-version=Apache Iceberg 1.6.1 (commit 8e9d59d299be42b0bca9461457cd1e95dbaad086)}, manifest-list=file:/Users/laszlobodor/apache/hive/itests/hive-unit/target/tmp/local_base/warehouse/sys.db/query_history/metadata/snap-9124228608853510592-1-188f39cd-ddb1-48c3-a2b8-d9a20828a694.avro, schema-id=0}
2025-03-05T05:59:53,113 DEBUG [IcebergRepository periodic snapshot expiry] hadoop.HadoopInputFile: Explicitly using fs.s3a.experimental.input.fadvise as normal for file:/Users/laszlobodor/apache/hive/itests/hive-unit/target/tmp/local_base/warehouse/sys.db/query_history/metadata/snap-8615467046748337991-1-5510283a-054e-4f5f-82ee-1aedcf9f8316.avro
2025-03-05T05:59:53,116 DEBUG [IcebergRepository periodic snapshot expiry] hadoop.HadoopInputFile: Explicitly using fs.s3a.experimental.input.fadvise as normal for file:/Users/laszlobodor/apache/hive/itests/hive-unit/target/tmp/local_base/warehouse/sys.db/query_history/metadata/snap-8995774032769229357-1-519fe9ca-7602-421b-88f1-82718cdef6b9.avro
2025-03-05T05:59:53,118 DEBUG [IcebergRepository periodic snapshot expiry] hadoop.HadoopInputFile: Explicitly using fs.s3a.experimental.input.fadvise as normal for file:/Users/laszlobodor/apache/hive/itests/hive-unit/target/tmp/local_base/warehouse/sys.db/query_history/metadata/snap-4248315275281594920-1-249b01bc-0822-459e-92cf-fecc27a91a97.avro
2025-03-05T05:59:53,121 DEBUG [IcebergRepository periodic snapshot expiry] hadoop.HadoopInputFile: Explicitly using fs.s3a.experimental.input.fadvise as normal for file:/Users/laszlobodor/apache/hive/itests/hive-unit/target/tmp/local_base/warehouse/sys.db/query_history/metadata/snap-9124228608853510592-1-188f39cd-ddb1-48c3-a2b8-d9a20828a694.avro

and in filesystem:


laszlobodor@lbodor-MBP16  ~   master ±  ls -la /Users/laszlobodor/apache/hive/itests/hive-unit/target/tmp/local_base/warehouse/sys.db/query_history/metadata | grep snap-
-rw-r--r--   1 laszlobodor  staff     48 Már  5 14:59 .snap-8615467046748337991-1-5510283a-054e-4f5f-82ee-1aedcf9f8316.avro.crc
-rw-r--r--   1 laszlobodor  staff   4789 Már  5 14:59 snap-8615467046748337991-1-5510283a-054e-4f5f-82ee-1aedcf9f8316.avro


Copy link
Member

@ayushtkn ayushtkn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanx @abstractdog will it be possible to extend a test for it as well


private void expireSnapshots() {
storageHandler.executeOperation(table, new AlterTableExecuteSpec<>(EXPIRE_SNAPSHOT,
new AlterTableExecuteSpec.ExpireSnapshotsSpec(10)));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to hardcode 10 here or just pass null & let the TBLPROPERTIES handle it, this way it can be configurable also by ALTER command.

I don't think this would work the way you expect, there is some default time thing as well

  public static final String MAX_SNAPSHOT_AGE_MS = "history.expire.max-snapshot-age-ms";
  public static final long MAX_SNAPSHOT_AGE_MS_DEFAULT = 432000000L;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @ayushtkn for taking a look!
good point, I'm not familiar with EXPIRE SNAPSHOT functionality detail, so this is more like a DRAFT, let me consider

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seemed to work:
4c9480f

added testing details in PR description

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ayushtkn : I just added a unit test for snapshot expiry testing

@abstractdog
Copy link
Contributor Author

while testing this patch, I realized that the meta hook commit process doesn't respect hiveLockEnabled, modified it, quite a small change but not related query history, please let me know if it can stay here @ayushtkn , @deniskuzZ

@ayushtkn
Copy link
Member

ayushtkn commented Mar 8, 2025

IMO we should split it out into a separate ticket, if it isn't related to QueryHistory

@abstractdog
Copy link
Contributor Author

IMO we should split it out into a separate ticket, if it isn't related to QueryHistory

ack, just created #5687

@abstractdog
Copy link
Contributor Author

unit test passed without the locking hack (most probably it was an incomplete step that I worked around with proper configuration in the meantime)
also addressed sonarqube issues

Table table = initTable(hive, database);
postInitTable(table);
initTable(hive, database);
postInitTable();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we trigger postInitTable within the initTable?

@@ -176,4 +193,13 @@ private void prepareConfForWrite() {
SessionStateUtil.addCommitInfo(SessionState.getSessionConf(), tableDesc.getTableName(), jobId, 1,
Maps.fromProperties(tableDesc.getProperties()));
}

private void expireSnapshots() {
Copy link
Member

@deniskuzZ deniskuzZ Mar 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have an AcidHouseKeeperService, I think we should create a similar IcebergHouseKeeperService and schedule periodic snapshot expiry on Iceberg tables.

You can define the expiry policy for the query-history table and IcebergHouseKeeperService / IcebergTableExpiryService would take care of it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, theoretically, handling them in a centralized place in metastore instead of multiple HS2s looks better from system design point of view
however, it needs a new service to be implemented, let me check

Copy link
Member

@deniskuzZ deniskuzZ Mar 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for a "NEW" service, add it to the list of TASK_THREADS_REMOTE_ONLY
but yes, that service should iterate over all iceberg tables with expiry configs and periodically trigger the snapshot expiry action

take a look at AcidTxnCleanerService

  public long runFrequency(TimeUnit unit) {
    return INTERVAL;
  }

  public void run() {
     doTheMagic()
  }

Copy link
Contributor Author

@abstractdog abstractdog Mar 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

took a look, my concern about this whole service is exactly the doTheMagic part: I remember we faced lots of problems with e.g. the PartitionManagementTask because it couldn't have been run in a lightweight fashion, and the common thing is that we need to iterate on all tables of all DBs to achieve what we want here: the best case scenario is that we implement a filter on ICEBERG tables (like: listTableNamesByFilter), kinda pushing down the filter to backend db
but even if we do that, we still need lots of code to make it as optimal as possible, just take a look at how complicated the partition management task filtering logic is to achieve the same).
So looking at the implementations so far, the "getting all iceberg tables" is the very part I'm worried about, and makes me wonder I really want to go towards that direction just the sake of this query history snapshot expiry, which is otherwise a very simple code

Focusing on the motivation, which is to handle the query history table—fully loaded and maintained by Hive—we owe it to users to optimize it as much as possible. However, the question is whether we should take on the additional burden in this PR to handle all Iceberg tables visible in the metastore, or keep the scope focused for now.

Or maybe a similar db + table name filter (that's used in the part mgmt task), but we default it to: "sys" + "query_history" in MetastoreConf and give the user the power to set it even to * + * ?

Copy link
Member

@deniskuzZ deniskuzZ Mar 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. you don't need to go down to partition level;
  2. you can get list of iceberg tables from HMS, there is an API for that;
  3. yes, service should be optimized.
  • check the last housekeeping event,
  • check if there were any changes to the table since last attempt (check if metadata file hasn't changed),
  • support table name filtering;
  1. adding it just for query history, doesn't bring much value and is not generic;
  2. downstream you can configure all policies in DLM so you don't need this at all;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants