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

brandonwilliams pushed a commit to branch cassandra-3.0
in repository https://gitbox.apache.org/repos/asf/cassandra.git


The following commit(s) were added to refs/heads/cassandra-3.0 by this push:
     new 87424da  Count bloom filter misses correctly.
87424da is described below

commit 87424dabd20acfdbb9a4489f289ec075ccfb87b0
Author: Aleksei Zotov <azotc...@gmail.com>
AuthorDate: Thu Jul 15 21:40:10 2021 +0400

    Count bloom filter misses correctly.
    
    Patch by Aleksei Zotov; reviewed by blerer and blambov for
    CASSANDRA-12922
---
 CHANGES.txt                                        |   1 +
 .../io/sstable/format/big/BigTableReader.java      |  14 ++-
 .../cassandra/io/sstable/SSTableReaderTest.java    | 105 ++++++++++++++++-----
 3 files changed, 96 insertions(+), 24 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index de54aad..d4e9322 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 3.0.25:
+ * Count bloom filter misses correctly (CASSANDRA-12922)
  * Reject token() in MV WHERE clause (CASSANDRA-13464)
  * Ensure java executable is on the path (CASSANDRA-14325)
  * Make speculative retry parameter case-insensitive for backward 
compatibility with 2.1 (CASSANDRA-16467)
diff --git 
a/src/java/org/apache/cassandra/io/sstable/format/big/BigTableReader.java 
b/src/java/org/apache/cassandra/io/sstable/format/big/BigTableReader.java
index 598f757..080cf04 100644
--- a/src/java/org/apache/cassandra/io/sstable/format/big/BigTableReader.java
+++ b/src/java/org/apache/cassandra/io/sstable/format/big/BigTableReader.java
@@ -138,6 +138,13 @@ public class BigTableReader extends SSTableReader
                                         boolean permitMatchPastLast,
                                         SSTableReadsListener listener)
     {
+        // Having no index file is impossible in a normal operation. The only 
way it might happen is running
+        // Scrubber that does not really rely onto this method.
+        if (ifile == null)
+        {
+            return null;
+        }
+
         if (op == Operator.EQ)
         {
             assert key instanceof DecoratedKey; // EQ only make sense if the 
key is a valid row key
@@ -158,6 +165,8 @@ public class BigTableReader extends SSTableReader
             RowIndexEntry cachedPosition = getCachedPosition(cacheKey, 
updateCacheAndStats);
             if (cachedPosition != null)
             {
+                // we do not need to track "true positive" for Bloom Filter 
here because it has been already tracked
+                // inside getCachedPosition method
                 listener.onSSTableSelected(this, cachedPosition, 
SelectionReason.KEY_CACHE_HIT);
                 Tracing.trace("Key cache hit for sstable {}", 
descriptor.generation);
                 return cachedPosition;
@@ -198,9 +207,6 @@ public class BigTableReader extends SSTableReader
 
         int effectiveInterval = 
indexSummary.getEffectiveIndexIntervalAfterIndex(sampledIndex);
 
-        if (ifile == null)
-            return null;
-
         // scan the on-disk index, starting at the nearest sampled position.
         // The check against IndexInterval is to be exit the loop in the EQ 
case when the key looked for is not present
         // (bloom filter false positive). But note that for non-EQ cases, we 
might need to check the first key of the
@@ -235,6 +241,8 @@ public class BigTableReader extends SSTableReader
                     exactMatch = (comparison == 0);
                     if (v < 0)
                     {
+                        if (op == SSTableReader.Operator.EQ && 
updateCacheAndStats)
+                            bloomFilterTracker.addFalsePositive();
                         listener.onSSTableSkipped(this, 
SkippingReason.PARTITION_INDEX_LOOKUP);
                         Tracing.trace("Partition index lookup allows skipping 
sstable {}", descriptor.generation);
                         return null;
diff --git a/test/unit/org/apache/cassandra/io/sstable/SSTableReaderTest.java 
b/test/unit/org/apache/cassandra/io/sstable/SSTableReaderTest.java
index 4ca6ec0..66155e5 100644
--- a/test/unit/org/apache/cassandra/io/sstable/SSTableReaderTest.java
+++ b/test/unit/org/apache/cassandra/io/sstable/SSTableReaderTest.java
@@ -70,7 +70,8 @@ public class SSTableReaderTest
     public static final String CF_STANDARD = "Standard1";
     public static final String CF_STANDARD2 = "Standard2";
     public static final String CF_INDEXED = "Indexed1";
-    public static final String CF_STANDARDLOWINDEXINTERVAL = 
"StandardLowIndexInterval";
+    public static final String CF_STANDARD_LOW_INDEX_INTERVAL = 
"StandardLowIndexInterval";
+    public static final String CF_STANDARD_SMALL_BLOOM_FILTER = 
"StandardSmallBloomFilter";
 
     private IPartitioner partitioner;
 
@@ -88,17 +89,21 @@ public class SSTableReaderTest
                                     SchemaLoader.standardCFMD(KEYSPACE1, 
CF_STANDARD),
                                     SchemaLoader.standardCFMD(KEYSPACE1, 
CF_STANDARD2),
                                     SchemaLoader.compositeIndexCFMD(KEYSPACE1, 
CF_INDEXED, true),
-                                    SchemaLoader.standardCFMD(KEYSPACE1, 
CF_STANDARDLOWINDEXINTERVAL)
+                                    SchemaLoader.standardCFMD(KEYSPACE1, 
CF_STANDARD_LOW_INDEX_INTERVAL)
                                                 .minIndexInterval(8)
                                                 .maxIndexInterval(256)
-                                                
.caching(CachingParams.CACHE_NOTHING));
+                                                
.caching(CachingParams.CACHE_NOTHING),
+                                    SchemaLoader.standardCFMD(KEYSPACE1, 
CF_STANDARD_SMALL_BLOOM_FILTER)
+                                                .minIndexInterval(4)
+                                                .maxIndexInterval(4)
+                                                .bloomFilterFpChance(0.99));
     }
 
     @Test
     public void testGetPositionsForRanges()
     {
         Keyspace keyspace = Keyspace.open(KEYSPACE1);
-        ColumnFamilyStore store = keyspace.getColumnFamilyStore("Standard2");
+        ColumnFamilyStore store = keyspace.getColumnFamilyStore(CF_STANDARD2);
         partitioner = store.getPartitioner();
 
         // insert data and compact to a single sstable
@@ -144,7 +149,7 @@ public class SSTableReaderTest
         try
         {
             Keyspace keyspace = Keyspace.open(KEYSPACE1);
-            ColumnFamilyStore store = 
keyspace.getColumnFamilyStore("Standard1");
+            ColumnFamilyStore store = 
keyspace.getColumnFamilyStore(CF_STANDARD);
             partitioner = store.getPartitioner();
 
             // insert a bunch of data and compact to a single sstable
@@ -188,7 +193,7 @@ public class SSTableReaderTest
     {
 
         Keyspace keyspace = Keyspace.open(KEYSPACE1);
-        ColumnFamilyStore store = keyspace.getColumnFamilyStore("Standard1");
+        ColumnFamilyStore store = keyspace.getColumnFamilyStore(CF_STANDARD);
         partitioner = store.getPartitioner();
 
         for (int j = 0; j < 100; j += 2)
@@ -216,7 +221,7 @@ public class SSTableReaderTest
     {
         // try to make sure CASSANDRA-8239 never happens again
         Keyspace keyspace = Keyspace.open(KEYSPACE1);
-        ColumnFamilyStore store = keyspace.getColumnFamilyStore("Standard1");
+        ColumnFamilyStore store = keyspace.getColumnFamilyStore(CF_STANDARD);
         partitioner = store.getPartitioner();
 
         for (int j = 0; j < 10; j++)
@@ -245,7 +250,7 @@ public class SSTableReaderTest
     public void testGetPositionsForRangesWithKeyCache()
     {
         Keyspace keyspace = Keyspace.open(KEYSPACE1);
-        ColumnFamilyStore store = keyspace.getColumnFamilyStore("Standard2");
+        ColumnFamilyStore store = keyspace.getColumnFamilyStore(CF_STANDARD2);
         partitioner = store.getPartitioner();
         CacheService.instance.keyCache.setCapacity(100);
 
@@ -298,10 +303,12 @@ public class SSTableReaderTest
         // check if opening and querying works
         assertIndexQueryWorks(store);
     }
+
+    @Test
     public void testGetPositionsKeyCacheStats()
     {
         Keyspace keyspace = Keyspace.open(KEYSPACE1);
-        ColumnFamilyStore store = keyspace.getColumnFamilyStore("Standard2");
+        ColumnFamilyStore store = keyspace.getColumnFamilyStore(CF_STANDARD2);
         partitioner = store.getPartitioner();
         CacheService.instance.keyCache.setCapacity(1000);
 
@@ -319,24 +326,80 @@ public class SSTableReaderTest
         CompactionManager.instance.performMaximal(store, false);
 
         SSTableReader sstable = store.getLiveSSTables().iterator().next();
+        // existing, non-cached key
         sstable.getPosition(k(2), SSTableReader.Operator.EQ);
+        assertEquals(1, sstable.getKeyCacheRequest());
         assertEquals(0, sstable.getKeyCacheHit());
-        assertEquals(1, sstable.getBloomFilterTruePositiveCount());
+        // existing, cached key
         sstable.getPosition(k(2), SSTableReader.Operator.EQ);
+        assertEquals(2, sstable.getKeyCacheRequest());
         assertEquals(1, sstable.getKeyCacheHit());
-        assertEquals(2, sstable.getBloomFilterTruePositiveCount());
-        sstable.getPosition(k(15), SSTableReader.Operator.EQ);
+        // non-existing key (it is specifically chosen to not be rejected by 
Bloom Filter check)
+        sstable.getPosition(k(14), SSTableReader.Operator.EQ);
+        assertEquals(3, sstable.getKeyCacheRequest());
         assertEquals(1, sstable.getKeyCacheHit());
-        assertEquals(2, sstable.getBloomFilterTruePositiveCount());
-
     }
 
+    @Test
+    public void testGetPositionsBloomFilterStats()
+    {
+        Keyspace keyspace = Keyspace.open(KEYSPACE1);
+        ColumnFamilyStore store = 
keyspace.getColumnFamilyStore(CF_STANDARD_SMALL_BLOOM_FILTER);
+        partitioner = store.getPartitioner();
+        CacheService.instance.keyCache.setCapacity(1000);
+
+        // insert data and compact to a single sstable
+        CompactionManager.instance.disableAutoCompaction();
+        for (int j = 0; j < 10; j++)
+        {
+            new RowUpdateBuilder(store.metadata, j, String.valueOf(j))
+                    .clustering("0")
+                    .add("val", ByteBufferUtil.EMPTY_BYTE_BUFFER)
+                    .build()
+                    .applyUnsafe();
+        }
+        store.forceBlockingFlush();
+        CompactionManager.instance.performMaximal(store, false);
+
+        SSTableReader sstable = store.getLiveSSTables().iterator().next();
+        // the keys are specifically chosen to cover certain use cases
+        // existing key is read from index
+        sstable.getPosition(k(2), SSTableReader.Operator.EQ);
+        assertEquals(1, sstable.getBloomFilterTruePositiveCount());
+        assertEquals(0, sstable.getBloomFilterTrueNegativeCount());
+        assertEquals(0, sstable.getBloomFilterFalsePositiveCount());
+        // existing key is read from Cache Key
+        sstable.getPosition(k(2), SSTableReader.Operator.EQ);
+        assertEquals(2, sstable.getBloomFilterTruePositiveCount());
+        assertEquals(0, sstable.getBloomFilterTrueNegativeCount());
+        assertEquals(0, sstable.getBloomFilterFalsePositiveCount());
+        // non-existing key is rejected by Bloom Filter check
+        sstable.getPosition(k(10), SSTableReader.Operator.EQ);
+        assertEquals(2, sstable.getBloomFilterTruePositiveCount());
+        assertEquals(1, sstable.getBloomFilterTrueNegativeCount());
+        assertEquals(0, sstable.getBloomFilterFalsePositiveCount());
+        // non-existing key is rejected by sstable keys range check
+        sstable.getPosition(k(99), SSTableReader.Operator.EQ);
+        assertEquals(2, sstable.getBloomFilterTruePositiveCount());
+        assertEquals(1, sstable.getBloomFilterTrueNegativeCount());
+        assertEquals(1, sstable.getBloomFilterFalsePositiveCount());
+        // non-existing key is rejected by index interval check
+        sstable.getPosition(k(14), SSTableReader.Operator.EQ);
+        assertEquals(2, sstable.getBloomFilterTruePositiveCount());
+        assertEquals(1, sstable.getBloomFilterTrueNegativeCount());
+        assertEquals(2, sstable.getBloomFilterFalsePositiveCount());
+        // non-existing key is rejected by index lookup check
+        sstable.getPosition(k(807), SSTableReader.Operator.EQ);
+        assertEquals(2, sstable.getBloomFilterTruePositiveCount());
+        assertEquals(1, sstable.getBloomFilterTrueNegativeCount());
+        assertEquals(3, sstable.getBloomFilterFalsePositiveCount());
+    }
 
     @Test
     public void testOpeningSSTable() throws Exception
     {
         String ks = KEYSPACE1;
-        String cf = "Standard1";
+        String cf = CF_STANDARD;
 
         // clear and create just one sstable for this test
         Keyspace keyspace = Keyspace.open(ks);
@@ -460,7 +523,7 @@ public class SSTableReaderTest
     public void testLoadingSummaryUsesCorrectPartitioner() throws Exception
     {
         Keyspace keyspace = Keyspace.open(KEYSPACE1);
-        ColumnFamilyStore store = keyspace.getColumnFamilyStore("Indexed1");
+        ColumnFamilyStore store = keyspace.getColumnFamilyStore(CF_INDEXED);
 
         new RowUpdateBuilder(store.metadata, System.currentTimeMillis(), "k1")
         .clustering("0")
@@ -494,7 +557,7 @@ public class SSTableReaderTest
     public void testGetScannerForNoIntersectingRanges() throws Exception
     {
         Keyspace keyspace = Keyspace.open(KEYSPACE1);
-        ColumnFamilyStore store = keyspace.getColumnFamilyStore("Standard1");
+        ColumnFamilyStore store = keyspace.getColumnFamilyStore(CF_STANDARD);
         partitioner = store.getPartitioner();
 
         new RowUpdateBuilder(store.metadata, 0, "k1")
@@ -520,7 +583,7 @@ public class SSTableReaderTest
     public void testGetPositionsForRangesFromTableOpenedForBulkLoading() 
throws IOException
     {
         Keyspace keyspace = Keyspace.open(KEYSPACE1);
-        ColumnFamilyStore store = keyspace.getColumnFamilyStore("Standard2");
+        ColumnFamilyStore store = keyspace.getColumnFamilyStore(CF_STANDARD2);
         partitioner = store.getPartitioner();
 
         // insert data and compact to a single sstable. The
@@ -563,7 +626,7 @@ public class SSTableReaderTest
     public void testIndexSummaryReplacement() throws IOException, 
ExecutionException, InterruptedException
     {
         Keyspace keyspace = Keyspace.open(KEYSPACE1);
-        final ColumnFamilyStore store = 
keyspace.getColumnFamilyStore("StandardLowIndexInterval"); // index interval of 
8, no key caching
+        final ColumnFamilyStore store = 
keyspace.getColumnFamilyStore(CF_STANDARD_LOW_INDEX_INTERVAL); // index 
interval of 8, no key caching
         CompactionManager.instance.disableAutoCompaction();
 
         final int NUM_PARTITIONS = 512;
@@ -642,7 +705,7 @@ public class SSTableReaderTest
     private void testIndexSummaryUpsampleAndReload0() throws Exception
     {
         Keyspace keyspace = Keyspace.open(KEYSPACE1);
-        final ColumnFamilyStore store = 
keyspace.getColumnFamilyStore("StandardLowIndexInterval"); // index interval of 
8, no key caching
+        final ColumnFamilyStore store = 
keyspace.getColumnFamilyStore(CF_STANDARD_LOW_INDEX_INTERVAL); // index 
interval of 8, no key caching
         CompactionManager.instance.disableAutoCompaction();
 
         final int NUM_PARTITIONS = 512;
@@ -674,7 +737,7 @@ public class SSTableReaderTest
 
     private void assertIndexQueryWorks(ColumnFamilyStore indexedCFS)
     {
-        assert "Indexed1".equals(indexedCFS.name);
+        assert CF_INDEXED.equals(indexedCFS.name);
 
         // make sure all sstables including 2ary indexes load from disk
         for (ColumnFamilyStore cfs : indexedCFS.concatWithIndexes())

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to