You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@impala.apache.org by cs...@apache.org on 2021/05/31 15:36:17 UTC

[impala] branch master updated: IMPALA-10700: Add query options to skip deleting stats

This is an automated email from the ASF dual-hosted git repository.

csringhofer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git


The following commit(s) were added to refs/heads/master by this push:
     new e24bdd2  IMPALA-10700: Add query options to skip deleting stats
e24bdd2 is described below

commit e24bdd2175062c30cc9a6bcf0eb2910e8f1f7cae
Author: Vihang Karajgaonkar <vi...@apache.org>
AuthorDate: Wed May 26 16:53:38 2021 -0700

    IMPALA-10700: Add query options to skip deleting stats
    
    When a truncate table command is issued, in case of
    non-transactional tables, the table and column statistics for the table
    are also deleted by default. This can be a expensive operation
    especially when many truncate table commands are running concurrently.
    As the concurrency increases, the response time from Hive metastore
    slows down the delete table and column statistics RPC calls.
    
    In cases where truncate operation is used to remove the existing
    data and then reload new data, it is likely that users will compute
    stats again as soon as the new data is reloaded. This would overwrite
    the existing statistics and hence the additional time spent by
    the truncate operation to delete column and table statistics becomes
    unnecessary.
    
    To improve this, this change introduces a new query option:
    DELETE_STATS_IN_TRUNCATE. The default value of this option is 1 or true
    which means stats will be deleted as part of truncate operation.
    
    As the name suggests, when this query options are set to false or 0,
    a truncate operation will not delete the table and column statistics
    for the table.
    
    This change also makes a improvement to truncate operation on
    tables which are replicated. If the table is being replicated,
    previously, the statistics were not getting deleted after truncate.
    Now the statistics will get deleted after truncate.
    
    Testing:
    Modified truncate-table.test to include variations of these query
    options and making sure that the statistics are deleted or skipped
    from deletion after truncate operation.
    
    Change-Id: I9400c3586b4bdf46d9b4056ea1023aabae8cc519
    Reviewed-on: http://gerrit.cloudera.org:8080/17521
    Reviewed-by: Impala Public Jenkins <im...@cloudera.com>
    Tested-by: Impala Public Jenkins <im...@cloudera.com>
---
 be/src/service/query-options.cc                    |   4 +
 be/src/service/query-options.h                     |   6 +-
 common/thrift/ImpalaService.thrift                 |   4 +
 common/thrift/JniCatalog.thrift                    |   4 +
 common/thrift/Query.thrift                         |   3 +
 .../apache/impala/service/CatalogOpExecutor.java   |  76 +++++---
 .../java/org/apache/impala/service/Frontend.java   |  10 +-
 .../queries/QueryTest/truncate-table.test          | 212 +++++++++++++++++++++
 8 files changed, 293 insertions(+), 26 deletions(-)

diff --git a/be/src/service/query-options.cc b/be/src/service/query-options.cc
index a7a88d8..dd0e732 100644
--- a/be/src/service/query-options.cc
+++ b/be/src/service/query-options.cc
@@ -1084,6 +1084,10 @@ Status impala::SetQueryOption(const string& key, const string& value,
         query_options->__set_kudu_replica_selection(enum_type);
         break;
       }
+      case TImpalaQueryOptions::DELETE_STATS_IN_TRUNCATE: {
+        query_options->__set_delete_stats_in_truncate(IsTrue(value));
+        break;
+      }
       default:
         if (IsRemovedQueryOption(key)) {
           LOG(WARNING) << "Ignoring attempt to set removed query option '" << key << "'";
diff --git a/be/src/service/query-options.h b/be/src/service/query-options.h
index 663c9e4..12a9c20 100644
--- a/be/src/service/query-options.h
+++ b/be/src/service/query-options.h
@@ -47,7 +47,7 @@ typedef std::unordered_map<string, beeswax::TQueryOptionLevel::type>
 // time we add or remove a query option to/from the enum TImpalaQueryOptions.
 #define QUERY_OPTS_TABLE\
   DCHECK_EQ(_TImpalaQueryOptions_VALUES_TO_NAMES.size(),\
-      TImpalaQueryOptions::KUDU_REPLICA_SELECTION + 1);\
+      TImpalaQueryOptions::DELETE_STATS_IN_TRUNCATE + 1);\
   REMOVED_QUERY_OPT_FN(abort_on_default_limit_exceeded, ABORT_ON_DEFAULT_LIMIT_EXCEEDED)\
   QUERY_OPT_FN(abort_on_error, ABORT_ON_ERROR, TQueryOptionLevel::REGULAR)\
   REMOVED_QUERY_OPT_FN(allow_unsupported_formats, ALLOW_UNSUPPORTED_FORMATS)\
