Repository: cassandra Updated Branches: refs/heads/cassandra-2.1 2dd244b43 -> c1b1d3bcc refs/heads/cassandra-2.2 3557d2e05 -> ab2b8a60c refs/heads/cassandra-3.0 f0cd3261b -> 5dbeef3f5 refs/heads/trunk c2acf4716 -> cb1a63474
Checking if an unlogged batch is local is inefficient patch by Stefania Alborghetti; reviewed by Paulo Motta for CASSANDRA-11529 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/c1b1d3bc Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/c1b1d3bc Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/c1b1d3bc Branch: refs/heads/cassandra-2.1 Commit: c1b1d3bccf30a7ee1deb633d2bc2dfbd7b9c542f Parents: 2dd244b Author: Stefania Alborghetti <[email protected]> Authored: Fri Apr 8 11:52:17 2016 +0800 Committer: Aleksey Yeschenko <[email protected]> Committed: Mon Apr 11 19:12:25 2016 +0100 ---------------------------------------------------------------------- CHANGES.txt | 1 + conf/cassandra.yaml | 4 +++ .../org/apache/cassandra/config/Config.java | 1 + .../cassandra/config/DatabaseDescriptor.java | 5 +++ .../cql3/statements/BatchStatement.java | 38 ++++++-------------- 5 files changed, 21 insertions(+), 28 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/c1b1d3bc/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 113da17..6385509 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 2.1.14 + * Checking if an unlogged batch is local is inefficient (CASSANDRA-11529) * Fix paging for COMPACT tables without clustering columns (CASSANDRA-11467) * Fix out-of-space error treatment in memtable flushing (CASSANDRA-11448) * Backport CASSANDRA-10859 (CASSANDRA-11415) http://git-wip-us.apache.org/repos/asf/cassandra/blob/c1b1d3bc/conf/cassandra.yaml ---------------------------------------------------------------------- diff --git a/conf/cassandra.yaml b/conf/cassandra.yaml index 0da4800..90c5be4 100644 --- a/conf/cassandra.yaml +++ b/conf/cassandra.yaml @@ -555,6 +555,10 @@ column_index_size_in_kb: 64 # Caution should be taken on increasing the size of this threshold as it can lead to node instability. batch_size_warn_threshold_in_kb: 5 + +# Log WARN on any batches not of type LOGGED than span across more partitions than this limit +unlogged_batch_across_partitions_warn_threshold: 10 + # Number of simultaneous compactions to allow, NOT including # validation "compactions" for anti-entropy repair. Simultaneous # compactions can help preserve read performance in a mixed read/write http://git-wip-us.apache.org/repos/asf/cassandra/blob/c1b1d3bc/src/java/org/apache/cassandra/config/Config.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/config/Config.java b/src/java/org/apache/cassandra/config/Config.java index 63bbf96..9ff7096 100644 --- a/src/java/org/apache/cassandra/config/Config.java +++ b/src/java/org/apache/cassandra/config/Config.java @@ -144,6 +144,7 @@ public class Config /* if the size of columns or super-columns are more than this, indexing will kick in */ public Integer column_index_size_in_kb = 64; public Integer batch_size_warn_threshold_in_kb = 5; + public Integer unlogged_batch_across_partitions_warn_threshold = 10; public Integer concurrent_compactors; public volatile Integer compaction_throughput_mb_per_sec = 16; public volatile Integer compaction_large_partition_warning_threshold_mb = 100; http://git-wip-us.apache.org/repos/asf/cassandra/blob/c1b1d3bc/src/java/org/apache/cassandra/config/DatabaseDescriptor.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java index 84381a0..166ce7e 100644 --- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java +++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java @@ -860,6 +860,11 @@ public class DatabaseDescriptor return conf.batch_size_warn_threshold_in_kb * 1024; } + public static int getUnloggedBatchAcrossPartitionsWarnThreshold() + { + return conf.unlogged_batch_across_partitions_warn_threshold; + } + public static Collection<String> getInitialTokens() { return tokensFromString(System.getProperty("cassandra.initial_token", conf.initial_token)); http://git-wip-us.apache.org/repos/asf/cassandra/blob/c1b1d3bc/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java b/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java index fb76c8d..ada8d91 100644 --- a/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java @@ -33,13 +33,10 @@ import org.apache.cassandra.config.ColumnDefinition; import org.apache.cassandra.cql3.*; import org.apache.cassandra.db.*; import org.apache.cassandra.db.composites.Composite; -import org.apache.cassandra.dht.Range; -import org.apache.cassandra.dht.Token; import org.apache.cassandra.exceptions.*; import org.apache.cassandra.service.ClientState; import org.apache.cassandra.service.QueryState; import org.apache.cassandra.service.StorageProxy; -import org.apache.cassandra.service.StorageService; import org.apache.cassandra.transport.messages.ResultMessage; import org.apache.cassandra.utils.NoSpamLogger; import org.apache.cassandra.utils.Pair; @@ -60,7 +57,8 @@ public class BatchStatement implements CQLStatement private final Attributes attrs; private final boolean hasConditions; private static final Logger logger = LoggerFactory.getLogger(BatchStatement.class); - private static final String unloggedBatchWarning = "Unlogged batch covering {} partition{} detected against table{} {}. You should use a logged batch for atomicity, or asynchronous writes for performance."; + private static final String unloggedBatchWarning = "Unlogged batch covering {} partitions detected against table{} {}. " + + "You should use a logged batch for atomicity, or asynchronous writes for performance."; /** * Creates a new BatchStatement from a list of statements and a @@ -263,40 +261,24 @@ public class BatchStatement implements CQLStatement Set<String> ksCfPairs = new HashSet<>(); Set<ByteBuffer> keySet = new HashSet<>(); - Map<String, Collection<Range<Token>>> localTokensByKs = new HashMap<>(); - boolean localMutationsOnly = true; - for (IMutation im : mutations) { keySet.add(im.key()); + for (ColumnFamily cf : im.getColumnFamilies()) ksCfPairs.add(String.format("%s.%s", cf.metadata().ksName, cf.metadata().cfName)); - - if (localMutationsOnly) - localMutationsOnly &= isMutationLocal(localTokensByKs, im); } - // CASSANDRA-9303: If we only have local mutations we do not warn - if (localMutationsOnly) - return; - - NoSpamLogger.log(logger, NoSpamLogger.Level.WARN, 1, TimeUnit.MINUTES, unloggedBatchWarning, - keySet.size(), keySet.size() == 1 ? "" : "s", - ksCfPairs.size() == 1 ? "" : "s", ksCfPairs); + // CASSANDRA-11529: log only if we have more than a threshold of keys, this was also suggested in the + // original ticket that introduced this warning, CASSANDRA-9282 + if (keySet.size() > DatabaseDescriptor.getUnloggedBatchAcrossPartitionsWarnThreshold()) + { + NoSpamLogger.log(logger, NoSpamLogger.Level.WARN, 1, TimeUnit.MINUTES, unloggedBatchWarning, + keySet.size(), ksCfPairs.size() == 1 ? "" : "s", ksCfPairs); + } } } - private boolean isMutationLocal(Map<String, Collection<Range<Token>>> localTokensByKs, IMutation mutation) - { - Collection<Range<Token>> localRanges = localTokensByKs.get(mutation.getKeyspaceName()); - if (localRanges == null) - { - localRanges = StorageService.instance.getLocalRanges(mutation.getKeyspaceName()); - localTokensByKs.put(mutation.getKeyspaceName(), localRanges); - } - - return Range.isInRanges(StorageService.getPartitioner().getToken(mutation.key()), localRanges); - } public ResultMessage execute(QueryState queryState, QueryOptions options) throws RequestExecutionException, RequestValidationException {
