You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by ma...@apache.org on 2015/08/17 08:56:08 UTC

[1/3] cassandra git commit: Make getFullyExpiredSSTables less expensive.

Repository: cassandra
Updated Branches:
  refs/heads/cassandra-2.2 0f287c46f -> 31db093c4


Make getFullyExpiredSSTables less expensive.

Patch by marcuse; reviewed by yukim for CASSANDRA-9882


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/f53aacba
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/f53aacba
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/f53aacba

Branch: refs/heads/cassandra-2.2
Commit: f53aacba80de3c3441e1524be9498f6d15c5c411
Parents: 50e5802
Author: Marcus Eriksson <ma...@apache.org>
Authored: Mon Aug 17 08:29:45 2015 +0200
Committer: Marcus Eriksson <ma...@apache.org>
Committed: Mon Aug 17 08:29:45 2015 +0200

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../apache/cassandra/db/ColumnFamilyStore.java  | 55 +++++++++++++++++---
 .../DateTieredCompactionStrategy.java           | 13 ++++-
 .../DateTieredCompactionStrategyTest.java       |  1 +
 4 files changed, 60 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/f53aacba/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 7d84538..905445e 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 2.0.17
+ * Make getFullyExpiredSSTables less expensive (CASSANDRA-9882)
  * Add tool to find why expired sstables are not getting dropped (CASSANDRA-10015)
  * Remove erroneous pending HH tasks from tpstats/jmx (CASSANDRA-9129)
  * Don't cast expected bf size to an int (CASSANDRA-9959)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f53aacba/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
index c125cf0..eb688f7 100644
--- a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
+++ b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
@@ -1028,17 +1028,56 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean
         if (sstables.isEmpty())
             return ImmutableSet.of();
 
-        DataTracker.SSTableIntervalTree tree = data.getView().intervalTree;
-
-        Set<SSTableReader> results = null;
-        for (SSTableReader sstable : sstables)
+        List<SSTableReader> sortedByFirst = new ArrayList<>(sstables);
+        Collections.sort(sortedByFirst, new Comparator<SSTableReader>()
         {
-            Set<SSTableReader> overlaps = ImmutableSet.copyOf(tree.search(Interval.<RowPosition, SSTableReader>create(sstable.first, sstable.last)));
-            results = results == null ? overlaps : Sets.union(results, overlaps).immutableCopy();
+            @Override
+            public int compare(SSTableReader o1, SSTableReader o2)
+            {
+                return o1.first.compareTo(o2.first);
+            }
+        });
+        List<Interval<RowPosition, SSTableReader>> intervals = new ArrayList<>();
+        DecoratedKey first = null, last = null;
+        /*
+        normalize the intervals covered by the sstables
+        assume we have sstables like this (brackets representing first/last key in the sstable);
+        [   ] [   ]    [   ]   [  ]
+           [   ]         [       ]
+        then we can, instead of searching the interval tree 6 times, normalize the intervals and
+        only query the tree 2 times, for these intervals;
+        [         ]    [          ]
+         */
+        for (SSTableReader sstable : sortedByFirst)
+        {
+            if (first == null)
+            {
+                first = sstable.first;
+                last = sstable.last;
+            }
+            else
+            {
+                if (sstable.first.compareTo(last) <= 0) // we do overlap
+                {
+                    if (sstable.last.compareTo(last) > 0)
+                        last = sstable.last;
+                }
+                else
+                {
+                    intervals.add(Interval.<RowPosition, SSTableReader>create(first, last));
+                    first = sstable.first;
+                    last = sstable.last;
+                }
+            }
         }
-        results = Sets.difference(results, ImmutableSet.copyOf(sstables));
+        intervals.add(Interval.<RowPosition, SSTableReader>create(first, last));
+        DataTracker.SSTableIntervalTree tree = data.getView().intervalTree;
+        Set<SSTableReader> results = new HashSet<>();
+
+        for (Interval<RowPosition, SSTableReader> interval : intervals)
+            results.addAll(tree.search(interval));
 