@@ -244,7 +244,9 @@ typedef std::unordered_map<string, beeswax::TQueryOptionLevel::type>
       TQueryOptionLevel::ADVANCED)\
   QUERY_OPT_FN(default_ndv_scale, DEFAULT_NDV_SCALE, TQueryOptionLevel::ADVANCED)\
   QUERY_OPT_FN(kudu_replica_selection, KUDU_REPLICA_SELECTION,\
-      TQueryOptionLevel::ADVANCED)
+      TQueryOptionLevel::ADVANCED)\
+  QUERY_OPT_FN(delete_stats_in_truncate, DELETE_STATS_IN_TRUNCATE,\
+      TQueryOptionLevel::ADVANCED)\
 ;
 
 /// Enforce practical limits on some query options to avoid undesired query state.
diff --git a/common/thrift/ImpalaService.thrift b/common/thrift/ImpalaService.thrift
index 774111e..e798dd5 100644
--- a/common/thrift/ImpalaService.thrift
+++ b/common/thrift/ImpalaService.thrift
@@ -661,6 +661,10 @@ enum TImpalaQueryOptions {
   //     LEADER_ONLY     - Select the LEADER replica.
   //     CLOSEST_REPLICA - Select the closest replica to the client (default).
   KUDU_REPLICA_SELECTION = 127
+
+  // If false, a truncate DDL operation will not delete table stats.
+  // the default value of this is true as set in Query.thrift
+  DELETE_STATS_IN_TRUNCATE = 128
 }
 
 // The summary of a DML statement.
diff --git a/common/thrift/JniCatalog.thrift b/common/thrift/JniCatalog.thrift
index 8b7bdef..abcf430 100644
--- a/common/thrift/JniCatalog.thrift
+++ b/common/thrift/JniCatalog.thrift
@@ -701,6 +701,10 @@ struct TTruncateParams {
 
   // If true, no error is raised if the target table does not exist
   2: required bool if_exists
+
+  // If false, table stats  will not be deleted as part of
+  // the truncate operation
+  3: optional bool delete_stats = true
 }
 
 // Parameters of DROP FUNCTION commands
diff --git a/common/thrift/Query.thrift b/common/thrift/Query.thrift
index 3ee83a9..9436c42 100644
--- a/common/thrift/Query.thrift
+++ b/common/thrift/Query.thrift
@@ -502,6 +502,9 @@ struct TQueryOptions {
   // See comment in ImpalaService.thrift
   128: optional TKuduReplicaSelection kudu_replica_selection =
       TKuduReplicaSelection.CLOSEST_REPLICA;
+
+  // See comment in ImpalaService.thrift
+  129: optional bool delete_stats_in_truncate = true;
 }
 
 // Impala currently has three types of sessions: Beeswax, HiveServer2 and external
