This is an automated email from the ASF dual-hosted git repository.
palashc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/phoenix.git
The following commit(s) were added to refs/heads/master by this push:
new 3ac1774213 PHOENIX-7381 : Skip last_ddl_timestamp validation when UCF
is defined on table and cache entry is not old (#1952)
3ac1774213 is described below
commit 3ac177421335a41d6e89b6cd36912c16f9f8983a
Author: Palash Chauhan <[email protected]>
AuthorDate: Mon Sep 30 23:35:13 2024 -0700
PHOENIX-7381 : Skip last_ddl_timestamp validation when UCF is defined on
table and cache entry is not old (#1952)
Co-authored-by: Palash Chauhan
<[email protected]>
---
.../org/apache/phoenix/schema/MetaDataClient.java | 21 +++++-----
.../java/org/apache/phoenix/util/MetaDataUtil.java | 8 ++++
.../phoenix/util/ValidateLastDDLTimestampUtil.java | 38 +++++++++++++++--
.../phoenix/cache/ServerMetadataCacheIT.java | 47 ++++++++++++++++++++++
.../UCFWithDisabledIndexWithDDLValidationIT.java | 14 +++----
5 files changed, 103 insertions(+), 25 deletions(-)
diff --git
a/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
b/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
index 166caa6a66..407fce4db3 100644
---
a/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
+++
b/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
@@ -785,13 +785,13 @@ public class MetaDataClient {
final long effectiveUpdateCacheFreq;
final String ucfInfoForLogging; // Only used for logging purposes
- boolean overrideUcfToDefault = false;
+ boolean overrideUcfToAlways = false;
if (table.getType() == INDEX) {
- overrideUcfToDefault =
+ overrideUcfToAlways =
PIndexState.PENDING_DISABLE.equals(table.getIndexState()) ||
!IndexMaintainer.sendIndexMaintainer(table);
}
- if (!overrideUcfToDefault && !table.getIndexes().isEmpty()) {
+ if (!overrideUcfToAlways && !table.getIndexes().isEmpty()) {
List<PTable> indexes = table.getIndexes();
List<PTable> maintainedIndexes =
Lists.newArrayList(IndexMaintainer.maintainedIndexes(indexes.iterator()));
@@ -801,7 +801,7 @@ public class MetaDataClient {
// not in usable state by the client mutations, we should
override
// UPDATE_CACHE_FREQUENCY to default value so that we make
getTable() RPC calls
// until all index states change to ACTIVE, BUILDING or other
usable states.
- overrideUcfToDefault = indexes.size() !=
maintainedIndexes.size();
+ overrideUcfToAlways = indexes.size() !=
maintainedIndexes.size();
}
// What if the table is created with UPDATE_CACHE_FREQUENCY
explicitly set to ALWAYS?
@@ -810,12 +810,10 @@ public class MetaDataClient {
//always fetch an Index in PENDING_DISABLE state to retrieve
server timestamp
//QueryOptimizer needs that to decide whether the index can be used
- if (overrideUcfToDefault) {
+ if (overrideUcfToAlways) {
effectiveUpdateCacheFreq =
- (Long) ConnectionProperty.UPDATE_CACHE_FREQUENCY.getValue(
- connection.getQueryServices().getProps()
-
.get(QueryServices.DEFAULT_UPDATE_CACHE_FREQUENCY_ATRRIB));
- ucfInfoForLogging = "connection-level-default";
+ (Long)
ConnectionProperty.UPDATE_CACHE_FREQUENCY.getValue("ALWAYS");
+ ucfInfoForLogging = "override-to-always";
} else if (table.getUpdateCacheFrequency()
!= QueryServicesOptions.DEFAULT_UPDATE_CACHE_FREQUENCY) {
effectiveUpdateCacheFreq = table.getUpdateCacheFrequency();
@@ -836,9 +834,8 @@ public class MetaDataClient {
(table.getTenantId() != null ? ", Tenant ID: " +
table.getTenantId() : ""));
}
- return (table.getRowTimestampColPos() == -1 &&
- connection.getMetaDataCache().getAge(tableRef) <
- effectiveUpdateCacheFreq);
+ return MetaDataUtil
+ .avoidMetadataRPC(connection, table, tableRef,
effectiveUpdateCacheFreq);
}
return false;
}
diff --git
a/phoenix-core-client/src/main/java/org/apache/phoenix/util/MetaDataUtil.java
b/phoenix-core-client/src/main/java/org/apache/phoenix/util/MetaDataUtil.java
index 2fa3ac109f..ca13846d9e 100644
---
a/phoenix-core-client/src/main/java/org/apache/phoenix/util/MetaDataUtil.java
+++
b/phoenix-core-client/src/main/java/org/apache/phoenix/util/MetaDataUtil.java
@@ -33,6 +33,7 @@ import org.apache.phoenix.schema.PColumnFamily;
import org.apache.phoenix.schema.PName;
import org.apache.phoenix.schema.PNameFactory;
import org.apache.phoenix.schema.PTable;
+import org.apache.phoenix.schema.PTableRef;
import org.apache.phoenix.schema.PTableType;
import org.apache.phoenix.schema.SequenceKey;
import org.apache.phoenix.schema.SortOrder;
@@ -1196,4 +1197,11 @@ public class MetaDataUtil {
return maxLookbackAge != null ? maxLookbackAge :
BaseScannerRegionObserverConstants.getMaxLookbackInMillis(conf);
}
+
+ public static boolean avoidMetadataRPC(PhoenixConnection connection,
PTable table,
+ PTableRef tableRef, long
effectiveUpdateCacheFreq) {
+ return table.getRowTimestampColPos() == -1 &&
+ connection.getMetaDataCache().getAge(tableRef) <
+ effectiveUpdateCacheFreq;
+ }
}
diff --git
a/phoenix-core-client/src/main/java/org/apache/phoenix/util/ValidateLastDDLTimestampUtil.java
b/phoenix-core-client/src/main/java/org/apache/phoenix/util/ValidateLastDDLTimestampUtil.java
index dbb321a244..95b1d1537a 100644
---
a/phoenix-core-client/src/main/java/org/apache/phoenix/util/ValidateLastDDLTimestampUtil.java
+++
b/phoenix-core-client/src/main/java/org/apache/phoenix/util/ValidateLastDDLTimestampUtil.java
@@ -35,10 +35,13 @@ import org.apache.phoenix.jdbc.PhoenixConnection;
import org.apache.phoenix.query.QueryConstants;
import org.apache.phoenix.query.QueryServices;
import org.apache.phoenix.query.QueryServicesOptions;
+import org.apache.phoenix.schema.ConnectionProperty;
import org.apache.phoenix.schema.PName;
import org.apache.phoenix.schema.PTable;
import org.apache.phoenix.schema.PTableKey;
+import org.apache.phoenix.schema.PTableRef;
import org.apache.phoenix.schema.PTableType;
+import org.apache.phoenix.schema.TableNotFoundException;
import org.apache.phoenix.schema.TableRef;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -100,7 +103,10 @@ public class ValidateLastDDLTimestampUtil {
public static void validateLastDDLTimestamp(PhoenixConnection conn,
List<TableRef> allTableRefs,
boolean doRetry) throws
SQLException {
- List<TableRef> tableRefs = filterTableRefs(allTableRefs);
+ List<TableRef> tableRefs = filterTableRefs(conn, allTableRefs);
+ if (tableRefs.isEmpty()) {
+ return;
+ }
String infoString = getInfoString(conn.getTenantId(), tableRefs);
try (Admin admin = conn.getQueryServices().getAdmin()) {
// get all live region servers
@@ -215,14 +221,38 @@ public class ValidateLastDDLTimestampUtil {
}
/**
- * Filter out any TableRefs which are not tables, views or indexes.
+ * Filter out TableRefs for sending to server to validate
last_ddl_timestamp.
+ * 1. table type is in ALLOWED_PTABLE_TYPES
+ * 2. table schema has a non-zero UPDATE_CACHE_FREQUENCY and cache entry
is old.
* @param tableRefs
* @return
*/
- private static List<TableRef> filterTableRefs(List<TableRef> tableRefs) {
+ private static List<TableRef> filterTableRefs(PhoenixConnection conn,
+ List<TableRef> tableRefs) {
List<TableRef> filteredTableRefs = tableRefs.stream()
- .filter(tableRef ->
ALLOWED_PTABLE_TYPES.contains(tableRef.getTable().getType()))
+ .filter(tableRef ->
ALLOWED_PTABLE_TYPES.contains(tableRef.getTable().getType())
+ && !avoidRpc(conn, tableRef.getTable()))
.collect(Collectors.toList());
return filteredTableRefs;
}
+
+ /**
+ * Decide whether we should avoid the validate timestamp RPC for this
table. If the schema of
+ * the table had specified a positive UCF to begin with, clients for this
table should not see
+ * a regression when metadata caching re-design is enabled i.e. any server
RPC should be
+ * skipped for them within the UCF window.
+ */
+ private static boolean avoidRpc(PhoenixConnection conn, PTable table) {
+ try {
+ PTableRef ptr = conn.getTableRef(table.getKey());
+ long tableUCF = table.getUpdateCacheFrequency();
+ return tableUCF > (Long)
ConnectionProperty.UPDATE_CACHE_FREQUENCY.getValue("ALWAYS")
+ && tableUCF < (Long)
ConnectionProperty.UPDATE_CACHE_FREQUENCY.getValue("NEVER")
+ && MetaDataUtil.avoidMetadataRPC(conn, table, ptr,
tableUCF);
+ } catch (TableNotFoundException e) {
+ //should not happen since this is called after query compilation
and optimizer
+ //so the table would be in the cache
+ return false;
+ }
+ }
}
diff --git
a/phoenix-core/src/it/java/org/apache/phoenix/cache/ServerMetadataCacheIT.java
b/phoenix-core/src/it/java/org/apache/phoenix/cache/ServerMetadataCacheIT.java
index 1ecf1843c9..8e309cbc2f 100644
---
a/phoenix-core/src/it/java/org/apache/phoenix/cache/ServerMetadataCacheIT.java
+++
b/phoenix-core/src/it/java/org/apache/phoenix/cache/ServerMetadataCacheIT.java
@@ -1812,6 +1812,47 @@ public class ServerMetadataCacheIT extends
ParallelStatsDisabledIT {
}
}
+ /**
+ * Test that last_ddl_timestamp validation is skipped when client's
operation involves
+ * a table with 0<UCF<Long.MAX_VALUE.
+ */
+ @Test
+ public void testNoDDLTimestampValidationWithTableUCF() throws Exception {
+ String tableName = generateUniqueName();
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ String url1 = QueryUtil.getConnectionUrl(props, config, "client1");
+ String url2 = QueryUtil.getConnectionUrl(props, config, "client2");
+ ConnectionQueryServices cqs1 = driver.getConnectionQueryServices(url1,
props);
+ ConnectionQueryServices cqs2 = driver.getConnectionQueryServices(url2,
props);
+ MetricsMetadataCachingSource metricsSource
+ =
MetricsPhoenixCoprocessorSourceFactory.getInstance().getMetadataCachingSource();
+ //take a snapshot of current metric values
+ MetricsMetadataCachingSource.MetadataCachingMetricValues
oldMetricValues
+ = metricsSource.getCurrentMetricValues();
+
+ try (Connection conn1 = cqs1.connect(url1, props);
+ Connection conn2 = cqs2.connect(url2, props)) {
+
+ // client-1 creates table with UCF=2days
+ createTableWithUCF(conn1, tableName, 2*24*60*60*1000L);
+
+ // query/upsert a few times with same and different client
+ for (int i=0; i<3; i++) {
+ query(conn2, tableName);
+ upsert(conn2, tableName, true);
+ query(conn1, tableName);
+ upsert(conn1, tableName, true);
+ }
+
+ MetricsMetadataCachingSource.MetadataCachingMetricValues
newMetricValues
+ = metricsSource.getCurrentMetricValues();
+
+ assertEquals("There should have been no timestamp validation
requests.",
+ 0,
+ newMetricValues.getValidateDDLTimestampRequestsCount()
+ -
oldMetricValues.getValidateDDLTimestampRequestsCount());
+ }
+ }
//Helper methods
public static void assertNumGetTableRPC(ConnectionQueryServices spyCqs,
String tableName, int numExpectedRPCs) throws SQLException {
@@ -1840,6 +1881,12 @@ public class ServerMetadataCacheIT extends
ParallelStatsDisabledIT {
+ "(k INTEGER NOT NULL PRIMARY KEY, v1 INTEGER, v2 INTEGER)");
}
+ private void createTableWithUCF(Connection conn, String tableName, long
ucf) throws SQLException {
+ conn.createStatement().execute("CREATE TABLE " + tableName
+ + "(k INTEGER NOT NULL PRIMARY KEY, v1 INTEGER, v2 INTEGER) "
+ + "UPDATE_CACHE_FREQUENCY=" + ucf);
+ }
+
private void createView(Connection conn, String parentName, String
viewName) throws SQLException {
conn.createStatement().execute("CREATE VIEW " + viewName + " AS SELECT
* FROM " + parentName);
}
diff --git
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/UCFWithDisabledIndexWithDDLValidationIT.java
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/UCFWithDisabledIndexWithDDLValidationIT.java
index 1d0b87d52a..74235aaa57 100644
---
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/UCFWithDisabledIndexWithDDLValidationIT.java
+++
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/UCFWithDisabledIndexWithDDLValidationIT.java
@@ -40,7 +40,7 @@ public class UCFWithDisabledIndexWithDDLValidationIT extends
UCFWithDisabledInde
Map<String, String> props = Maps.newConcurrentMap();
props.put(BaseScannerRegionObserverConstants.PHOENIX_MAX_LOOKBACK_AGE_CONF_KEY,
Integer.toString(60 * 60 * 1000));
- props.put(QueryServices.DEFAULT_UPDATE_CACHE_FREQUENCY_ATRRIB,
"ALWAYS");
+ props.put(QueryServices.DEFAULT_UPDATE_CACHE_FREQUENCY_ATRRIB,
"NEVER");
props.put(QueryServices.LAST_DDL_TIMESTAMP_VALIDATION_ENABLED,
Boolean.toString(true));
props.put(QueryServices.PHOENIX_METADATA_INVALIDATE_CACHE_ENABLED,
Boolean.toString(true));
props.put(QueryServices.TASK_HANDLING_INITIAL_DELAY_MS_ATTRIB,
@@ -55,26 +55,22 @@ public class UCFWithDisabledIndexWithDDLValidationIT
extends UCFWithDisabledInde
@Test
public void testUcfWithNoGetTableCalls() throws Throwable {
- // Uncomment with PHOENIX-7381
- //super.testUcfWithNoGetTableCalls();
+ super.testUcfWithNoGetTableCalls();
}
@Test
public void testUcfWithDisabledIndex1() throws Throwable {
- // Uncomment with PHOENIX-7381
- //super.testUcfWithDisabledIndex1();
+ super.testUcfWithDisabledIndex1();
}
@Test
public void testUcfWithDisabledIndex2() throws Throwable {
- // Uncomment with PHOENIX-7381
- //super.testUcfWithDisabledIndex2();
+ super.testUcfWithDisabledIndex2();
}
@Test
public void testUcfWithDisabledIndex3() throws Throwable {
- // Uncomment with PHOENIX-7381
- //super.testUcfWithDisabledIndex3();
+ super.testUcfWithDisabledIndex3();
}
}