-        return results;
+        return Sets.difference(results, ImmutableSet.copyOf(sstables));
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f53aacba/src/java/org/apache/cassandra/db/compaction/DateTieredCompactionStrategy.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/compaction/DateTieredCompactionStrategy.java b/src/java/org/apache/cassandra/db/compaction/DateTieredCompactionStrategy.java
index df28bd4..fea4995 100644
--- a/src/java/org/apache/cassandra/db/compaction/DateTieredCompactionStrategy.java
+++ b/src/java/org/apache/cassandra/db/compaction/DateTieredCompactionStrategy.java
@@ -18,6 +18,7 @@
 package org.apache.cassandra.db.compaction;
 
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Predicate;
@@ -37,6 +38,8 @@ public class DateTieredCompactionStrategy extends AbstractCompactionStrategy
 
     protected DateTieredCompactionStrategyOptions options;
     protected volatile int estimatedRemainingTasks;
+    @VisibleForTesting
+    long lastExpiredCheck;
 
     public DateTieredCompactionStrategy(ColumnFamilyStore cfs, Map<String, String> options)
     {
@@ -83,8 +86,14 @@ public class DateTieredCompactionStrategy extends AbstractCompactionStrategy
 
         Set<SSTableReader> uncompacting = cfs.getUncompactingSSTables();
 
-        // Find fully expired SSTables. Those will be included no matter what.
-        Set<SSTableReader> expired = CompactionController.getFullyExpiredSSTables(cfs, uncompacting, cfs.getOverlappingSSTables(uncompacting), gcBefore);
+        Set<SSTableReader> expired = Collections.emptySet();
+        // we only check for expired sstables every 10 minutes due to it being an expensive operation
+        if (System.currentTimeMillis() - lastExpiredCheck > TimeUnit.MINUTES.toMillis(10))
+        {
+            // Find fully expired SSTables. Those will be included no matter what.
+            expired = CompactionController.getFullyExpiredSSTables(cfs, uncompacting, cfs.getOverlappingSSTables(uncompacting), gcBefore);
+            lastExpiredCheck = System.currentTimeMillis();
+        }
         Set<SSTableReader> candidates = Sets.newHashSet(filterSuspectSSTables(uncompacting));
 
         List<SSTableReader> compactionCandidates = new ArrayList<>(getNextNonExpiredSSTables(Sets.difference(candidates, expired), gcBefore));

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f53aacba/test/unit/org/apache/cassandra/db/compaction/DateTieredCompactionStrategyTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/db/compaction/DateTieredCompactionStrategyTest.java b/test/unit/org/apache/cassandra/db/compaction/DateTieredCompactionStrategyTest.java
index d7caf6b..0084a16 100644
--- a/test/unit/org/apache/cassandra/db/compaction/DateTieredCompactionStrategyTest.java
+++ b/test/unit/org/apache/cassandra/db/compaction/DateTieredCompactionStrategyTest.java
@@ -308,6 +308,7 @@ public class DateTieredCompactionStrategyTest extends SchemaLoader
         DateTieredCompactionStrategy dtcs = new DateTieredCompactionStrategy(cfs, options);
         dtcs.startup();
         assertNull(dtcs.getNextBackgroundTask((int) (System.currentTimeMillis() / 1000)));
+        dtcs.lastExpiredCheck = 0;
         Thread.sleep(2000);
         AbstractCompactionTask t = dtcs.getNextBackgroundTask((int) (System.currentTimeMillis()/1000));
         assertNotNull(t);


[2/3] cassandra git commit: Merge branch 'cassandra-2.0' into cassandra-2.1

Posted by ma...@apache.org.
Merge branch 'cassandra-2.0' into cassandra-2.1

Conflicts:
	CHANGES.txt
	src/java/org/apache/cassandra/db/compaction/DateTieredCompactionStrategy.java


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/26ff1507
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/26ff1507
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/26ff1507

Branch: refs/heads/cassandra-2.2
Commit: 26ff15070eb67779050975a9ae07053f4b5e5b04
Parents: 7a6a509 f53aacb
Author: Marcus Eriksson <ma...@apache.org>
Authored: Mon Aug 17 08:30:17 2015 +0200
Committer: Marcus Eriksson <ma...@apache.org>
Committed: Mon Aug 17 08:30:17 2015 +0200

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../apache/cassandra/db/ColumnFamilyStore.java  | 55 +++++++++++++++++---
 .../DateTieredCompactionStrategy.java           | 13 ++++-
 .../DateTieredCompactionStrategyTest.java       |  1 +
 4 files changed, 60 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/26ff1507/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 5a76978,905445e..4626899
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,27 -1,5 +1,28 @@@
 -2.0.17
 +2.1.9
 + * (cqlsh) Allow encoding to be set through command line (CASSANDRA-10004)
 + * Add new JMX methods to change local compaction strategy (CASSANDRA-9965)
 + * Write hints for paxos commits (CASSANDRA-7342)
 + * (cqlsh) Fix timestamps before 1970 on Windows, always
 +   use UTC for timestamp display (CASSANDRA-10000)
 + * (cqlsh) Avoid overwriting new config file with old config
 +   when both exist (CASSANDRA-9777)
 + * Release snapshot selfRef when doing snapshot repair (CASSANDRA-9998)
 + * Cannot replace token does not exist - DN node removed as Fat Client (CASSANDRA-9871)
 + * Fix handling of enable/disable autocompaction (CASSANDRA-9899)
 + * Commit log segment recycling is disabled by default (CASSANDRA-9896)
 + * Add consistency level to tracing ouput (CASSANDRA-9827)
 + * Fix MarshalException when upgrading superColumn family (CASSANDRA-9582)
 + * Fix broken logging for "empty" flushes in Memtable (CASSANDRA-9837)
 + * Handle corrupt files on startup (CASSANDRA-9686)
 + * Fix clientutil jar and tests (CASSANDRA-9760)
 + * (cqlsh) Allow the SSL protocol version to be specified through the
 +   config file or environment variables (CASSANDRA-9544)
 + * Remove repair snapshot leftover on startup (CASSANDRA-7357)
 + * Use random nodes for batch log when only 2 racks (CASSANDRA-8735)
 + * Ensure atomicity inside thrift and stream session (CASSANDRA-7757)
 + * Fix nodetool info error when the node is not joined (CASSANDRA-9031)
 +Merged from 2.0:
+  * Make getFullyExpiredSSTables less expensive (CASSANDRA-9882)
   * Add tool to find why expired sstables are not getting dropped (CASSANDRA-10015)
   * Remove erroneous pending HH tasks from tpstats/jmx (CASSANDRA-9129)
   * Don't cast expected bf size to an int (CASSANDRA-9959)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/26ff1507/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/ColumnFamilyStore.java
index 7364528,eb688f7..25b3e57
--- a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
+++ b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
@@@ -1367,20 -1025,59 +1367,59 @@@ public class ColumnFamilyStore implemen
  
          // a normal compaction won't ever have an empty sstables list, but we create a skeleton
          // compaction controller for streaming, and that passes an empty list.
 -        if (sstables.isEmpty())
 +        if (!sstables.iterator().hasNext())
              return ImmutableSet.of();
  
-         DataTracker.SSTableIntervalTree tree = data.getView().intervalTree;
- 
-         Set<SSTableReader> results = null;
-         for (SSTableReader sstable : sstables)
 -        List<SSTableReader> sortedByFirst = new ArrayList<>(sstables);
++        List<SSTableReader> sortedByFirst = Lists.newArrayList(sstables);
+         Collections.sort(sortedByFirst, new Comparator<SSTableReader>()
+         {
+             @Override
+             public int compare(SSTableReader o1, SSTableReader o2)
+             {
+                 return o1.first.compareTo(o2.first);
+             }
+         });
+         List<Interval<RowPosition, SSTableReader>> intervals = new ArrayList<>();
+         DecoratedKey first = null, last = null;
+         /*
+         normalize the intervals covered by the sstables
+         assume we have sstables like this (brackets representing first/last key in the sstable);
+         [   ] [   ]    [   ]   [  ]
+            [   ]         [       ]
+         then we can, instead of searching the interval tree 6 times, normalize the intervals and
+         only query the tree 2 times, for these intervals;
+         [         ]    [          ]
+          */
+         for (SSTableReader sstable : sortedByFirst)
          {
-             Set<SSTableReader> overlaps = ImmutableSet.copyOf(tree.search(Interval.<RowPosition, SSTableReader>create(sstable.first, sstable.last)));
-             results = results == null ? overlaps : Sets.union(results, overlaps).immutableCopy();
+             if (first == null)
+             {
+                 first = sstable.first;
+                 last = sstable.last;
+             }
+             else
+             {
+                 if (sstable.first.compareTo(last) <= 0) // we do overlap
+                 {
+                     if (sstable.last.compareTo(last) > 0)
+                         last = sstable.last;
+                 }
+                 else
+                 {
+                     intervals.add(Interval.<RowPosition, SSTableReader>create(first, last));
+                     first = sstable.first;
+                     last = sstable.last;
+                 }
+             }
          }
-         results = Sets.difference(results, ImmutableSet.copyOf(sstables));
+         intervals.add(Interval.<RowPosition, SSTableReader>create(first, last));
+         DataTracker.SSTableIntervalTree tree = data.getView().intervalTree;
+         Set<SSTableReader> results = new HashSet<>();
+ 
+         for (Interval<RowPosition, SSTableReader> interval : intervals)
+             results.addAll(tree.search(interval));
  
-         return results;
+         return Sets.difference(results, ImmutableSet.copyOf(sstables));
      }
  
      /**

http://git-wip-us.apache.org/repos/asf/cassandra/blob/26ff1507/src/java/org/apache/cassandra/db/compaction/DateTieredCompactionStrategy.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/compaction/DateTieredCompactionStrategy.java
index dec0cef,fea4995..41c304b
--- a/src/java/org/apache/cassandra/db/compaction/DateTieredCompactionStrategy.java
+++ b/src/java/org/apache/cassandra/db/compaction/DateTieredCompactionStrategy.java
@@@ -35,9 -36,10 +36,11 @@@ public class DateTieredCompactionStrate
  {
      private static final Logger logger = LoggerFactory.getLogger(DateTieredCompactionStrategy.class);
  
 -    protected DateTieredCompactionStrategyOptions options;
 +    private final DateTieredCompactionStrategyOptions options;
      protected volatile int estimatedRemainingTasks;
 +    private final Set<SSTableReader> sstables = new HashSet<>();
+     @VisibleForTesting
+     long lastExpiredCheck;
  
      public DateTieredCompactionStrategy(ColumnFamilyStore cfs, Map<String, String> options)
      {
@@@ -76,13 -81,19 +79,19 @@@
       */
      private List<SSTableReader> getNextBackgroundSSTables(final int gcBefore)
      {
 -        if (!isEnabled() || cfs.getSSTables().isEmpty())
 +        if (cfs.getSSTables().isEmpty())
              return Collections.emptyList();
  
 -        Set<SSTableReader> uncompacting = cfs.getUncompactingSSTables();
 +        Set<SSTableReader> uncompacting = Sets.intersection(sstables, cfs.getUncompactingSSTables());
  
-         // Find fully expired SSTables. Those will be included no matter what.
-         Set<SSTableReader> expired = CompactionController.getFullyExpiredSSTables(cfs, uncompacting, cfs.getOverlappingSSTables(uncompacting), gcBefore);
+         Set<SSTableReader> expired = Collections.emptySet();
+         // we only check for expired sstables every 10 minutes due to it being an expensive operation
+         if (System.currentTimeMillis() - lastExpiredCheck > TimeUnit.MINUTES.toMillis(10))
+         {
+             // Find fully expired SSTables. Those will be included no matter what.
+             expired = CompactionController.getFullyExpiredSSTables(cfs, uncompacting, cfs.getOverlappingSSTables(uncompacting), gcBefore);
+             lastExpiredCheck = System.currentTimeMillis();
+         }
          Set<SSTableReader> candidates = Sets.newHashSet(filterSuspectSSTables(uncompacting));
  
          List<SSTableReader> compactionCandidates = new ArrayList<>(getNextNonExpiredSSTables(Sets.difference(candidates, expired), gcBefore));

http://git-wip-us.apache.org/repos/asf/cassandra/blob/26ff1507/test/unit/org/apache/cassandra/db/compaction/DateTieredCompactionStrategyTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/db/compaction/DateTieredCompactionStrategyTest.java
index 14e22f0,0084a16..cea835f
--- a/test/unit/org/apache/cassandra/db/compaction/DateTieredCompactionStrategyTest.java
+++ b/test/unit/org/apache/cassandra/db/compaction/DateTieredCompactionStrategyTest.java
@@@ -306,10 -306,9 +306,11 @@@ public class DateTieredCompactionStrate
          options.put(DateTieredCompactionStrategyOptions.TIMESTAMP_RESOLUTION_KEY, "MILLISECONDS");
          options.put(DateTieredCompactionStrategyOptions.MAX_SSTABLE_AGE_KEY, Double.toString((1d / (24 * 60 * 60))));
          DateTieredCompactionStrategy dtcs = new DateTieredCompactionStrategy(cfs, options);
 +        for (SSTableReader sstable : cfs.getSSTables())
 +            dtcs.addSSTable(sstable);
          dtcs.startup();
          assertNull(dtcs.getNextBackgroundTask((int) (System.currentTimeMillis() / 1000)));
+         dtcs.lastExpiredCheck = 0;
          Thread.sleep(2000);
          AbstractCompactionTask t = dtcs.getNextBackgroundTask((int) (System.currentTimeMillis()/1000));
          assertNotNull(t);


[3/3] cassandra git commit: Merge branch 'cassandra-2.1' into cassandra-2.2

Posted by ma...@apache.org.
Merge branch 'cassandra-2.1' into cassandra-2.2

Conflicts:
	src/java/org/apache/cassandra/db/ColumnFamilyStore.java


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/31db093c
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/31db093c
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/31db093c

Branch: refs/heads/cassandra-2.2
Commit: 31db093c478f29f000481e1368b3b2addff33eb2
Parents: 0f287c4 26ff150
Author: Marcus Eriksson <ma...@apache.org>
Authored: Mon Aug 17 08:34:24 2015 +0200
Committer: Marcus Eriksson <ma...@apache.org>
Committed: Mon Aug 17 08:34:24 2015 +0200

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../apache/cassandra/db/ColumnFamilyStore.java  | 55 +++++++++++++++++---
 .../DateTieredCompactionStrategy.java           | 13 ++++-
 .../DateTieredCompactionStrategyTest.java       |  1 +
 4 files changed, 61 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/31db093c/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 6bc671d,4626899..1299aa2
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -17,23 -9,8 +17,24 @@@ Merged from 2.1
   * Release snapshot selfRef when doing snapshot repair (CASSANDRA-9998)
   * Cannot replace token does not exist - DN node removed as Fat Client (CASSANDRA-9871)
   * Fix handling of enable/disable autocompaction (CASSANDRA-9899)
 - * Commit log segment recycling is disabled by default (CASSANDRA-9896)
   * Add consistency level to tracing ouput (CASSANDRA-9827)
 + * Remove repair snapshot leftover on startup (CASSANDRA-7357)
 + * Use random nodes for batch log when only 2 racks (CASSANDRA-8735)
 + * Ensure atomicity inside thrift and stream session (CASSANDRA-7757)
 + * Fix nodetool info error when the node is not joined (CASSANDRA-9031)
 +Merged from 2.0:
++ * Make getFullyExpiredSSTables less expensive (CASSANDRA-9882)
 + * Log when messages are dropped due to cross_node_timeout (CASSANDRA-9793)
 + * Don't track hotness when opening from snapshot for validation (CASSANDRA-9382)
 +
 +
 +2.2.0
 + * Allow the selection of columns together with aggregates (CASSANDRA-9767)
 + * Fix cqlsh copy methods and other windows specific issues (CASSANDRA-9795)
 + * Don't wrap byte arrays in SequentialWriter (CASSANDRA-9797)
 + * sum() and avg() functions missing for smallint and tinyint types (CASSANDRA-9671)
 + * Revert CASSANDRA-9542 (allow native functions in UDA) (CASSANDRA-9771)
 +Merged from 2.1:
   * Fix MarshalException when upgrading superColumn family (CASSANDRA-9582)
   * Fix broken logging for "empty" flushes in Memtable (CASSANDRA-9837)
   * Handle corrupt files on startup (CASSANDRA-9686)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/31db093c/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/db/ColumnFamilyStore.java
index 8bda6b2,25b3e57..343ecee
--- a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
+++ b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
@@@ -1389,17 -1370,56 +1389,58 @@@ public class ColumnFamilyStore implemen
          if (!sstables.iterator().hasNext())
              return ImmutableSet.of();
  
-         SSTableIntervalTree tree = data.getView().intervalTree;
 +
-         Set<SSTableReader> results = null;
-         for (SSTableReader sstable : sstables)
++
+         List<SSTableReader> sortedByFirst = Lists.newArrayList(sstables);
+         Collections.sort(sortedByFirst, new Comparator<SSTableReader>()
+         {
+             @Override
+             public int compare(SSTableReader o1, SSTableReader o2)
+             {
+                 return o1.first.compareTo(o2.first);
+             }
+         });
+         List<Interval<RowPosition, SSTableReader>> intervals = new ArrayList<>();
+         DecoratedKey first = null, last = null;
+         /*
+         normalize the intervals covered by the sstables
+         assume we have sstables like this (brackets representing first/last key in the sstable);
+         [   ] [   ]    [   ]   [  ]
+            [   ]         [       ]
+         then we can, instead of searching the interval tree 6 times, normalize the intervals and
+         only query the tree 2 times, for these intervals;
+         [         ]    [          ]
+          */
+         for (SSTableReader sstable : sortedByFirst)
          {
-             Set<SSTableReader> overlaps = ImmutableSet.copyOf(tree.search(Interval.<RowPosition, SSTableReader>create(sstable.first, sstable.last)));
-             results = results == null ? overlaps : Sets.union(results, overlaps).immutableCopy();
+             if (first == null)
+             {
+                 first = sstable.first;
+                 last = sstable.last;
+             }
+             else
+             {
+                 if (sstable.first.compareTo(last) <= 0) // we do overlap
+                 {
+                     if (sstable.last.compareTo(last) > 0)
+                         last = sstable.last;
+                 }
+                 else
+                 {
+                     intervals.add(Interval.<RowPosition, SSTableReader>create(first, last));
+                     first = sstable.first;
+                     last = sstable.last;
+                 }
+             }
          }
-         results = Sets.difference(results, ImmutableSet.copyOf(sstables));
+         intervals.add(Interval.<RowPosition, SSTableReader>create(first, last));
 -        DataTracker.SSTableIntervalTree tree = data.getView().intervalTree;
++        SSTableIntervalTree tree = data.getView().intervalTree;
+         Set<SSTableReader> results = new HashSet<>();
+ 
+         for (Interval<RowPosition, SSTableReader> interval : intervals)
+             results.addAll(tree.search(interval));
  
-         return results;
+         return Sets.difference(results, ImmutableSet.copyOf(sstables));
      }
  
      /**

http://git-wip-us.apache.org/repos/asf/cassandra/blob/31db093c/src/java/org/apache/cassandra/db/compaction/DateTieredCompactionStrategy.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/31db093c/test/unit/org/apache/cassandra/db/compaction/DateTieredCompactionStrategyTest.java
----------------------------------------------------------------------