diff --git a/fe/src/main/java/org/apache/impala/service/CatalogOpExecutor.java b/fe/src/main/java/org/apache/impala/service/CatalogOpExecutor.java
index 253102b..d345907 100644
--- a/fe/src/main/java/org/apache/impala/service/CatalogOpExecutor.java
+++ b/fe/src/main/java/org/apache/impala/service/CatalogOpExecutor.java
@@ -2173,6 +2173,7 @@ public class CatalogOpExecutor {
     Preconditions.checkState(catalog_.getLock().isWriteLockedByCurrentThread());
     catalog_.getLock().writeLock().unlock();
     TableName tblName = TableName.fromThrift(params.getTable_name());
+    Stopwatch sw = Stopwatch.createStarted();
     try (MetaStoreClient msClient = catalog_.getMetaStoreClient()) {
       long newCatalogVersion = 0;
       IMetaStoreClient hmsClient = msClient.getHiveClient();
@@ -2188,6 +2189,8 @@ public class CatalogOpExecutor {
         catalog_.lockTableInTransaction(tblName.getDb(), tblName.getTbl(), txn,
             DataOperationType.NO_TXN, ctx);
         tryWriteLock(table, "truncating");
+        LOG.trace("Time elapsed after taking write lock on table {}: {} msec",
+            table.getFullName(), sw.elapsed(TimeUnit.MILLISECONDS));
         newCatalogVersion = catalog_.incrementAndGetCatalogVersion();
         catalog_.getLock().writeLock().unlock();
         TblTransaction tblTxn = MetastoreShim.createTblTransaction(hmsClient,
@@ -2197,16 +2200,17 @@ public class CatalogOpExecutor {
         // if moves the files into in replication change manager location which is later
         // used for replication.
         if (isTableBeingReplicated(hmsClient, hdfsTable)) {
-          Stopwatch sw = Stopwatch.createStarted();
           String dbName = Preconditions.checkNotNull(hdfsTable.getDb()).getName();
           hmsClient.truncateTable(dbName, hdfsTable.getName(), null, tblTxn.validWriteIds,
               tblTxn.writeId);
-          LOG.debug("Time taken to truncate table {} using HMS API: {} msec",
-              hdfsTable.getFullName(), sw.stop().elapsed(TimeUnit.MILLISECONDS));
+          LOG.trace("Time elapsed to truncate table {} using HMS API: {} msec",
+              hdfsTable.getFullName(), sw.elapsed(TimeUnit.MILLISECONDS));
         } else {
           Collection<? extends FeFsPartition> parts =
               FeCatalogUtils.loadAllPartitions(hdfsTable);
           createEmptyBaseDirectories(parts, tblTxn.writeId);
+          LOG.trace("Time elapsed after creating empty base directories for table {}: {} "
+                  + "msec", table.getFullName(), sw.elapsed(TimeUnit.MILLISECONDS));
           // Currently Impala cannot update the statistics properly. So instead of
           // writing correct stats, let's just remove COLUMN_STATS_ACCURATE parameter from
           // each partition.
@@ -2230,6 +2234,8 @@ public class CatalogOpExecutor {
           }
           // Remove COLUMN_STATS_ACCURATE property from the table.
           unsetTableColStats(table.getMetaStoreTable(), tblTxn);
+          LOG.trace("Time elapsed after unset partition and column statistics for table "
+              + "{}: {} msec", table.getFullName(), sw.elapsed(TimeUnit.MILLISECONDS));
         }
         txn.commit();
       }
@@ -2237,6 +2243,10 @@ public class CatalogOpExecutor {
     } catch (Exception e) {
       throw new ImpalaRuntimeException(
           String.format(HMS_RPC_ERROR_FORMAT_STR, "truncateTable"), e);
+    } finally {
+      LOG.trace("Time taken to do metastore and file system operations for"
+              + " truncating table {}: {} msec", table.getFullName(),
+          sw.stop().elapsed(TimeUnit.MILLISECONDS));
     }
   }
 
@@ -2269,8 +2279,10 @@ public class CatalogOpExecutor {
     long newCatalogVersion = catalog_.incrementAndGetCatalogVersion();
     catalog_.getLock().writeLock().unlock();
     FeIcebergTable iceTable = (FeIcebergTable)table;
-    dropColumnStats(table);
-    dropTableStats(table);
+    if (params.isDelete_stats()) {
+      dropColumnStats(table);
+      dropTableStats(table);
+    }
     IcebergCatalogOpExecutor.truncateTable(iceTable);
     return newCatalogVersion;
   }
@@ -2282,26 +2294,44 @@ public class CatalogOpExecutor {
     long newCatalogVersion = catalog_.incrementAndGetCatalogVersion();
     catalog_.getLock().writeLock().unlock();
     HdfsTable hdfsTable = (HdfsTable) table;
-    // if the table is being replicated we issue the HMS API to truncate the table
-    // since it generates additional events which are used by Hive Replication.
-    try (MetaStoreClient metaStoreClient = catalog_.getMetaStoreClient()) {
-      if (isTableBeingReplicated(metaStoreClient.getHiveClient(), hdfsTable)) {
-        String dbName = Preconditions.checkNotNull(hdfsTable.getDb()).getName();
-        Stopwatch sw = Stopwatch.createStarted();
-        metaStoreClient.getHiveClient().truncateTable(dbName, hdfsTable.getName(), null);
-        LOG.debug("Time taken to truncate table {} using HMS API: {} msec",
-            hdfsTable.getFullName(), sw.stop().elapsed(TimeUnit.MILLISECONDS));
-        return newCatalogVersion;
+    boolean isTableBeingReplicated = false;
+    Stopwatch sw = Stopwatch.createStarted();
+    try {
+      // if the table is being replicated we issue the HMS API to truncate the table
+      // since it generates additional events which are used by Hive Replication.
+      try (MetaStoreClient metaStoreClient = catalog_.getMetaStoreClient()) {
+        if (isTableBeingReplicated(metaStoreClient.getHiveClient(), hdfsTable)) {
+          isTableBeingReplicated = true;
+          String dbName = Preconditions.checkNotNull(hdfsTable.getDb()).getName();
+          metaStoreClient.getHiveClient()
+              .truncateTable(dbName, hdfsTable.getName(), null);
+          LOG.trace("Time elapsed after truncating table {} using HMS API: {} msec",
+              hdfsTable.getFullName(), sw.elapsed(TimeUnit.MILLISECONDS));
+        }
       }
+      if (!isTableBeingReplicated) {
+        // when table is replicated we let the HMS API handle the file deletion logic
+        // otherwise we delete the files.
+        Collection<? extends FeFsPartition> parts = FeCatalogUtils
+            .loadAllPartitions(hdfsTable);
+        for (FeFsPartition part : parts) {
+          FileSystemUtil.deleteAllVisibleFiles(new Path(part.getLocation()));
+        }
+        LOG.trace("Time elapsed after deleting files for table {}: {} msec",
+            table.getFullName(), sw.elapsed(TimeUnit.MILLISECONDS));
+      }
+      if (params.isDelete_stats()) {
+        dropColumnStats(table);
+        dropTableStats(table);
+        LOG.trace("Time elapsed after deleting statistics for table {}: {} msec ",
+            table.getFullName(), sw.elapsed(TimeUnit.MILLISECONDS));
+      }
+      return newCatalogVersion;
+    } finally {
+      LOG.debug("Time taken for metastore and filesystem operations for truncating "
+              + "table {}: {} msec", table.getFullName(),
+          sw.stop().elapsed(TimeUnit.MILLISECONDS));
     }
-    Collection<? extends FeFsPartition> parts = FeCatalogUtils
-        .loadAllPartitions(hdfsTable);
-    for (FeFsPartition part : parts) {
-      FileSystemUtil.deleteAllVisibleFiles(new Path(part.getLocation()));
-    }
-    dropColumnStats(table);
-    dropTableStats(table);
-    return newCatalogVersion;
   }
 
   /**
diff --git a/fe/src/main/java/org/apache/impala/service/Frontend.java b/fe/src/main/java/org/apache/impala/service/Frontend.java
index 959cae8..92c28a7 100644
--- a/fe/src/main/java/org/apache/impala/service/Frontend.java
+++ b/fe/src/main/java/org/apache/impala/service/Frontend.java
@@ -171,6 +171,7 @@ import org.apache.impala.thrift.TShowFilesParams;
 import org.apache.impala.thrift.TShowStatsOp;
 import org.apache.impala.thrift.TStmtType;
 import org.apache.impala.thrift.TTableName;
+import org.apache.impala.thrift.TTruncateParams;
 import org.apache.impala.thrift.TUpdateCatalogCacheRequest;
 import org.apache.impala.thrift.TUpdateCatalogCacheResponse;
 import org.apache.impala.thrift.TUpdateExecutorMembershipRequest;
@@ -589,7 +590,14 @@ public class Frontend {
       TDdlExecRequest req = new TDdlExecRequest();
       TruncateStmt stmt = analysis.getTruncateStmt();
       req.setDdl_type(TDdlType.TRUNCATE_TABLE);
-      req.setTruncate_params(stmt.toThrift());
+      TTruncateParams truncateParams = stmt.toThrift();
+      TQueryOptions queryOptions = result.getQuery_options();
+      // if DELETE_STATS_IN_TRUNCATE option is unset forward it to catalogd
+      // so that it can skip deleting the statistics during truncate execution
+      if (!queryOptions.isDelete_stats_in_truncate()) {
+        truncateParams.setDelete_stats(false);
+      }
+      req.setTruncate_params(truncateParams);
       ddl.setDdl_params(req);
     } else if (analysis.isDropFunctionStmt()) {
       ddl.op_type = TCatalogOpType.DDL;
diff --git a/testdata/workloads/functional-query/queries/QueryTest/truncate-table.test b/testdata/workloads/functional-query/queries/QueryTest/truncate-table.test
index 4f3e7fa..fa5cb57 100644
--- a/testdata/workloads/functional-query/queries/QueryTest/truncate-table.test
+++ b/testdata/workloads/functional-query/queries/QueryTest/truncate-table.test
@@ -193,3 +193,215 @@ select count(*) from t3;
 ---- TYPES
 BIGINT
 ====
+---- QUERY
+# First create a partitioned table
+create table t4 like functional.alltypes
+location '$FILESYSTEM_PREFIX/test-warehouse/$DATABASE.db/t4';
+insert into t4 partition(year, month) select * from functional.alltypes;
+compute incremental stats t4;
+# if DELETE_STATS_IN_TRUNCATE is unset then truncate should not
+# delete the table statistics.
+set DELETE_STATS_IN_TRUNCATE=0;
+truncate table t4;
+show table stats t4;
+---- LABELS
+YEAR, MONTH, #ROWS, #FILES, SIZE, BYTES CACHED, CACHE REPLICATION, FORMAT, INCREMENTAL STATS, LOCATION
+---- RESULTS
+'2009','1',310,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2009','2',280,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2009','3',310,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2009','4',300,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2009','5',310,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2009','6',300,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2009','7',310,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2009','8',310,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2009','9',300,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2009','10',310,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2009','11',300,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2009','12',310,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2010','1',310,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2010','2',280,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2010','3',310,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2010','4',300,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2010','5',310,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2010','6',300,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2010','7',310,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2010','8',310,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2010','9',300,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2010','10',310,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2010','11',300,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'2010','12',310,0,'0B','NOT CACHED','NOT CACHED','TEXT','true',regex:.*
+'Total','',7300,0,'0B','0B','','','',''
+---- TYPES
+STRING, STRING, BIGINT, BIGINT, STRING, STRING, STRING, STRING, STRING, STRING
+====
+---- QUERY
+show column stats t4;
+---- LABELS
+COLUMN, TYPE, #DISTINCT VALUES, #NULLS, MAX SIZE, AVG SIZE, #TRUES, #FALSES
+---- RESULTS
+'id','INT',7300,0,4,4,-1,-1
+'bool_col','BOOLEAN',2,0,1,1,3650,3650
+'tinyint_col','TINYINT',10,0,1,1,-1,-1
+'smallint_col','SMALLINT',10,0,2,2,-1,-1
+'int_col','INT',10,0,4,4,-1,-1
+'bigint_col','BIGINT',10,0,8,8,-1,-1
+'float_col','FLOAT',10,0,4,4,-1,-1
+'double_col','DOUBLE',10,0,8,8,-1,-1
+'date_string_col','STRING',736,0,8,8,-1,-1
+'string_col','STRING',10,0,1,1,-1,-1
+'timestamp_col','TIMESTAMP',7300,0,16,16,-1,-1
+'year','INT',2,0,4,4,-1,-1
+'month','INT',12,0,4,4,-1,-1
+---- TYPES
+STRING, STRING, BIGINT, BIGINT, BIGINT, DOUBLE, BIGINT, BIGINT
+====
+---- QUERY
+#Verify that truncate was successful
+select count(*) from t4;
+---- RESULTS
+0
+---- TYPES
+BIGINT
+====
+---- QUERY
+insert into t4 partition(year, month) select * from functional.alltypes;
+compute incremental stats t4;
+# if DELETE_STATS_IN_TRUNCATE is set then truncate should
+# delete the statistics.
+set DELETE_STATS_IN_TRUNCATE=1;
+truncate table t4;
+show table stats t4;
+---- LABELS
+YEAR, MONTH, #ROWS, #FILES, SIZE, BYTES CACHED, CACHE REPLICATION, FORMAT, INCREMENTAL STATS, LOCATION
+---- RESULTS
+'2009','1',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2009','2',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2009','3',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2009','4',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2009','5',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2009','6',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2009','7',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2009','8',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2009','9',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2009','10',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2009','11',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2009','12',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2010','1',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2010','2',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2010','3',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2010','4',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2010','5',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2010','6',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2010','7',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2010','8',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2010','9',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2010','10',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2010','11',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'2010','12',-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+'Total','',-1,0,'0B','0B','','','',''
+---- TYPES
+STRING, STRING, BIGINT, BIGINT, STRING, STRING, STRING, STRING, STRING, STRING
+====
+---- QUERY
+# Show that the truncation removed the column stats.
+show column stats t4;
+---- LABELS
+COLUMN, TYPE, #DISTINCT VALUES, #NULLS, MAX SIZE, AVG SIZE, #TRUES, #FALSES
+---- RESULTS
+'id','INT',-1,-1,4,4,-1,-1
+'bool_col','BOOLEAN',-1,-1,1,1,-1,-1
+'tinyint_col','TINYINT',-1,-1,1,1,-1,-1
+'smallint_col','SMALLINT',-1,-1,2,2,-1,-1
+'int_col','INT',-1,-1,4,4,-1,-1
+'bigint_col','BIGINT',-1,-1,8,8,-1,-1
+'float_col','FLOAT',-1,-1,4,4,-1,-1
+'double_col','DOUBLE',-1,-1,8,8,-1,-1
+'date_string_col','STRING',-1,-1,-1,-1,-1,-1
+'string_col','STRING',-1,-1,-1,-1,-1,-1
+'timestamp_col','TIMESTAMP',-1,-1,16,16,-1,-1
+'year','INT',2,0,4,4,-1,-1
+'month','INT',12,0,4,4,-1,-1
+---- TYPES
+STRING, STRING, BIGINT, BIGINT, BIGINT, DOUBLE, BIGINT, BIGINT
+====
+---- QUERY
+#Verify that truncate was successful
+select count(*) from t4;
+---- RESULTS
+0
+---- TYPES
+BIGINT
+====
+---- QUERY
+# Unpartitioned table case: Show that if DELETE_STATS_IN_TRUNCATE is
+# unset truncation removes all files
+# but does not delete table and column stats.
+create table t6 like functional.tinytable
+location '$FILESYSTEM_PREFIX/test-warehouse/$DATABASE.db/t6';
+insert into t6 select * from functional.tinytable;
+compute incremental stats t6;
+set DELETE_STATS_IN_TRUNCATE=0;
+truncate table t6;
+show table stats t6;
+---- LABELS
+#ROWS, #FILES, SIZE, BYTES CACHED, CACHE REPLICATION, FORMAT, INCREMENTAL STATS, LOCATION
+---- RESULTS
+3,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+---- TYPES
+BIGINT, BIGINT, STRING, STRING, STRING, STRING, STRING, STRING
+====
+---- QUERY
+# Show that the truncation removed the column stats.
+show column stats t6;
+---- LABELS
+COLUMN, TYPE, #DISTINCT VALUES, #NULLS, MAX SIZE, AVG SIZE, #TRUES, #FALSES
+---- RESULTS
+'a','STRING',3,0,8,6.666666507720947,-1,-1
+'b','STRING',3,0,7,4,-1,-1
+---- TYPES
+STRING, STRING, BIGINT, BIGINT, BIGINT, DOUBLE, BIGINT, BIGINT
+====
+---- QUERY
+#Verify that truncate was successful
+select count(*) from t6;
+---- RESULTS
+0
+---- TYPES
+BIGINT
+====
+---- QUERY
+# Unpartitioned table case: Show that if DELETE_STATS_IN_TRUNCATE is
+# set truncation removes all files and deletes stats.
+insert into t6 select * from functional.tinytable;
+compute incremental stats t6;
+# table stats should be deleted
+set DELETE_STATS_IN_TRUNCATE=1;
+truncate table t6;
+show table stats t6;
+---- LABELS
+#ROWS, #FILES, SIZE, BYTES CACHED, CACHE REPLICATION, FORMAT, INCREMENTAL STATS, LOCATION
+---- RESULTS
+-1,0,'0B','NOT CACHED','NOT CACHED','TEXT','false',regex:.*
+---- TYPES
+BIGINT, BIGINT, STRING, STRING, STRING, STRING, STRING, STRING
+====
+---- QUERY
+# Show that the truncation removed the column stats.
+show column stats t6;
+---- LABELS
+COLUMN, TYPE, #DISTINCT VALUES, #NULLS, MAX SIZE, AVG SIZE, #TRUES, #FALSES
+---- RESULTS
+'a','STRING',-1,-1,-1,-1,-1,-1
+'b','STRING',-1,-1,-1,-1,-1,-1
+---- TYPES
+STRING, STRING, BIGINT, BIGINT, BIGINT, DOUBLE, BIGINT, BIGINT
+====
+---- QUERY
+#Verify that truncate was successful
+select count(*) from t6;
+---- RESULTS
+0
+---- TYPES
+BIGINT
+====