You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@quickstep.apache.org by hb...@apache.org on 2016/10/16 20:47:20 UTC

[1/9] incubator-quickstep git commit: Remove unnecessary code from resize() [Forced Update!]

Repository: incubator-quickstep
Updated Branches:
  refs/heads/partitioned-aggregate-new f6ab30f37 -> aaba94624 (forced update)


Remove unnecessary code from resize()

- In resize, all the values are moved from original hash table are
  copied to the new hash table using memcpy().
- Removed the for loop where values are constructed using 'new' operator, as
  all the values are trivially constructible in the specialized
  aggregation hash table implementation.


Project: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/commit/2e023333
Tree: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/tree/2e023333
Diff: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/diff/2e023333

Branch: refs/heads/partitioned-aggregate-new
Commit: 2e0233333eb41d8f21f9e3f19029d08be8a01fdc
Parents: ad1f8c4
Author: Harshad Deshmukh <hb...@apache.org>
Authored: Wed Oct 5 16:05:05 2016 -0500
Committer: Harshad Deshmukh <hb...@apache.org>
Committed: Thu Oct 6 14:21:07 2016 -0500

----------------------------------------------------------------------
 storage/FastSeparateChainingHashTable.hpp | 22 +++-------------------
 1 file changed, 3 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/2e023333/storage/FastSeparateChainingHashTable.hpp
----------------------------------------------------------------------
diff --git a/storage/FastSeparateChainingHashTable.hpp b/storage/FastSeparateChainingHashTable.hpp
index 886a8ca..a41535c 100644
--- a/storage/FastSeparateChainingHashTable.hpp
+++ b/storage/FastSeparateChainingHashTable.hpp
@@ -1450,27 +1450,11 @@ void FastSeparateChainingHashTable<
   //       d. Relative pointers are not used with resizable hash tables.
   //     4. If values are not trivially copyable, then we invoke ValueT's copy
   //        or move constructor with placement new.
+  // NOTE(harshad) - Regarding point 4 above, as this is a specialized
+  // hash table implemented for aggregation, the values are trivially copyable,
+  // therefore we don't need to invoke payload values' copy/move constructors.
   std::memcpy(resized_buckets, buckets_, original_buckets_used * bucket_size_);
 
-  // TODO(chasseur): std::is_trivially_copyable is not yet implemented in
-  // GCC 4.8.3, so we assume we need to invoke ValueT's copy or move
-  // constructor, even though the plain memcpy above could suffice for many
-  // possible ValueTs.
-  void *current_value_original = static_cast<char *>(buckets_) + kValueOffset;
-  void *current_value_resized =
-      static_cast<char *>(resized_buckets) + kValueOffset;
-  for (std::size_t bucket_num = 0; bucket_num < original_buckets_used;
-       ++bucket_num) {
-    // Use a move constructor if available to avoid a deep-copy, since resizes
-    // always succeed.
-    new (current_value_resized) std::uint8_t(
-        std::move(*static_cast<std::uint8_t *>(current_value_original)));
-    current_value_original =
-        static_cast<char *>(current_value_original) + bucket_size_;
-    current_value_resized =
-        static_cast<char *>(current_value_resized) + bucket_size_;
-  }
-
   // Copy over variable-length key components, if any.
   if (original_variable_storage_used > 0) {
     DEBUG_ASSERT(original_variable_storage_used ==


[7/9] incubator-quickstep git commit: Add unit test for PackedRowStore ColumnAccessor

Posted by hb...@apache.org.
Add unit test for PackedRowStore ColumnAccessor


Project: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/commit/262ad5a6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/tree/262ad5a6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/diff/262ad5a6

Branch: refs/heads/partitioned-aggregate-new
Commit: 262ad5a6bf7bdff976a87d6858807bba8a1c0d8d
Parents: 743f6b0
Author: Saket Saurabh <ss...@cs.wisc.edu>
Authored: Thu Sep 22 16:44:19 2016 -0500
Committer: Saket Saurabh <ss...@cs.wisc.edu>
Committed: Tue Oct 11 11:36:57 2016 -0500

----------------------------------------------------------------------
 ...kedRowStoreTupleStorageSubBlock_unittest.cpp | 40 ++++++++++++++++++++
 1 file changed, 40 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/262ad5a6/storage/tests/PackedRowStoreTupleStorageSubBlock_unittest.cpp
----------------------------------------------------------------------
diff --git a/storage/tests/PackedRowStoreTupleStorageSubBlock_unittest.cpp b/storage/tests/PackedRowStoreTupleStorageSubBlock_unittest.cpp
index 304fa07..a6f6606 100644
--- a/storage/tests/PackedRowStoreTupleStorageSubBlock_unittest.cpp
+++ b/storage/tests/PackedRowStoreTupleStorageSubBlock_unittest.cpp
@@ -37,6 +37,8 @@
 #include "storage/StorageErrors.hpp"
 #include "storage/TupleIdSequence.hpp"
 #include "storage/TupleStorageSubBlock.hpp"
+#include "storage/ValueAccessor.hpp"
+#include "storage/ValueAccessorUtil.hpp"
 #include "types/CharType.hpp"
 #include "types/DoubleType.hpp"
 #include "types/IntType.hpp"
@@ -248,6 +250,36 @@ class PackedRowStoreTupleStorageSubBlockTest : public ::testing::TestWithParam<b
                                                     tuple_store_->getAttributeValueTyped(tid, 2)));
     }
   }
+  
+  template<bool check_null>
+  void checkColumnAccessor() {
+    initializeNewBlock(kSubBlockSize);
+    fillBlockWithSampleData();
+    ASSERT_TRUE(tuple_store_->isPacked());
+    std::unique_ptr<ValueAccessor> accessor(tuple_store_->createValueAccessor());
+    attribute_id  value_accessor_id = 0;
+    tuple_id tid = 0;
+    InvokeOnAnyValueAccessor(accessor.get(),
+                             [&](auto *accessor) -> void {  // NOLINT(build/c++11)
+      accessor->beginIteration();
+      ASSERT_TRUE(accessor->isColumnAccessorSupported());
+      std::unique_ptr<const ColumnAccessor<check_null>>
+      column_accessor(accessor->template getColumnAccessor<check_null>(value_accessor_id));
+      ASSERT_TRUE(column_accessor != nullptr);
+      while (accessor->next()) {
+        const void *va_value = column_accessor->getUntypedValue();
+        std::unique_ptr<Tuple> expected_tuple(createSampleTuple(tid));
+         
+        if (expected_tuple->getAttributeValue(value_accessor_id).isNull()) {
+          ASSERT_TRUE(va_value == nullptr);
+        } else {
+          ASSERT_TRUE(eq_comp_int_->compareDataPtrs(expected_tuple->getAttributeValue(value_accessor_id).getDataPtr(),
+                                                    va_value));
+        }
+        ++tid;
+      }
+    });
+  }
 
   std::unique_ptr<CatalogRelation> relation_;
   ScopedBuffer tuple_store_memory_;
@@ -374,6 +406,14 @@ TEST_P(PackedRowStoreTupleStorageSubBlockTest, InsertInBatchTest) {
   EXPECT_EQ(row_capacity - 1, tuple_store_->getMaxTupleID());
   EXPECT_EQ(row_capacity, tuple_store_->numTuples());
 }
+  
+TEST_P(PackedRowStoreTupleStorageSubBlockTest, ColumnAccessorTest) {
+  if (GetParam()) { // when true, the attributes can be nullable.
+    checkColumnAccessor<true>();
+  } else { // when false, the attributes are non-null.
+    checkColumnAccessor<false>();
+  }
+}
 
 TEST_P(PackedRowStoreTupleStorageSubBlockTest, GetAttributeValueTest) {
   initializeNewBlock(kSubBlockSize);


[3/9] incubator-quickstep git commit: Minor bug fix in AggregationOperationState

Posted by hb...@apache.org.
Minor bug fix in AggregationOperationState

- Replace getHashTable() call with getHashTableFast() call.


Project: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/commit/80af2332
Tree: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/tree/80af2332
Diff: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/diff/80af2332

Branch: refs/heads/partitioned-aggregate-new
Commit: 80af23327f1f19d2f55457f949917a3cb2e467a5
Parents: b5dcb6d
Author: Harshad Deshmukh <hb...@apache.org>
Authored: Mon Oct 10 14:13:09 2016 -0500
Committer: Harshad Deshmukh <hb...@apache.org>
Committed: Mon Oct 10 14:13:09 2016 -0500

----------------------------------------------------------------------
 storage/AggregationOperationState.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/80af2332/storage/AggregationOperationState.cpp
----------------------------------------------------------------------
diff --git a/storage/AggregationOperationState.cpp b/storage/AggregationOperationState.cpp
index 073b813..7908db1 100644
--- a/storage/AggregationOperationState.cpp
+++ b/storage/AggregationOperationState.cpp
@@ -537,7 +537,7 @@ void AggregationOperationState::finalizeHashTable(
       // However for aggregateOnDistinctifyHashTableForGroupBy to work
       // correctly, we should create an empty group by hash table.
       AggregationStateHashTableBase *new_hash_table =
-          group_by_hashtable_pool_->getHashTable();
+          group_by_hashtable_pool_->getHashTableFast();
       group_by_hashtable_pool_->returnHashTable(new_hash_table);
       hash_tables = group_by_hashtable_pool_->getAllHashTables();
     }


[4/9] incubator-quickstep git commit: Try fix for clang memory problems

Posted by hb...@apache.org.
Try fix for clang memory problems

Project: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/commit/17ffbb05
Tree: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/tree/17ffbb05
Diff: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/diff/17ffbb05

Branch: refs/heads/partitioned-aggregate-new
Commit: 17ffbb05d53e33ff846a1a6d774accadbd8e1b20
Parents: e4de241
Author: Saket Saurabh <sa...@users.noreply.github.com>
Authored: Tue Oct 11 10:06:42 2016 -0500
Committer: Saket Saurabh <ss...@cs.wisc.edu>
Committed: Tue Oct 11 11:36:57 2016 -0500

----------------------------------------------------------------------
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/17ffbb05/.travis.yml
----------------------------------------------------------------------
diff --git a/.travis.yml b/.travis.yml
index 54a0c8a..6895c0d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -21,7 +21,7 @@ env:
   - BUILD_TYPE=Release VECTOR_COPY_ELISION_LEVEL=selection
 
 install:
-  - if [ "$CC" = "gcc" ]; then
+  - if [ "$CC" = "gcc" ] || [[ "$BUILD_TYPE" = "Release" &&  "$VECTOR_COPY_ELISION_LEVEL" = "selection" ]]; then
       export MAKE_JOBS=1;
     else
       export MAKE_JOBS=2;


[9/9] incubator-quickstep git commit: Support for performing partitioned aggregation.

Posted by hb...@apache.org.
Support for performing partitioned aggregation.

- Used for creating a pool of hash tables such that each hash table
  belongs to a unique partition.
- The partitioning is done on the group-by keys.
- Wrote a utility function to compute composite hash of a group of
  TypedValues.
- Added a check for whether the aggregation is partitioned or not.
- The conditions for whether the aggregation can be partitioned
  are as follows:
  1. The query has a GROUP BY clause.
  2. There are no aggrgeations with a DISTINCT clause.
  3. The estimated number of groups are greater than a pre-defined
  threshold.
  4. The query has at least one aggregation function.
- Method for partitioned aggregation with GROUP BY
- StorageBlock now provides a method for performing GROUP BY aggregation
  in a partitioned way.
- The Tuple class now supports a method to compute the hash of the entire
  tuple (i.e. hash key is the composite key made up of all the
  attributes in the tuple).
- AggregationOperationState calls appropriate method (i.e.
  aggregateGroupBy or aggregateGroupByPartitioned) based on the way in
  which aggregation is being performed.
- Set each hash table's size estimate to be overall estimate divided by
  the number of partitions.


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

Branch: refs/heads/partitioned-aggregate-new
Commit: aaba94624a9a9240de58b5928f8d54b1ca3c66e5
Parents: 17ffbb0
Author: Harshad Deshmukh <hb...@apache.org>
Authored: Wed Sep 21 11:43:39 2016 -0500
Committer: Harshad Deshmukh <hb...@apache.org>
Committed: Sun Oct 16 15:46:49 2016 -0500

----------------------------------------------------------------------
 .../FinalizeAggregationOperator.cpp             |  35 ++-
 .../FinalizeAggregationOperator.hpp             |   9 +-
 storage/AggregationOperationState.cpp           | 135 ++++++++---
 storage/AggregationOperationState.hpp           |  52 +++++
 storage/CMakeLists.txt                          |  12 +
 storage/HashTablePool.hpp                       |  17 +-
 storage/PartitionedHashTablePool.hpp            | 224 +++++++++++++++++++
 storage/StorageBlock.cpp                        | 115 ++++++++++
 storage/StorageBlock.hpp                        |  43 ++++
 types/containers/CMakeLists.txt                 |   1 +
 types/containers/Tuple.hpp                      |   8 +
 utility/CMakeLists.txt                          |   6 +
 utility/CompositeHash.hpp                       |  52 +++++
 13 files changed, 661 insertions(+), 48 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/aaba9462/relational_operators/FinalizeAggregationOperator.cpp
----------------------------------------------------------------------
diff --git a/relational_operators/FinalizeAggregationOperator.cpp b/relational_operators/FinalizeAggregationOperator.cpp
index 7e337de..55d1357 100644
--- a/relational_operators/FinalizeAggregationOperator.cpp
+++ b/relational_operators/FinalizeAggregationOperator.cpp
@@ -41,12 +41,29 @@ bool FinalizeAggregationOperator::getAllWorkOrders(
 
   if (blocking_dependencies_met_ && !started_) {
     started_ = true;
-    container->addNormalWorkOrder(
-        new FinalizeAggregationWorkOrder(
-            query_id_,
-            query_context->getAggregationState(aggr_state_index_),
-            query_context->getInsertDestination(output_destination_index_)),
-        op_index_);
+    DCHECK(query_context->getAggregationState(aggr_state_index_) != nullptr);
+    if (query_context->getAggregationState(aggr_state_index_)->isAggregatePartitioned()) {
+      // The same AggregationState is shared across all the WorkOrders.
+      for (std::size_t part_id = 0;
+           part_id < query_context->getAggregationState(aggr_state_index_)
+                         ->getNumPartitions();
+           ++part_id) {
+        container->addNormalWorkOrder(
+            new FinalizeAggregationWorkOrder(
+                query_id_,
+                query_context->getAggregationState(aggr_state_index_),
+                query_context->getInsertDestination(output_destination_index_),
+                static_cast<int>(part_id)),
+            op_index_);
+      }
+    } else {
+      container->addNormalWorkOrder(
+          new FinalizeAggregationWorkOrder(
+              query_id_,
+              query_context->getAggregationState(aggr_state_index_),
+              query_context->getInsertDestination(output_destination_index_)),
+          op_index_);
+    }
   }
   return started_;
 }
@@ -70,7 +87,11 @@ bool FinalizeAggregationOperator::getAllWorkOrderProtos(WorkOrderProtosContainer
 
 
 void FinalizeAggregationWorkOrder::execute() {
-  state_->finalizeAggregate(output_destination_);
+  if (state_->isAggregatePartitioned()) {
+    state_->finalizeAggregatePartitioned(part_id_, output_destination_);
+  } else {
+    state_->finalizeAggregate(output_destination_);
+  }
 }
 
 }  // namespace quickstep

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/aaba9462/relational_operators/FinalizeAggregationOperator.hpp
----------------------------------------------------------------------
diff --git a/relational_operators/FinalizeAggregationOperator.hpp b/relational_operators/FinalizeAggregationOperator.hpp
index 0aeac2a..ae7127a 100644
--- a/relational_operators/FinalizeAggregationOperator.hpp
+++ b/relational_operators/FinalizeAggregationOperator.hpp
@@ -119,13 +119,17 @@ class FinalizeAggregationWorkOrder : public WorkOrder {
    * @param state The AggregationState to use.
    * @param output_destination The InsertDestination to insert aggregation
    *        results.
+   * @param part_id The partition ID for which the Finalize aggregation work
+   *        order is issued. Ignore if aggregation is not partitioned.
    */
   FinalizeAggregationWorkOrder(const std::size_t query_id,
                                AggregationOperationState *state,
-                               InsertDestination *output_destination)
+                               InsertDestination *output_destination,
+                               const int part_id = -1)
       : WorkOrder(query_id),
         state_(DCHECK_NOTNULL(state)),
-        output_destination_(DCHECK_NOTNULL(output_destination)) {}
+        output_destination_(DCHECK_NOTNULL(output_destination)),
+        part_id_(part_id) {}
 
   ~FinalizeAggregationWorkOrder() override {}
 
@@ -134,6 +138,7 @@ class FinalizeAggregationWorkOrder : public WorkOrder {
  private:
   AggregationOperationState *state_;
   InsertDestination *output_destination_;
+  const int part_id_;
 
   DISALLOW_COPY_AND_ASSIGN(FinalizeAggregationWorkOrder);
 };

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/aaba9462/storage/AggregationOperationState.cpp
----------------------------------------------------------------------
diff --git a/storage/AggregationOperationState.cpp b/storage/AggregationOperationState.cpp
index 7908db1..beb1899 100644
--- a/storage/AggregationOperationState.cpp
+++ b/storage/AggregationOperationState.cpp
@@ -69,6 +69,8 @@ AggregationOperationState::AggregationOperationState(
     const std::vector<HashTableImplType> &distinctify_hash_table_impl_types,
     StorageManager *storage_manager)
     : input_relation_(input_relation),
+      is_aggregate_partitioned_(checkAggregatePartitioned(
+          estimated_num_entries, is_distinct, group_by, aggregate_functions)),
       predicate_(predicate),
       group_by_list_(std::move(group_by)),
       arguments_(std::move(arguments)),
@@ -166,18 +168,16 @@ AggregationOperationState::AggregationOperationState(
       }
 
       // Initialize the corresponding distinctify hash table if this is a
-      // DISTINCT
-      // aggregation.
+      // DISTINCT aggregation.
       if (*is_distinct_it) {
         std::vector<const Type *> key_types(group_by_types);
         key_types.insert(
             key_types.end(), argument_types.begin(), argument_types.end());
         // TODO(jianqiao): estimated_num_entries is quite inaccurate for
-        // estimating
-        // the number of entries in the distinctify hash table. We may estimate
-        // for each distinct aggregation an estimated_num_distinct_keys value
-        // during
-        // query optimization, if it worths.
+        // estimating the number of entries in the distinctify hash table.
+        // We may estimate for each distinct aggregation an
+        // estimated_num_distinct_keys value during query optimization, if it's
+        // worth.
         distinctify_hashtables_.emplace_back(
             AggregationStateFastHashTableFactory::CreateResizable(
                 *distinctify_hash_table_impl_types_it,
@@ -193,14 +193,24 @@ AggregationOperationState::AggregationOperationState(
     }
 
     if (!group_by_handles.empty()) {
-      // Aggregation with GROUP BY: create a HashTable pool for per-group
-      // states.
-      group_by_hashtable_pool_.reset(new HashTablePool(estimated_num_entries,
-                                                       hash_table_impl_type,
-                                                       group_by_types,
-                                                       payload_sizes,
-                                                       group_by_handles,
-                                                       storage_manager));
+      // Aggregation with GROUP BY: create a HashTable pool.
+      if (!is_aggregate_partitioned_) {
+        group_by_hashtable_pool_.reset(new HashTablePool(estimated_num_entries,
+                                                         hash_table_impl_type,
+                                                         group_by_types,
+                                                         payload_sizes,
+                                                         group_by_handles,
+                                                         storage_manager));
+      } else {
+        partitioned_group_by_hashtable_pool_.reset(
+            new PartitionedHashTablePool(estimated_num_entries,
+                                         kNumPartitionsForAggregate,
+                                         hash_table_impl_type,
+                                         group_by_types,
+                                         payload_sizes,
+                                         group_by_handles,
+                                         storage_manager));
+      }
     }
   }
 }
@@ -439,20 +449,30 @@ void AggregationOperationState::aggregateBlockHashTable(
     }
   }
 
-  // Call StorageBlock::aggregateGroupBy() to aggregate this block's values
-  // directly into the (threadsafe) shared global HashTable for this
-  // aggregate.
-  DCHECK(group_by_hashtable_pool_ != nullptr);
-  AggregationStateHashTableBase *agg_hash_table =
+  if (!is_aggregate_partitioned_) {
+    // Call StorageBlock::aggregateGroupBy() to aggregate this block's values
+    // directly into the (threadsafe) shared global HashTable for this
+    // aggregate.
+    DCHECK(group_by_hashtable_pool_ != nullptr);
+    AggregationStateHashTableBase *agg_hash_table =
       group_by_hashtable_pool_->getHashTableFast();
-  DCHECK(agg_hash_table != nullptr);
-  block->aggregateGroupBy(arguments_,
-                          group_by_list_,
-                          predicate_.get(),
-                          agg_hash_table,
-                          &reuse_matches,
-                          &reuse_group_by_vectors);
-  group_by_hashtable_pool_->returnHashTable(agg_hash_table);
+    DCHECK(agg_hash_table != nullptr);
+    block->aggregateGroupBy(arguments_,
+        group_by_list_,
+        predicate_.get(),
+        agg_hash_table,
+        &reuse_matches,
+        &reuse_group_by_vectors);
+    group_by_hashtable_pool_->returnHashTable(agg_hash_table);
+  } else {
+    block->aggregateGroupByPartitioned(
+        arguments_,
+        group_by_list_,
+        predicate_.get(),
+        &reuse_matches,
+        &reuse_group_by_vectors,
+        partitioned_group_by_hashtable_pool_.get());
+  }
 }
 
 void AggregationOperationState::finalizeSingleState(
@@ -595,4 +615,63 @@ void AggregationOperationState::finalizeHashTable(
   output_destination->bulkInsertTuples(&complete_result);
 }
 
+void AggregationOperationState::finalizeAggregatePartitioned(
+    const std::size_t partition_id, InsertDestination *output_destination) {
+  // Each element of 'group_by_keys' is a vector of values for a particular
+  // group (which is also the prefix of the finalized Tuple for that group).
+  std::vector<std::vector<TypedValue>> group_by_keys;
+
+  // Collect per-aggregate finalized values.
+  std::vector<std::unique_ptr<ColumnVector>> final_values;
+  for (std::size_t agg_idx = 0; agg_idx < handles_.size(); ++agg_idx) {
+    AggregationStateHashTableBase *hash_table =
+        partitioned_group_by_hashtable_pool_->getHashTable(partition_id);
+    ColumnVector *agg_result_col = handles_[agg_idx]->finalizeHashTable(
+        *hash_table, &group_by_keys, agg_idx);
+    if (agg_result_col != nullptr) {
+      final_values.emplace_back(agg_result_col);
+    }
+  }
+
+  // Reorganize 'group_by_keys' in column-major order so that we can make a
+  // ColumnVectorsValueAccessor to bulk-insert results.
+  //
+  // TODO(chasseur): Shuffling around the GROUP BY keys like this is suboptimal
+  // if there is only one aggregate. The need to do this should hopefully go
+  // away when we work out storing composite structures for multiple aggregates
+  // in a single HashTable.
+  std::vector<std::unique_ptr<ColumnVector>> group_by_cvs;
+  std::size_t group_by_element_idx = 0;
+  for (const std::unique_ptr<const Scalar> &group_by_element : group_by_list_) {
+    const Type &group_by_type = group_by_element->getType();
+    if (NativeColumnVector::UsableForType(group_by_type)) {
+      NativeColumnVector *element_cv = new NativeColumnVector(group_by_type, group_by_keys.size());
+      group_by_cvs.emplace_back(element_cv);
+      for (std::vector<TypedValue> &group_key : group_by_keys) {
+        element_cv->appendTypedValue(std::move(group_key[group_by_element_idx]));
+      }
+    } else {
+      IndirectColumnVector *element_cv = new IndirectColumnVector(group_by_type, group_by_keys.size());
+      group_by_cvs.emplace_back(element_cv);
+      for (std::vector<TypedValue> &group_key : group_by_keys) {
+        element_cv->appendTypedValue(std::move(group_key[group_by_element_idx]));
+      }
+    }
+    ++group_by_element_idx;
+  }
+
+  // Stitch together a ColumnVectorsValueAccessor combining the GROUP BY keys
+  // and the finalized aggregates.
+  ColumnVectorsValueAccessor complete_result;
+  for (std::unique_ptr<ColumnVector> &group_by_cv : group_by_cvs) {
+    complete_result.addColumn(group_by_cv.release());
+  }
+  for (std::unique_ptr<ColumnVector> &final_value_cv : final_values) {
+    complete_result.addColumn(final_value_cv.release());
+  }
+
+  // Bulk-insert the complete result.
+  output_destination->bulkInsertTuples(&complete_result);
+}
+
 }  // namespace quickstep

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/aaba9462/storage/AggregationOperationState.hpp
----------------------------------------------------------------------
diff --git a/storage/AggregationOperationState.hpp b/storage/AggregationOperationState.hpp
index cbbfc22..4dae8c7 100644
--- a/storage/AggregationOperationState.hpp
+++ b/storage/AggregationOperationState.hpp
@@ -32,6 +32,7 @@
 #include "storage/AggregationOperationState.pb.h"
 #include "storage/HashTableBase.hpp"
 #include "storage/HashTablePool.hpp"
+#include "storage/PartitionedHashTablePool.hpp"
 #include "storage/StorageBlockInfo.hpp"
 #include "utility/Macros.hpp"
 
@@ -167,12 +168,31 @@ class AggregationOperationState {
    **/
   void finalizeAggregate(InsertDestination *output_destination);
 
+  void finalizeAggregatePartitioned(
+      const std::size_t partition_id, InsertDestination *output_destination);
+
   static void mergeGroupByHashTables(AggregationStateHashTableBase *src,
                                      AggregationStateHashTableBase *dst);
 
+  bool isAggregatePartitioned() const {
+    return is_aggregate_partitioned_;
+  }
+
+  /**
+   * @note This method is relevant only when the aggregate is partitioned.
+   **/
+  std::size_t getNumPartitions() const {
+    return is_aggregate_partitioned_
+               ? partitioned_group_by_hashtable_pool_->getNumPartitions()
+               : 1;
+  }
+
   int dflag;
 
  private:
+  static constexpr std::size_t kPartitionedAggregateThreshold = 100;
+  static constexpr std::size_t kNumPartitionsForAggregate = 40;
+
   // Merge locally (per storage block) aggregated states with global aggregation
   // states.
   void mergeSingleState(
@@ -185,9 +205,39 @@ class AggregationOperationState {
   void finalizeSingleState(InsertDestination *output_destination);
   void finalizeHashTable(InsertDestination *output_destination);
 
+  bool checkAggregatePartitioned(
+      const std::size_t estimated_num_groups,
+      const std::vector<bool> &is_distinct,
+      const std::vector<std::unique_ptr<const Scalar>> &group_by,
+      const std::vector<const AggregateFunction *> &aggregate_functions) const {
+    // If there's no aggregation, return false.
+    if (aggregate_functions.empty()) {
+      return false;
+    }
+    // Check if there's a distinct operation involved in any aggregate, if so
+    // the aggregate can't be partitioned.
+    for (auto distinct : is_distinct) {
+      if (distinct) {
+        return false;
+      }
+    }
+    // There's no distinct aggregation involved, Check if there's at least one
+    // GROUP BY operation.
+    if (group_by.empty()) {
+      return false;
+    }
+    // There are GROUP BYs without DISTINCT. Check if the estimated number of
+    // groups is large enough to warrant a partitioned aggregation.
+    return estimated_num_groups > kPartitionedAggregateThreshold;
+  }
+
   // Common state for all aggregates in this operation: the input relation, the
   // filter predicate (if any), and the list of GROUP BY expressions (if any).
   const CatalogRelationSchema &input_relation_;
+
+  // Whether the aggregation is partitioned or not.
+  const bool is_aggregate_partitioned_;
+
   std::unique_ptr<const Predicate> predicate_;
   std::vector<std::unique_ptr<const Scalar>> group_by_list_;
 
@@ -224,6 +274,8 @@ class AggregationOperationState {
   // A vector of group by hash table pools.
   std::unique_ptr<HashTablePool> group_by_hashtable_pool_;
 
+  std::unique_ptr<PartitionedHashTablePool> partitioned_group_by_hashtable_pool_;
+
   StorageManager *storage_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(AggregationOperationState);

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/aaba9462/storage/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/storage/CMakeLists.txt b/storage/CMakeLists.txt
index f05cc46..9c1ebd0 100644
--- a/storage/CMakeLists.txt
+++ b/storage/CMakeLists.txt
@@ -235,6 +235,7 @@ add_library(quickstep_storage_PackedRowStoreTupleStorageSubBlock
 add_library(quickstep_storage_PackedRowStoreValueAccessor
             ../empty_src.cpp
             PackedRowStoreValueAccessor.hpp)
+add_library(quickstep_storage_PartitionedHashTablePool ../empty_src.cpp PartitionedHashTablePool.hpp)
 add_library(quickstep_storage_PreloaderThread PreloaderThread.cpp PreloaderThread.hpp)
 add_library(quickstep_storage_SMAIndexSubBlock SMAIndexSubBlock.cpp SMAIndexSubBlock.hpp)
 add_library(quickstep_storage_SeparateChainingHashTable ../empty_src.cpp SeparateChainingHashTable.hpp)
@@ -289,6 +290,7 @@ target_link_libraries(quickstep_storage_AggregationOperationState
                       quickstep_storage_HashTableFactory
                       quickstep_storage_HashTablePool
                       quickstep_storage_InsertDestination
+                      quickstep_storage_PartitionedHashTablePool
                       quickstep_storage_StorageBlock
                       quickstep_storage_StorageBlockInfo
                       quickstep_storage_StorageManager
@@ -850,6 +852,14 @@ target_link_libraries(quickstep_storage_PackedRowStoreValueAccessor
                       quickstep_types_TypedValue
                       quickstep_utility_BitVector
                       quickstep_utility_Macros)
+target_link_libraries(quickstep_storage_PartitionedHashTablePool
+                      glog
+                      quickstep_expressions_aggregation_AggregationHandle
+                      quickstep_storage_FastHashTable
+                      quickstep_storage_FastHashTableFactory
+                      quickstep_storage_HashTableBase
+                      quickstep_utility_Macros
+                      quickstep_utility_StringUtil)                    
 target_link_libraries(quickstep_storage_PreloaderThread
                       glog
                       quickstep_catalog_CatalogDatabase
@@ -971,6 +981,7 @@ target_link_libraries(quickstep_storage_StorageBlock
                       quickstep_storage_IndexSubBlock
                       quickstep_storage_InsertDestinationInterface
                       quickstep_storage_PackedRowStoreTupleStorageSubBlock
+                      quickstep_storage_PartitionedHashTablePool
                       quickstep_storage_SMAIndexSubBlock
                       quickstep_storage_SplitRowStoreTupleStorageSubBlock
                       quickstep_storage_StorageBlockBase
@@ -1167,6 +1178,7 @@ target_link_libraries(quickstep_storage
                       quickstep_storage_LinearOpenAddressingHashTable
                       quickstep_storage_PackedRowStoreTupleStorageSubBlock
                       quickstep_storage_PackedRowStoreValueAccessor
+                      quickstep_storage_PartitionedHashTablePool
                       quickstep_storage_PreloaderThread
                       quickstep_storage_SMAIndexSubBlock
                       quickstep_storage_SeparateChainingHashTable

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/aaba9462/storage/HashTablePool.hpp
----------------------------------------------------------------------
diff --git a/storage/HashTablePool.hpp b/storage/HashTablePool.hpp
index 3cdfcb3..c34a435 100644
--- a/storage/HashTablePool.hpp
+++ b/storage/HashTablePool.hpp
@@ -77,7 +77,7 @@ class HashTablePool {
                 const std::vector<const Type *> &group_by_types,
                 AggregationHandle *agg_handle,
                 StorageManager *storage_manager)
-      : estimated_num_entries_(reduceEstimatedCardinality(estimated_num_entries)),
+      : estimated_num_entries_(setHashTableSize()),
         hash_table_impl_type_(hash_table_impl_type),
         group_by_types_(group_by_types),
         agg_handle_(DCHECK_NOTNULL(agg_handle)),
@@ -104,7 +104,7 @@ class HashTablePool {
                 const std::vector<std::size_t> &payload_sizes,
                 const std::vector<AggregationHandle *> &handles,
                 StorageManager *storage_manager)
-      : estimated_num_entries_(reduceEstimatedCardinality(estimated_num_entries)),
+      : estimated_num_entries_(setHashTableSize()),
         hash_table_impl_type_(hash_table_impl_type),
         group_by_types_(group_by_types),
         payload_sizes_(payload_sizes),
@@ -196,17 +196,12 @@ class HashTablePool {
                 storage_manager_);
   }
 
-  inline std::size_t reduceEstimatedCardinality(
-      const std::size_t original_estimate) const {
-    if (original_estimate < kEstimateReductionFactor) {
-      return original_estimate;
-    } else {
-      DCHECK_GT(kEstimateReductionFactor, 0u);
-      return original_estimate / kEstimateReductionFactor;
-    }
+  inline std::size_t setHashTableSize() const {
+    return kHashTableSize;
   }
 
-  static constexpr std::size_t kEstimateReductionFactor = 100;
+  // L2 cache size.
+  static constexpr std::size_t kHashTableSize = 262144;
 
   std::vector<std::unique_ptr<AggregationStateHashTableBase>> hash_tables_;
 

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/aaba9462/storage/PartitionedHashTablePool.hpp
----------------------------------------------------------------------
diff --git a/storage/PartitionedHashTablePool.hpp b/storage/PartitionedHashTablePool.hpp
new file mode 100644
index 0000000..ba51d21
--- /dev/null
+++ b/storage/PartitionedHashTablePool.hpp
@@ -0,0 +1,224 @@
+/**
+ *   Copyright 2016, Quickstep Research Group, Computer Sciences Department,
+ *     University of Wisconsin\u2014Madison.
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ **/
+
+#ifndef QUICKSTEP_STORAGE_PARTITIONED_HASH_TABLE_POOL_HPP_
+#define QUICKSTEP_STORAGE_PARTITIONED_HASH_TABLE_POOL_HPP_
+
+#include <algorithm>
+#include <chrono>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "expressions/aggregation/AggregationHandle.hpp"
+#include "storage/HashTableBase.hpp"
+#include "storage/FastHashTable.hpp"
+#include "storage/FastHashTableFactory.hpp"
+#include "utility/Macros.hpp"
+#include "utility/StringUtil.hpp"
+
+#include "glog/logging.h"
+
+namespace quickstep {
+
+class StorageManager;
+class Type;
+
+/** \addtogroup Storage
+ *  @{
+ */
+
+/**
+ * @brief A pool of HashTables used for a single aggregation handle. Each
+ *        HashTable represents values from a given partition, which is
+ *        determined by the keys in the group by clause.
+ **/
+class PartitionedHashTablePool {
+ public:
+  /**
+   * @brief Constructor.
+   *
+   * @param estimated_num_entries The maximum number of entries in a hash table.
+   * @param num_partitions The number of partitions (i.e. number of HashTables)
+   * @param hash_table_impl_type The type of hash table implementation.
+   * @param group_by_types A vector of pointer of types which form the group by
+   *        key.
+   * @param agg_handle The aggregation handle.
+   * @param storage_manager A pointer to the storage manager.
+   *
+   * @note The estimate of number of entries is quite inaccurate at this time.
+   *       If we go by the current estimate, each hash table demands much
+   *       larger space than it actually needs, which causes the system to
+   *       either trigger evictions or worse - run out of memory. To fix this
+   *       issue, we divide the estimate by 100. The division will not affect
+   *       correctness, however it may allocate some hash tables smaller space
+   *       than their requirement, causing them to be resized during build
+   *       phase, which has a performance penalty.
+   **/
+  PartitionedHashTablePool(const std::size_t estimated_num_entries,
+                           const std::size_t num_partitions,
+                           const HashTableImplType hash_table_impl_type,
+                           const std::vector<const Type *> &group_by_types,
+                           AggregationHandle *agg_handle,
+                           StorageManager *storage_manager)
+      : estimated_num_entries_(
+            setHashTableSize(estimated_num_entries, num_partitions)),
+        num_partitions_(num_partitions),
+        hash_table_impl_type_(hash_table_impl_type),
+        group_by_types_(group_by_types),
+        agg_handle_(DCHECK_NOTNULL(agg_handle)),
+        storage_manager_(DCHECK_NOTNULL(storage_manager)) {
+    initializeAllHashTables();
+  }
+
+  /**
+   * @brief Constructor.
+   *
+   * @note This constructor is relevant for the HashTable specialized for
+   *       aggregation.
+   *
+   * @param estimated_num_entries The maximum number of entries in a hash table.
+   * @param num_partitions The number of partitions (i.e. number of HashTables)
+   * @param hash_table_impl_type The type of hash table implementation.
+   * @param group_by_types A vector of pointer of types which form the group by
+   *        key.
+   * @param payload_sizes The sizes of the payload elements (i.e.
+   *        AggregationStates).
+   * @param handles The aggregation handles.
+   * @param storage_manager A pointer to the storage manager.
+   **/
+  PartitionedHashTablePool(const std::size_t estimated_num_entries,
+                           const std::size_t num_partitions,
+                           const HashTableImplType hash_table_impl_type,
+                           const std::vector<const Type *> &group_by_types,
+                           const std::vector<std::size_t> &payload_sizes,
+                           const std::vector<AggregationHandle *> &handles,
+                           StorageManager *storage_manager)
+      : estimated_num_entries_(
+            setHashTableSize(estimated_num_entries, num_partitions)),
+        num_partitions_(num_partitions),
+        hash_table_impl_type_(hash_table_impl_type),
+        group_by_types_(group_by_types),
+        payload_sizes_(payload_sizes),
+        handles_(handles),
+        storage_manager_(DCHECK_NOTNULL(storage_manager)) {
+    initializeAllHashTables();
+  }
+
+  /**
+   * @brief Check out a hash table for insertion.
+   *
+   * @param partition_id The ID of the partitioned HashTable.
+   *
+   * @return A hash table pointer for the given HashTable.
+   **/
+  AggregationStateHashTableBase* getHashTable(const std::size_t partition_id) {
+    DCHECK_LT(partition_id, num_partitions_);
+    DCHECK_LT(partition_id, hash_tables_.size());
+    return hash_tables_[partition_id].get();
+  }
+
+  /**
+   * @brief Check out a hash table for insertion.
+   *
+   * @param partition_id The ID of the partitioned HashTable.
+   *
+   * @return A hash table pointer for the given HashTable.
+   **/
+  AggregationStateHashTableBase* getHashTableFast(const std::size_t partition_id) {
+    DCHECK_LT(partition_id, num_partitions_);
+    DCHECK_LT(partition_id, hash_tables_.size());
+    return hash_tables_[partition_id].get();
+  }
+
+  /**
+   * @brief Get all the hash tables from the pool.
+   *
+   * @warning The caller should ensure that this call is made when no hash table
+   *          is being checked in or checked out from the pool. In other words
+   *          the hash table pool is in read-only state.
+   *
+   * @param All the hash tables in the pool.
+   *
+   **/
+  std::vector<std::unique_ptr<AggregationStateHashTableBase>>*
+      getAllHashTables() {
+    return &hash_tables_;
+  }
+
+  /**
+   * @brief Get the number of partitions used for the aggregation.
+   **/
+  inline std::size_t getNumPartitions() const {
+    return num_partitions_;
+  }
+
+ private:
+  void initializeAllHashTables() {
+    for (std::size_t part_num = 0; part_num < num_partitions_; ++part_num) {
+      AggregationStateHashTableBase *part_hash_table = createNewHashTableFast();
+      hash_tables_.push_back(
+          std::unique_ptr<AggregationStateHashTableBase>(part_hash_table));
+    }
+  }
+
+  AggregationStateHashTableBase* createNewHashTable() {
+    return agg_handle_->createGroupByHashTable(hash_table_impl_type_,
+                                               group_by_types_,
+                                               estimated_num_entries_,
+                                               storage_manager_);
+  }
+
+  AggregationStateHashTableBase* createNewHashTableFast() {
+    return AggregationStateFastHashTableFactory::CreateResizable(
+                hash_table_impl_type_,
+                group_by_types_,
+                estimated_num_entries_,
+                payload_sizes_,
+                handles_,
+                storage_manager_);
+  }
+
+  inline std::size_t setHashTableSize(const std::size_t overall_estimate,
+                                      const std::size_t num_partitions) const {
+    CHECK_NE(num_partitions, 0);
+    return std::min(static_cast<std::size_t>(overall_estimate/num_partitions), 1Lu);
+  }
+
+  std::vector<std::unique_ptr<AggregationStateHashTableBase>> hash_tables_;
+
+  const std::size_t estimated_num_entries_;
+  const std::size_t num_partitions_;
+
+  const HashTableImplType hash_table_impl_type_;
+
+  const std::vector<const Type *> group_by_types_;
+
+  std::vector<std::size_t> payload_sizes_;
+
+  AggregationHandle *agg_handle_;
+  const std::vector<AggregationHandle *> handles_;
+  StorageManager *storage_manager_;
+
+  DISALLOW_COPY_AND_ASSIGN(PartitionedHashTablePool);
+};
+
+/** @} */
+
+}  // namespace quickstep
+
+#endif  // QUICKSTEP_STORAGE_HASH_TABLE_POOL_HPP_

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/aaba9462/storage/StorageBlock.cpp
----------------------------------------------------------------------
diff --git a/storage/StorageBlock.cpp b/storage/StorageBlock.cpp
index ec5990f..94c46a8 100644
--- a/storage/StorageBlock.cpp
+++ b/storage/StorageBlock.cpp
@@ -41,6 +41,7 @@
 #include "storage/IndexSubBlock.hpp"
 #include "storage/InsertDestinationInterface.hpp"
 #include "storage/PackedRowStoreTupleStorageSubBlock.hpp"
+#include "storage/PartitionedHashTablePool.hpp"
 #include "storage/SMAIndexSubBlock.hpp"
 #include "storage/SplitRowStoreTupleStorageSubBlock.hpp"
 #include "storage/StorageBlockBase.hpp"
@@ -1369,4 +1370,118 @@ const std::size_t StorageBlock::getNumTuples() const {
   return tuple_store_->numTuples();
 }
 
+void StorageBlock::aggregateGroupByPartitioned(
+    const std::vector<std::vector<std::unique_ptr<const Scalar>>> &arguments,
+    const std::vector<std::unique_ptr<const Scalar>> &group_by,
+    const Predicate *predicate,
+    std::unique_ptr<TupleIdSequence> *reuse_matches,
+    std::vector<std::unique_ptr<ColumnVector>> *reuse_group_by_vectors,
+    PartitionedHashTablePool *hashtable_pool) const {
+  DCHECK(!group_by.empty())
+      << "Called aggregateGroupByPartitioned() with zero GROUP BY expressions";
+
+  SubBlocksReference sub_blocks_ref(*tuple_store_,
+                                    indices_,
+                                    indices_consistent_);
+
+  // IDs of 'arguments' as attributes in the ValueAccessor we create below.
+  std::vector<attribute_id> arg_ids;
+  std::vector<attribute_id> argument_ids;
+
+  // IDs of GROUP BY key element(s) in the ValueAccessor we create below.
+  std::vector<attribute_id> key_ids;
+
+  // An intermediate ValueAccessor that stores the materialized 'arguments' for
+  // this aggregate, as well as the GROUP BY expression values.
+  ColumnVectorsValueAccessor temp_result;
+  std::unique_ptr<ValueAccessor> accessor;
+  if (predicate) {
+    if (!*reuse_matches) {
+      // If there is a filter predicate that hasn't already been evaluated,
+      // evaluate it now and save the results for other aggregates on this
+      // same block.
+      reuse_matches->reset(getMatchesForPredicate(predicate));
+    }
+
+    // Create a filtered ValueAccessor that only iterates over predicate
+    // matches.
+    accessor.reset(tuple_store_->createValueAccessor(reuse_matches->get()));
+  } else {
+    // Create a ValueAccessor that iterates over all tuples in this block
+    accessor.reset(tuple_store_->createValueAccessor());
+  }
+
+  attribute_id attr_id = 0;
+
+  // First, put GROUP BY keys into 'temp_result'.
+  if (reuse_group_by_vectors->empty()) {
+    // Compute GROUP BY values from group_by Scalars, and store them in
+    // reuse_group_by_vectors for reuse by other aggregates on this same
+    // block.
+    reuse_group_by_vectors->reserve(group_by.size());
+    for (const std::unique_ptr<const Scalar> &group_by_element : group_by) {
+      reuse_group_by_vectors->emplace_back(
+          group_by_element->getAllValues(accessor.get(), &sub_blocks_ref));
+      temp_result.addColumn(reuse_group_by_vectors->back().get(), false);
+      key_ids.push_back(attr_id++);
+    }
+  } else {
+    // Reuse precomputed GROUP BY values from reuse_group_by_vectors.
+    DCHECK_EQ(group_by.size(), reuse_group_by_vectors->size())
+        << "Wrong number of reuse_group_by_vectors";
+    for (const std::unique_ptr<ColumnVector> &reuse_cv : *reuse_group_by_vectors) {
+      temp_result.addColumn(reuse_cv.get(), false);
+      key_ids.push_back(attr_id++);
+    }
+  }
+
+  // Compute argument vectors and add them to 'temp_result'.
+  for (const std::vector<std::unique_ptr<const Scalar>> &argument : arguments) {
+    arg_ids.clear();
+    for (const std::unique_ptr<const Scalar> &args : argument) {
+      temp_result.addColumn(args->getAllValues(accessor.get(), &sub_blocks_ref));
+      argument_ids.push_back(attr_id++);
+    }
+    if (argument.empty()) {
+      argument_ids.push_back(kInvalidAttributeID);
+    }
+  }
+
+  // Compute the partitions for the tuple formed by group by values.
+  std::vector<std::unique_ptr<TupleIdSequence>> partition_membership;
+  partition_membership.resize(hashtable_pool->getNumPartitions());
+
+  // Create a tuple-id sequence for each partition.
+  for (std::size_t partition = 0;
+       partition < hashtable_pool->getNumPartitions();
+       ++partition) {
+    partition_membership[partition].reset(new TupleIdSequence(temp_result.getEndPosition()));
+  }
+
+  // Iterate over ValueAccessor for each tuple,
+  // set a bit in the appropriate TupleIdSequence.
+  temp_result.beginIteration();
+  while (temp_result.next()) {
+    const std::size_t curr_tuple_partition_id =
+        temp_result.getTupleWithAttributes(key_ids)->getTupleHash() %
+        hashtable_pool->getNumPartitions();
+    partition_membership[curr_tuple_partition_id]->set(
+        temp_result.getCurrentPosition(), true);
+  }
+  // For each partition, create an adapter around Value Accessor and
+  // TupleIdSequence.
+  std::vector<std::unique_ptr<
+      TupleIdSequenceAdapterValueAccessor<ColumnVectorsValueAccessor>>> adapter;
+  adapter.resize(hashtable_pool->getNumPartitions());
+  for (std::size_t partition = 0;
+       partition < hashtable_pool->getNumPartitions();
+       ++partition) {
+    adapter[partition].reset(temp_result.createSharedTupleIdSequenceAdapter(
+        *partition_membership[partition]));
+    hashtable_pool->getHashTable(partition)
+        ->upsertValueAccessorCompositeKeyFast(
+            argument_ids, adapter[partition].get(), key_ids, true);
+  }
+}
+
 }  // namespace quickstep

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/aaba9462/storage/StorageBlock.hpp
----------------------------------------------------------------------
diff --git a/storage/StorageBlock.hpp b/storage/StorageBlock.hpp
index bab5bab..3fcaddf 100644
--- a/storage/StorageBlock.hpp
+++ b/storage/StorageBlock.hpp
@@ -44,6 +44,7 @@ class AggregationState;
 class CatalogRelationSchema;
 class ColumnVector;
 class InsertDestinationInterface;
+class PartitionedHashTablePool;
 class Predicate;
 class Scalar;
 class StorageBlockLayout;
@@ -466,6 +467,48 @@ class StorageBlock : public StorageBlockBase {
       std::unique_ptr<TupleIdSequence> *reuse_matches,
       std::vector<std::unique_ptr<ColumnVector>> *reuse_group_by_vectors) const;
 
+
+  /**
+   * @brief Perform the GROUP BY aggregation for the case when aggregation is
+   *        partitioned.
+   *
+   * @note The difference between this method and the aggregateGroupBy method
+   *       is that in this method, the tuples are routed to different HashTables
+   *       based on the partition to which they belong to. The partition is
+   *       determined by the GROUP BY attributes. Right now hash based
+   *       partitioning is performed.
+   *
+   * @param arguments The arguments to the aggregation function as Scalars.
+   * @param group_by The list of GROUP BY attributes/expressions. The tuples in
+   *        this storage block are grouped by these attributes before
+   *        aggregation.
+   * @param predicate A predicate for selection. nullptr indicates that all
+   *        tuples should be aggregated on.
+   * @param reuse_matches This parameter is used to store and reuse tuple-id
+   *        sequence of matches pre-computed in an earlier invocations of
+   *        aggregateGroupBy(). \c reuse_matches is never \c nullptr for ease of
+   *        use.  Current invocation of aggregateGroupBy() will reuse
+   *        TupleIdSequence if passed, otherwise computes a TupleIdSequence based
+   *        on \c predicate and stores in \c reuse_matches. We use
+   *        std::unique_ptr for each of use, since the caller will not have to
+   *        selective free.
+   * @param reuse_group_by_vectors This parameter is used to store and reuse
+   *        GROUP BY attribute vectors pre-computed in an earlier invocation of
+   *        aggregateGroupBy(). \c reuse_group_by_vectors is never \c nullptr
+   *        for ease of use. Current invocation of aggregateGroupBy() will reuse
+   *        ColumnVectors if non-empty, otherwise computes ColumnVectors based
+   *        on \c group_by and stores them in \c reuse_group_by_vectors.
+   * @param hashtable_pool The pool of aggregation HashTables. Each hash table
+   *        in this pool belongs to a unique partition.
+   **/
+  void aggregateGroupByPartitioned(
+      const std::vector<std::vector<std::unique_ptr<const Scalar>>> &arguments,
+      const std::vector<std::unique_ptr<const Scalar>> &group_by,
+      const Predicate *predicate,
+      std::unique_ptr<TupleIdSequence> *reuse_matches,
+      std::vector<std::unique_ptr<ColumnVector>> *reuse_group_by_vectors,
+      PartitionedHashTablePool *hashtable_pool) const;
+
   /**
    * @brief Inserts the GROUP BY expressions and aggregation arguments together
    *        as keys into the distinctify hash table.

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/aaba9462/types/containers/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/types/containers/CMakeLists.txt b/types/containers/CMakeLists.txt
index aacb63a..c2a6623 100644
--- a/types/containers/CMakeLists.txt
+++ b/types/containers/CMakeLists.txt
@@ -49,6 +49,7 @@ target_link_libraries(quickstep_types_containers_Tuple
                       quickstep_catalog_CatalogTypedefs
                       quickstep_types_TypedValue
                       quickstep_types_containers_Tuple_proto
+                      quickstep_utility_CompositeHash
                       quickstep_utility_Macros)
 target_link_libraries(quickstep_types_containers_Tuple_proto
                       quickstep_types_TypedValue_proto

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/aaba9462/types/containers/Tuple.hpp
----------------------------------------------------------------------
diff --git a/types/containers/Tuple.hpp b/types/containers/Tuple.hpp
index 60f832c..6237d54 100644
--- a/types/containers/Tuple.hpp
+++ b/types/containers/Tuple.hpp
@@ -28,6 +28,7 @@
 #include "catalog/CatalogTypedefs.hpp"
 #include "types/TypedValue.hpp"
 #include "types/containers/Tuple.pb.h"
+#include "utility/CompositeHash.hpp"
 #include "utility/Macros.hpp"
 
 #include "glog/logging.h"
@@ -218,6 +219,13 @@ class Tuple {
     return attribute_values_.size();
   }
 
+  /**
+   * @brief Get the hash value of the tuple.
+   **/
+  std::size_t getTupleHash() const {
+    return HashCompositeKey(attribute_values_);
+  }
+
  private:
   /**
    * @brief Constructor which does not create any attributes, nor pre-reserve

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/aaba9462/utility/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/utility/CMakeLists.txt b/utility/CMakeLists.txt
index ddaae45..4fb6e5b 100644
--- a/utility/CMakeLists.txt
+++ b/utility/CMakeLists.txt
@@ -167,6 +167,7 @@ add_library(quickstep_utility_BloomFilter_proto
 add_library(quickstep_utility_CalculateInstalledMemory CalculateInstalledMemory.cpp CalculateInstalledMemory.hpp)
 add_library(quickstep_utility_Cast ../empty_src.cpp Cast.hpp)
 add_library(quickstep_utility_CheckSnprintf ../empty_src.cpp CheckSnprintf.hpp)
+add_library(quickstep_utility_CompositeHash ../empty_src.cpp CompositeHash.hpp)
 add_library(quickstep_utility_DAG ../empty_src.cpp DAG.hpp)
 add_library(quickstep_utility_EqualsAnyConstant ../empty_src.cpp EqualsAnyConstant.hpp)
 add_library(quickstep_utility_ExecutionDAGVisualizer
@@ -227,6 +228,10 @@ target_link_libraries(quickstep_utility_CalculateInstalledMemory
                       glog)
 target_link_libraries(quickstep_utility_CheckSnprintf
                       glog)
+target_link_libraries(quickstep_utility_CompositeHash
+                      quickstep_types_TypedValue
+                      quickstep_utility_HashPair
+                      glog)
 target_link_libraries(quickstep_utility_DAG
                       glog
                       quickstep_utility_Macros)
@@ -318,6 +323,7 @@ target_link_libraries(quickstep_utility
                       quickstep_utility_CalculateInstalledMemory
                       quickstep_utility_Cast
                       quickstep_utility_CheckSnprintf
+                      quickstep_utility_CompositeHash
                       quickstep_utility_DAG
                       quickstep_utility_EqualsAnyConstant
                       quickstep_utility_ExecutionDAGVisualizer

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/aaba9462/utility/CompositeHash.hpp
----------------------------------------------------------------------
diff --git a/utility/CompositeHash.hpp b/utility/CompositeHash.hpp
new file mode 100644
index 0000000..517bc96
--- /dev/null
+++ b/utility/CompositeHash.hpp
@@ -0,0 +1,52 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ **/
+
+#ifndef QUICKSTEP_UTILITY_COMPOSITE_HASH_HPP_
+#define QUICKSTEP_UTILITY_COMPOSITE_HASH_HPP_
+
+#include <cstddef>
+#include <vector>
+
+#include "types/TypedValue.hpp"
+#include "utility/HashPair.hpp"
+
+#include "glog/logging.h"
+
+namespace quickstep {
+
+/**
+ * @brief Compute the hash value of a composite key.
+ *
+ * @param key A vector of TypedValues which together form the composite key.
+ * @return The hash value.
+ **/
+static std::size_t HashCompositeKey(const std::vector<TypedValue> &key) {
+  DCHECK(!key.empty());
+  std::size_t hash = key.front().getHash();
+  for (std::vector<TypedValue>::const_iterator key_it = key.begin() + 1;
+       key_it != key.end();
+       ++key_it) {
+    hash = CombineHashes(hash, key_it->getHash());
+  }
+  return hash;
+}
+
+}  // namespace quickstep
+
+#endif  // QUICKSTEP_UTILITY_COMPOSITE_HASH_HPP_



[6/9] incubator-quickstep git commit: Fix testcase failure by explicit typecasting and avoiding macro usage

Posted by hb...@apache.org.
Fix testcase failure by explicit typecasting and avoiding macro usage


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

Branch: refs/heads/partitioned-aggregate-new
Commit: e4de24178d085464af648d5914891ec548f09853
Parents: e845246
Author: Saket Saurabh <ss...@cs.wisc.edu>
Authored: Mon Oct 3 01:21:30 2016 -0500
Committer: Saket Saurabh <ss...@cs.wisc.edu>
Committed: Tue Oct 11 11:36:57 2016 -0500

----------------------------------------------------------------------
 ...kedRowStoreTupleStorageSubBlock_unittest.cpp | 38 ++++++++++----------
 1 file changed, 18 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/e4de2417/storage/tests/PackedRowStoreTupleStorageSubBlock_unittest.cpp
----------------------------------------------------------------------
diff --git a/storage/tests/PackedRowStoreTupleStorageSubBlock_unittest.cpp b/storage/tests/PackedRowStoreTupleStorageSubBlock_unittest.cpp
index 924f9b1..bf3c605 100644
--- a/storage/tests/PackedRowStoreTupleStorageSubBlock_unittest.cpp
+++ b/storage/tests/PackedRowStoreTupleStorageSubBlock_unittest.cpp
@@ -256,29 +256,27 @@ class PackedRowStoreTupleStorageSubBlockTest : public ::testing::TestWithParam<b
     initializeNewBlock(kSubBlockSize);
     fillBlockWithSampleData();
     ASSERT_TRUE(tuple_store_->isPacked());
-    std::unique_ptr<ValueAccessor> accessor(tuple_store_->createValueAccessor());
+    std::unique_ptr<PackedRowStoreValueAccessor> accessor(
+      static_cast<PackedRowStoreValueAccessor*>(tuple_store_->createValueAccessor()));
     attribute_id  value_accessor_id = 0;
     tuple_id tid = 0;
-    InvokeOnAnyValueAccessor(accessor.get(),
-                             [&](auto *accessor) -> void {  // NOLINT(build/c++11)
-      accessor->beginIteration();
-      ASSERT_TRUE(accessor->isColumnAccessorSupported());
-      std::unique_ptr<const ColumnAccessor<check_null>>
-      column_accessor(accessor->template getColumnAccessor<check_null>(value_accessor_id));
-      ASSERT_TRUE(column_accessor != nullptr);
-      while (accessor->next()) {
-        const void *va_value = column_accessor->getUntypedValue();
-        std::unique_ptr<Tuple> expected_tuple(createSampleTuple(tid));
-
-        if (expected_tuple->getAttributeValue(value_accessor_id).isNull()) {
-          ASSERT_TRUE(va_value == nullptr);
-        } else {
-          ASSERT_TRUE(eq_comp_int_->compareDataPtrs(expected_tuple->getAttributeValue(value_accessor_id).getDataPtr(),
-                                                    va_value));
-        }
-        ++tid;
+    accessor->beginIteration();
+    ASSERT_TRUE(accessor->isColumnAccessorSupported());
+    std::unique_ptr<const ColumnAccessor<check_null>>
+    column_accessor(accessor->template getColumnAccessor<check_null>(value_accessor_id));
+    ASSERT_TRUE(column_accessor != nullptr);
+    while (accessor->next()) {
+      const void *va_value = column_accessor->getUntypedValue();
+      std::unique_ptr<Tuple> expected_tuple(createSampleTuple(tid));
+
+      if (expected_tuple->getAttributeValue(value_accessor_id).isNull()) {
+        ASSERT_TRUE(va_value == nullptr);
+      } else {
+        ASSERT_TRUE(eq_comp_int_->compareDataPtrs(expected_tuple->getAttributeValue(value_accessor_id).getDataPtr(),
+                                                  va_value));
       }
-    });
+      ++tid;
+    }
   }
 
   std::unique_ptr<CatalogRelation> relation_;


[5/9] incubator-quickstep git commit: Optimize PackedRowStoreValueAccessor & BasicColumnStoreValueAccessor by removing redundant computations and clearly exposing a strided memory access pattern

Posted by hb...@apache.org.
Optimize PackedRowStoreValueAccessor & BasicColumnStoreValueAccessor by removing redundant computations and clearly exposing a strided memory access pattern


Project: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/commit/743f6b0a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/tree/743f6b0a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/diff/743f6b0a

Branch: refs/heads/partitioned-aggregate-new
Commit: 743f6b0acc769a0f2eedb0daf8ed6f535dc1c4b0
Parents: 80af233
Author: Saket Saurabh <ss...@cs.wisc.edu>
Authored: Wed Sep 21 03:17:19 2016 -0500
Committer: Saket Saurabh <ss...@cs.wisc.edu>
Committed: Tue Oct 11 11:36:57 2016 -0500

----------------------------------------------------------------------
 .gitignore                                      |   1 +
 storage/BasicColumnStoreValueAccessor.hpp       |  55 +++++++
 storage/CompressedColumnStoreValueAccessor.hpp  |  33 +++++
 .../CompressedPackedRowStoreValueAccessor.hpp   |  33 +++++
 storage/PackedRowStoreValueAccessor.hpp         |  54 +++++++
 storage/SplitRowStoreValueAccessor.hpp          |  18 +++
 storage/ValueAccessor.hpp                       | 143 +++++++++++++++++++
 types/containers/ColumnVectorsValueAccessor.hpp |  18 +++
 .../comparisons/AsciiStringComparators-inl.hpp  | 101 ++++++++++---
 types/operations/comparisons/Comparison-inl.hpp |  27 +++-
 .../comparisons/LiteralComparators-inl.hpp      | 129 +++++++++++++----
 .../PatternMatchingComparators-inl.hpp          |  24 +++-
 12 files changed, 574 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 37a361f..5dea02f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,4 +7,5 @@
 Makefile.in
 autom4te.cache
 .DS_Store
+.idea
 *~

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/storage/BasicColumnStoreValueAccessor.hpp
----------------------------------------------------------------------
diff --git a/storage/BasicColumnStoreValueAccessor.hpp b/storage/BasicColumnStoreValueAccessor.hpp
index 0560d99..22d3c0b 100644
--- a/storage/BasicColumnStoreValueAccessor.hpp
+++ b/storage/BasicColumnStoreValueAccessor.hpp
@@ -52,6 +52,61 @@ class BasicColumnStoreValueAccessorHelper {
     return num_tuples_;
   }
 
+  /**
+   * @brief Returns whether this accessor has a fast strided ColumnAccessor available
+   *        that can be used to optimize memory access in a tight loop iteration
+   *        over the underlying storage block.
+   *
+   * @return true if fast ColumnAccessor is supported, otherwise false.
+   */
+  inline bool isColumnAccessorSupported() const {
+    return true;
+  }
+
+  /**
+   * @brief Get a pointer to a ColumnAccessor object that provides a fast strided memory
+   *        access on the underlying storage block.
+   * @note The ownership of the returned object lies with the caller.
+   * @warning This method should only be called if isColumnAccessorSupported() method
+   *          returned true. If ColumnAccessor is not supported this method will return a nullptr.
+   *
+   * @param current_tuple_position A constant reference to the tuple position in the containing
+   *        ValueAccessor. This reference value is shared between the containing ValueAccessor &
+   *        a ColumnAccessor. However, a ColumnAccessor *CANNOT* modify this tuple position.
+   * @param attr_id The attribute id on which this ColumnAccessor will be created.
+   *
+   * @return A pointer to a ColumnAccessor object with specific properties set that can be used
+   *         in a tight loop iterations over the underlying storage block.
+   **/
+  template <bool check_null = true>
+  inline const ColumnAccessor<check_null>* getColumnAccessor(const tuple_id &current_tuple_position,
+                                                             const attribute_id attr_id) const {
+    DEBUG_ASSERT(relation_.hasAttributeWithId(attr_id));
+    const void* base_location = static_cast<const char*>(column_stripes_[attr_id]);
+    const std::size_t stride = relation_.getAttributeById(attr_id)->getType().maximumByteLength();
+    std::unique_ptr<ColumnAccessor<check_null>> column_accessor;
+    if (check_null) {
+      // The nullable_base might get initialized to -1 if column_null_bitmaps returns false for
+      // the given attribute. Setting the nullable_base to -1 will mean that
+      // column accessor will always evaluate null check to false.
+      const int nullable_base = (!column_null_bitmaps_.elementIsNull(attr_id)) ? 0 : -1;
+      const unsigned nullable_stride = 1;
+      column_accessor.reset(new ColumnAccessor<check_null>(current_tuple_position,
+                                                           num_tuples_,
+                                                           base_location,
+                                                           stride,
+                                                           &(column_null_bitmaps_[attr_id]),
+                                                           nullable_base,
+                                                           nullable_stride));
+    } else {
+      column_accessor.reset(new ColumnAccessor<check_null>(current_tuple_position,
+                                                           num_tuples_,
+                                                           base_location,
+                                                           stride));
+    }
+    return column_accessor.release();
+  }
+
   template <bool check_null>
   inline const void* getAttributeValue(const tuple_id tuple,
                                        const attribute_id attr) const {

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/storage/CompressedColumnStoreValueAccessor.hpp
----------------------------------------------------------------------
diff --git a/storage/CompressedColumnStoreValueAccessor.hpp b/storage/CompressedColumnStoreValueAccessor.hpp
index 25e5eed..366d4c6 100644
--- a/storage/CompressedColumnStoreValueAccessor.hpp
+++ b/storage/CompressedColumnStoreValueAccessor.hpp
@@ -67,6 +67,39 @@ class CompressedColumnStoreValueAccessorHelper {
     return num_tuples_;
   }
 
+  /**
+   * @brief Returns whether this accessor has a fast strided ColumnAccessor available
+   *        that can be used to optimize memory access in a tight loop iteration
+   *        over the underlying storage block.
+   *
+   * @return true if fast ColumnAccessor is supported, otherwise false.
+   */
+  inline bool isColumnAccessorSupported() const {
+    return false;
+  }
+
+  /**
+   * @brief Get a pointer to a ColumnAccessor object that provides a fast strided memory
+   *        access on the underlying storage block.
+   * @note The ownership of the returned object lies with the caller.
+   * @warning This method should only be called if isColumnAccessorSupported() method
+   *          returned true. If ColumnAccessor is not supported this method will return a nullptr.
+   *
+   * @param current_tuple_position A constant reference to the tuple position in the containing
+   *        ValueAccessor. This reference value is shared between the containing ValueAccessor &
+   *        a ColumnAccessor. However, a ColumnAccessor *CANNOT* modify this tuple position.
+   * @param attr_id The attribute id on which this ColumnAccessor will be created.
+   *
+   * @return A pointer to a ColumnAccessor object with specific properties set that can be used
+   *         in a tight loop iterations over the underlying storage block.
+   **/
+  template <bool check_null = true>
+  inline const ColumnAccessor<check_null>* getColumnAccessor(const tuple_id &current_tuple_position,
+                                                             const attribute_id attr_id) const {
+    // Return nullptr because this value accessor does not support column accessor yet.
+    return nullptr;
+  }
+
   template <bool check_null>
   inline const void* getAttributeValue(const tuple_id tuple,
                                        const attribute_id attr) const {

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/storage/CompressedPackedRowStoreValueAccessor.hpp
----------------------------------------------------------------------
diff --git a/storage/CompressedPackedRowStoreValueAccessor.hpp b/storage/CompressedPackedRowStoreValueAccessor.hpp
index 8858175..aeff2e1 100644
--- a/storage/CompressedPackedRowStoreValueAccessor.hpp
+++ b/storage/CompressedPackedRowStoreValueAccessor.hpp
@@ -75,6 +75,39 @@ class CompressedPackedRowStoreValueAccessorHelper {
     return num_tuples_;
   }
 
+  /**
+   * @brief Returns whether this accessor has a fast strided ColumnAccessor available
+   *        that can be used to optimize memory access in a tight loop iteration
+   *        over the underlying storage block.
+   *
+   * @return true if fast ColumnAccessor is supported, otherwise false.
+   */
+  inline bool isColumnAccessorSupported() const {
+    return false;
+  }
+
+  /**
+   * @brief Get a pointer to a ColumnAccessor object that provides a fast strided memory
+   *        access on the underlying storage block.
+   * @note The ownership of the returned object lies with the caller.
+   * @warning This method should only be called if isColumnAccessorSupported() method
+   *          returned true. If ColumnAccessor is not supported this method will return a nullptr.
+   *
+   * @param current_tuple_position A constant reference to the tuple position in the containing
+   *        ValueAccessor. This reference value is shared between the containing ValueAccessor &
+   *        a ColumnAccessor. However, a ColumnAccessor *CANNOT* modify this tuple position.
+   * @param attr_id The attribute id on which this ColumnAccessor will be created.
+   *
+   * @return A pointer to a ColumnAccessor object with specific properties set that can be used
+   *         in a tight loop iterations over the underlying storage block.
+   **/
+  template <bool check_null = true>
+  inline const ColumnAccessor<check_null>* getColumnAccessor(const tuple_id &current_tuple_position,
+                                                             const attribute_id attr_id) const {
+    // Return nullptr because this value accessor does not support column accessor yet.
+    return nullptr;
+  }
+
   template <bool check_null>
   inline const void* getAttributeValue(const tuple_id tuple,
                                        const attribute_id attr) const {

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/storage/PackedRowStoreValueAccessor.hpp
----------------------------------------------------------------------
diff --git a/storage/PackedRowStoreValueAccessor.hpp b/storage/PackedRowStoreValueAccessor.hpp
index 80edecd..7eb2d41 100644
--- a/storage/PackedRowStoreValueAccessor.hpp
+++ b/storage/PackedRowStoreValueAccessor.hpp
@@ -49,6 +49,60 @@ class PackedRowStoreValueAccessorHelper {
     return num_tuples_;
   }
 
+  /**
+   * @brief Returns whether this accessor has a fast strided ColumnAccessor available
+   *        that can be used to optimize memory access in a tight loop iteration
+   *        over the underlying storage block.
+   *
+   * @return true if fast ColumnAccessor is supported, otherwise false.
+   */
+  inline bool isColumnAccessorSupported() const {
+    return true;
+  }
+
+  /**
+   * @brief Get a pointer to a ColumnAccessor object that provides a fast strided memory
+   *        access on the underlying storage block.
+   * @note The ownership of the returned object lies with the caller.
+   * @warning This method should only be called if isColumnAccessorSupported() method
+   *          returned true. If ColumnAccessor is not supported this method will return a nullptr.
+   *
+   * @param current_tuple_position A constant reference to the tuple position in the containing
+   *        ValueAccessor. This reference value is shared between the containing ValueAccessor &
+   *        a ColumnAccessor. However, a ColumnAccessor *CANNOT* modify this tuple position.
+   * @param attr_id The attribute id on which this ColumnAccessor will be created.
+   *
+   * @return A pointer to a ColumnAccessor object with specific properties set that can be used
+   *         in a tight loop iterations over the underlying storage block.
+   **/
+  template <bool check_null = true>
+  inline const ColumnAccessor<check_null>* getColumnAccessor(const tuple_id &current_tuple_position,
+                                                             const attribute_id attr_id) const {
+    DEBUG_ASSERT(relation_.hasAttributeWithId(attr_id));
+    const void* base_location = static_cast<const char*>(tuple_storage_)
+        + relation_.getFixedLengthAttributeOffset(attr_id);
+    const std::size_t stride = relation_.getFixedByteLength();
+
+    std::unique_ptr<ColumnAccessor<check_null>> column_accessor;
+    if (check_null) {
+      const int nullable_base = relation_.getNullableAttributeIndex(attr_id);
+      const unsigned nullable_stride = relation_.numNullableAttributes();
+      column_accessor.reset(new ColumnAccessor<check_null>(current_tuple_position,
+                                                           num_tuples_,
+                                                           base_location,
+                                                           stride,
+                                                           null_bitmap_,
+                                                           nullable_base,
+                                                           nullable_stride));
+    } else {
+      column_accessor.reset(new ColumnAccessor<check_null>(current_tuple_position,
+                                                           num_tuples_,
+                                                           base_location,
+                                                           stride));
+    }
+    return column_accessor.release();
+  }
+
   template <bool check_null>
   inline const void* getAttributeValue(const tuple_id tuple,
                                        const attribute_id attr) const {

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/storage/SplitRowStoreValueAccessor.hpp
----------------------------------------------------------------------
diff --git a/storage/SplitRowStoreValueAccessor.hpp b/storage/SplitRowStoreValueAccessor.hpp
index 61bb7bf..951a20a 100644
--- a/storage/SplitRowStoreValueAccessor.hpp
+++ b/storage/SplitRowStoreValueAccessor.hpp
@@ -97,6 +97,24 @@ class SplitRowStoreValueAccessor : public ValueAccessor {
     return num_tuples_;
   }
 
+  /**
+   * @brief Get a pointer to a ColumnAccessor object that provides a fast strided memory
+   *        access on the underlying storage block.
+   * @note The ownership of the returned object lies with the caller.
+   * @warning This method should only be called if isColumnAccessorSupported() method
+   *          returned true. If ColumnAccessor is not supported this method will return a nullptr.
+   *
+   * @param attr_id The attribute id on which this ColumnAccessor will be created.
+   *
+   * @return A pointer to a ColumnAccessor object with specific properties set that can be used
+   *         in a tight loop iterations over the underlying storage block.
+   **/
+  template <bool check_null = true>
+  inline const ColumnAccessor<check_null>* getColumnAccessor(const attribute_id attr_id) const {
+    // Column Accessors are currently unsupported for this value accessor, hence nullptr.
+    return nullptr;
+  }
+
   template <bool check_null = true>
   inline const void* getUntypedValue(const attribute_id attr_id) const {
     return getUntypedValueAtAbsolutePosition<check_null>(attr_id, current_position_);

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/storage/ValueAccessor.hpp
----------------------------------------------------------------------
diff --git a/storage/ValueAccessor.hpp b/storage/ValueAccessor.hpp
index 70d4405..3b58a7c 100644
--- a/storage/ValueAccessor.hpp
+++ b/storage/ValueAccessor.hpp
@@ -41,6 +41,9 @@ namespace quickstep {
 
 class TupleStorageSubBlock;
 
+template <bool check_null = true>
+class ColumnAccessor;
+
 // TODO(chasseur): Iteration on ValueAccessors is row-at-a-time, but in some
 // cases column-wise data movement may be more efficient.
 
@@ -182,6 +185,18 @@ class ValueAccessor {
   virtual tuple_id getNumTuplesVirtual() const = 0;
 
   /**
+   * @brief Returns whether this accessor has a fast strided ColumnAccessor available
+   *        that can be used to optimize memory access in a tight loop iteration
+   *        over the underlying storage block. Specific derived classes should override
+   *        this method if they support ColumnAccessor.
+   *
+   * @return true if fast ColumnAccessor is supported, otherwise false.
+   */
+  virtual inline bool isColumnAccessorSupported() const {
+    return false;
+  }
+
+  /**
    * @brief Get a pointer to an untyped value for the current tuple in stateful
    *        iteration.
    * @note The inline version of this method provided by subclasses,
@@ -372,6 +387,24 @@ class TupleIdSequenceAdapterValueAccessor : public ValueAccessor {
     return id_sequence_.numTuples();
   }
 
+  /**
+   * @brief Get a pointer to a ColumnAccessor object that provides a fast strided memory
+   *        access on the underlying storage block.
+   * @note The ownership of the returned object lies with the caller.
+   * @warning This method should only be called if isColumnAccessorSupported() method
+   *          returned true. If ColumnAccessor is not supported this method will return a nullptr.
+   *
+   * @param attr_id The attribute id on which this ColumnAccessor will be created.
+   *
+   * @return A pointer to a ColumnAccessor object with specific properties set that can be used
+   *         in a tight loop iterations over the underlying storage block.
+   **/
+  template <bool check_null = true>
+  inline const ColumnAccessor<check_null>* getColumnAccessor(const attribute_id attr_id) const {
+    // Column Accessors are currently unsupported for this accessor, hence nullptr.
+    return nullptr;
+  }
+
   template <bool check_null = true>
   inline const void* getUntypedValue(const attribute_id attr_id) const {
     return accessor_->template getUntypedValueAtAbsolutePosition<check_null>(attr_id, *current_position_);
@@ -556,6 +589,24 @@ class OrderedTupleIdSequenceAdapterValueAccessor : public ValueAccessor {
     return id_sequence_.size();
   }
 
+  /**
+   * @brief Get a pointer to a ColumnAccessor object that provides a fast strided memory
+   *        access on the underlying storage block.
+   * @note The ownership of the returned object lies with the caller.
+   * @warning This method should only be called if isColumnAccessorSupported() method
+   *          returned true. If ColumnAccessor is not supported this method will return a nullptr.
+   *
+   * @param attr_id The attribute id on which this ColumnAccessor will be created.
+   *
+   * @return A pointer to a ColumnAccessor object with specific properties set that can be used
+   *         in a tight loop iterations over the underlying storage block.
+   **/
+  template <bool check_null = true>
+  inline const ColumnAccessor<check_null>* getColumnAccessor(const attribute_id attr_id) const {
+    // Column Accessors are currently unsupported for this accessor, hence nullptr.
+    return nullptr;
+  }
+
   template <bool check_null = true>
   inline const void* getUntypedValue(const attribute_id attr_id) const {
     return accessor_->template getUntypedValueAtAbsolutePosition<check_null>(attr_id,
@@ -743,6 +794,27 @@ class PackedTupleStorageSubBlockValueAccessor : public ValueAccessor {
     return getTypedValueAtAbsolutePosition(attr_id, current_tuple_);
   }
 
+  inline bool isColumnAccessorSupported() const override {
+    return helper_.isColumnAccessorSupported();
+  }
+
+  /**
+   * @brief Get a pointer to a ColumnAccessor object that provides a fast strided memory
+   *        access on the underlying storage block.
+   * @note The ownership of the returned object lies with the caller.
+   * @warning This method should only be called if isColumnAccessorSupported() method
+   *          returned true. If ColumnAccessor is not supported this method will return a nullptr.
+   *
+   * @param attr_id The attribute id on which this ColumnAccessor will be created.
+   *
+   * @return A pointer to a ColumnAccessor object with specific properties set that can be used
+   *         in a tight loop iterations over the underlying storage block.
+   **/
+  template <bool check_null = true>
+  inline const ColumnAccessor<check_null>* getColumnAccessor(const attribute_id attr_id) const {
+    return helper_.template getColumnAccessor<check_null>(current_tuple_, attr_id);
+  }
+
   template <bool check_null = true>
   inline const void* getUntypedValueAtAbsolutePosition(const attribute_id attr_id,
                                                        const tuple_id tid) const {
@@ -896,6 +968,77 @@ class PackedTupleStorageSubBlockValueAccessor : public ValueAccessor {
   DISALLOW_COPY_AND_ASSIGN(PackedTupleStorageSubBlockValueAccessor);
 };
 
+
+/**
+ * @brief ColumnAccessor is a helper template class that is used to optimize memory
+ *        access patterns for a ValueAccessor when it is used in a tight loop
+ *        to extract values for a given attribute from a given storage block.
+ **/
+template <bool check_null>
+class ColumnAccessor {
+ public:
+  /**
+   * @brief Constructor.
+   *
+   * @param current_tuple_position A constant reference to the tuple position in the containing
+   *        ValueAccessor. This reference value is shared between the containing ValueAccessor &
+   *        a ColumnAccessor. However, a ColumnAccessor *CANNOT* modify this tuple position.
+   * @param num_tuples Number of tuples for this block.
+   * @param base_address The starting address in memory for the first column value.
+   * @param stride The memory offset at which other column values will be found.
+   * @param null_bitmap The bitmap that will be referred in case of nullable attributes.
+   * @param nullable_base The starting index for the first nullable attribute in the bitmap.
+   *        Note that setting this value to -1 will essentially cause null checks to always
+   *        return false.
+   * @param nullable_stride The offset at which null bits will be found for
+   *        different attribute values.
+   **/
+  ColumnAccessor(const tuple_id &current_tuple_position,
+                 const std::size_t num_tuples,
+                 const void *base_address,
+                 const std::size_t stride,
+                 const BitVector<false> *null_bitmap = nullptr,
+                 const int nullable_base = -1,
+                 const unsigned nullable_stride = 0)
+      : current_tuple_position_(current_tuple_position),
+        num_tuples_(num_tuples),
+        base_address_(base_address),
+        stride_(stride),
+        null_bitmap_(null_bitmap),
+        nullable_base_(nullable_base),
+        nullable_stride_(nullable_stride) {
+  }
+
+  /**
+   * @brief Get a pointer to an untyped value for the current tuple in stateful
+   *        iteration over the given column.
+   *
+   * @return An untyped pointer to the attribute value for the current tuple.
+   **/
+  inline const void* getUntypedValue() const {
+    DEBUG_ASSERT(current_tuple_position_ < num_tuples_);
+    if (check_null) {
+      DEBUG_ASSERT(null_bitmap_ != nullptr);
+      if ((nullable_base_ != -1)
+          && null_bitmap_->getBit(current_tuple_position_ * nullable_stride_ + nullable_base_)) {
+        return nullptr;
+      }
+    }
+    return static_cast<const char*>(base_address_) + current_tuple_position_ * stride_;
+  }
+
+ private:
+  const tuple_id &current_tuple_position_;
+  const tuple_id num_tuples_;
+  const void *base_address_;
+  const std::size_t stride_;
+  const BitVector<false> *null_bitmap_;
+  const int nullable_base_;
+  const unsigned nullable_stride_;
+
+  DISALLOW_COPY_AND_ASSIGN(ColumnAccessor);
+};
+
 /** @} */
 
 }  // namespace quickstep

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/types/containers/ColumnVectorsValueAccessor.hpp
----------------------------------------------------------------------
diff --git a/types/containers/ColumnVectorsValueAccessor.hpp b/types/containers/ColumnVectorsValueAccessor.hpp
index 2300f3b..fe413a0 100644
--- a/types/containers/ColumnVectorsValueAccessor.hpp
+++ b/types/containers/ColumnVectorsValueAccessor.hpp
@@ -121,6 +121,24 @@ class ColumnVectorsValueAccessor : public ValueAccessor {
     return column_length_;
   }
 
+  /**
+   * @brief Get a pointer to a ColumnAccessor object that provides a fast strided memory
+   *        access on the underlying storage block.
+   * @note The ownership of the returned object lies with the caller.
+   * @warning This method should only be called if isColumnAccessorSupported() method
+   *          returned true. If ColumnAccessor is not supported this method will return a nullptr.
+   *
+   * @param attr_id The attribute id on which this ColumnAccessor will be created.
+   *
+   * @return A pointer to a ColumnAccessor object with specific properties set that can be used
+   *         in a tight loop iterations over the underlying storage block.
+   **/
+  template <bool check_null = true>
+  inline const ColumnAccessor<check_null>* getColumnAccessor(const attribute_id attr_id) const {
+    // Column Accessors are currently unsupported for this value accessor, hence nullptr.
+    return nullptr;
+  }
+
   template <bool check_null = true>
   inline const void* getUntypedValue(const attribute_id attr_id) const {
     return getUntypedValueAtAbsolutePosition<check_null>(attr_id, current_position_);

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/types/operations/comparisons/AsciiStringComparators-inl.hpp
----------------------------------------------------------------------
diff --git a/types/operations/comparisons/AsciiStringComparators-inl.hpp b/types/operations/comparisons/AsciiStringComparators-inl.hpp
index cde03c3..b048c60 100644
--- a/types/operations/comparisons/AsciiStringComparators-inl.hpp
+++ b/types/operations/comparisons/AsciiStringComparators-inl.hpp
@@ -273,13 +273,32 @@ TupleIdSequence* AsciiStringUncheckedComparator<ComparisonFunctor,
       }
     } else {
       accessor->beginIteration();
-      while (accessor->next()) {
-        const void *left_value = accessor->template getUntypedValue<left_nullable>(left_id);
-        const void *right_value = accessor->template getUntypedValue<right_nullable>(right_id);
-        result->set(accessor->getCurrentPosition(),
-                    (!(left_nullable && (left_value == nullptr))
-                        || (right_nullable && (right_value == nullptr)))
-                            && this->compareDataPtrsHelper<true>(left_value, right_value));
+      if (accessor->isColumnAccessorSupported()) {
+        // If ColumnAccessor is supported on the underlying accessor, we have a fast strided
+        // column accessor available for the iteration on the underlying block.
+        std::unique_ptr<const ColumnAccessor<left_nullable>>
+            left_column_accessor(accessor->template getColumnAccessor<left_nullable>(left_id));
+        std::unique_ptr<const ColumnAccessor<right_nullable>>
+            right_column_accessor(accessor->template getColumnAccessor<right_nullable>(right_id));
+        DEBUG_ASSERT(left_column_accessor != nullptr);
+        DEBUG_ASSERT(right_column_accessor != nullptr);
+        while (accessor->next()) {
+          const void *left_value = left_column_accessor->getUntypedValue();
+          const void *right_value = right_column_accessor->getUntypedValue();
+          result->set(accessor->getCurrentPosition(),
+                      (!(left_nullable && (left_value == nullptr))
+                          || (right_nullable && (right_value == nullptr)))
+                          && this->compareDataPtrsHelper<true>(left_value, right_value));
+        }
+      } else {
+        while (accessor->next()) {
+          const void *left_value = accessor->template getUntypedValue<left_nullable>(left_id);
+          const void *right_value = accessor->template getUntypedValue<right_nullable>(right_id);
+          result->set(accessor->getCurrentPosition(),
+                      (!(left_nullable && (left_value == nullptr))
+                          || (right_nullable && (right_value == nullptr)))
+                          && this->compareDataPtrsHelper<true>(left_value, right_value));
+        }
       }
       if (!short_circuit && (filter != nullptr)) {
         result->intersectWith(*filter);
@@ -333,12 +352,28 @@ TupleIdSequence* AsciiStringUncheckedComparator<ComparisonFunctor,
       }
     } else {
       accessor->beginIteration();
-      while (accessor->next()) {
-        const void *va_value
-            = accessor->template getUntypedValue<va_nullable>(value_accessor_attr_id);
-        result->set(accessor->getCurrentPosition(),
-                    !(va_nullable && (va_value == nullptr))
-                        && this->compareDataPtrsHelper<value_accessor_on_left>(va_value, static_string));
+      if (accessor->isColumnAccessorSupported()) {
+        // If ColumnAccessor is supported on the underlying accessor, we have a fast strided
+        // column accessor available for the iteration on the underlying block.
+        std::unique_ptr<const ColumnAccessor<va_nullable>>
+            column_accessor(accessor->template getColumnAccessor<va_nullable>(value_accessor_attr_id));
+        DEBUG_ASSERT(column_accessor != nullptr);
+        while (accessor->next()) {
+          const void *va_value = column_accessor->getUntypedValue();
+          result->set(accessor->getCurrentPosition(),
+                      !(va_nullable && (va_value == nullptr))
+                          && this->compareDataPtrsHelper<value_accessor_on_left>(va_value,
+                                                                                 static_string));
+        }
+      } else {
+        while (accessor->next()) {
+          const void *va_value
+              = accessor->template getUntypedValue<va_nullable>(value_accessor_attr_id);
+          result->set(accessor->getCurrentPosition(),
+                      !(va_nullable && (va_value == nullptr))
+                          && this->compareDataPtrsHelper<value_accessor_on_left>(va_value,
+                                                                                 static_string));
+        }
       }
       if (!short_circuit && (filter != nullptr)) {
         result->intersectWith(*filter);
@@ -448,16 +483,36 @@ TupleIdSequence* AsciiStringUncheckedComparator<ComparisonFunctor,
         } else {
           accessor->beginIteration();
           std::size_t cv_pos = 0;
-          while (accessor->next()) {
-            const void *cv_value
-                = column_vector.template getUntypedValue<cv_nullable>(cv_pos);
-            const void *va_value
-                = accessor->template getUntypedValue<va_nullable>(value_accessor_attr_id);
-            result->set(cv_pos,
-                        (!((cv_nullable && (cv_value == nullptr))
-                            || (va_nullable && (va_value == nullptr))))
-                                && this->compareDataPtrsHelper<column_vector_on_left>(cv_value, va_value));
-            ++cv_pos;
+          if (accessor->isColumnAccessorSupported()) {
+            // If ColumnAccessor is supported on the underlying accessor, we have a fast strided
+            // column accessor available for the iteration on the underlying block.
+            std::unique_ptr<const ColumnAccessor<va_nullable>>
+                column_accessor(accessor->template getColumnAccessor<va_nullable>(value_accessor_attr_id));
+            DEBUG_ASSERT(column_accessor != nullptr);
+            while (accessor->next()) {
+              const void *cv_value
+                  = column_vector.template getUntypedValue<cv_nullable>(cv_pos);
+              const void *va_value = column_accessor->getUntypedValue();
+              result->set(cv_pos,
+                          (!((cv_nullable && (cv_value == nullptr))
+                              || (va_nullable && (va_value == nullptr))))
+                              && this->compareDataPtrsHelper<column_vector_on_left>(cv_value,
+                                                                                    va_value));
+              ++cv_pos;
+            }
+          } else {
+            while (accessor->next()) {
+              const void *cv_value
+                  = column_vector.template getUntypedValue<cv_nullable>(cv_pos);
+              const void *va_value
+                  = accessor->template getUntypedValue<va_nullable>(value_accessor_attr_id);
+              result->set(cv_pos,
+                          (!((cv_nullable && (cv_value == nullptr))
+                              || (va_nullable && (va_value == nullptr))))
+                              && this->compareDataPtrsHelper<column_vector_on_left>(cv_value,
+                                                                                    va_value));
+              ++cv_pos;
+            }
           }
         }
         if (!short_circuit && (filter != nullptr)) {

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/types/operations/comparisons/Comparison-inl.hpp
----------------------------------------------------------------------
diff --git a/types/operations/comparisons/Comparison-inl.hpp b/types/operations/comparisons/Comparison-inl.hpp
index 25f5f15..96771bf 100644
--- a/types/operations/comparisons/Comparison-inl.hpp
+++ b/types/operations/comparisons/Comparison-inl.hpp
@@ -309,11 +309,28 @@ TupleIdSequence* UncheckedComparator::compareSingleValueAccessorDefaultImpl(
       }
     } else {
       accessor->beginIteration();
-      while (accessor->next()) {
-        result->set(accessor->getCurrentPosition(),
-                    this->compareDataPtrs(
-                        accessor->template getUntypedValue<left_nullable>(left_id),
-                        accessor->template getUntypedValue<right_nullable>(right_id)));
+      if (accessor->isColumnAccessorSupported()) {
+        // If ColumnAccessor is supported on the underlying accessor, we have a fast strided
+        // column accessor available for the iteration on the underlying block.
+        std::unique_ptr<const ColumnAccessor<left_nullable>>
+            left_column_accessor(accessor->template getColumnAccessor<left_nullable>(left_id));
+        std::unique_ptr<const ColumnAccessor<right_nullable>>
+            right_column_accessor(accessor->template getColumnAccessor<right_nullable>(right_id));
+        DEBUG_ASSERT(left_column_accessor != nullptr);
+        DEBUG_ASSERT(right_column_accessor != nullptr);
+        while (accessor->next()) {
+          result->set(accessor->getCurrentPosition(),
+                      this->compareDataPtrs(
+                          left_column_accessor->getUntypedValue(),
+                          right_column_accessor->getUntypedValue()));
+        }
+      } else {
+        while (accessor->next()) {
+          result->set(accessor->getCurrentPosition(),
+                      this->compareDataPtrs(
+                          accessor->template getUntypedValue<left_nullable>(left_id),
+                          accessor->template getUntypedValue<right_nullable>(right_id)));
+        }
       }
       if (!short_circuit && (filter != nullptr)) {
         result->intersectWith(*filter);

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/types/operations/comparisons/LiteralComparators-inl.hpp
----------------------------------------------------------------------
diff --git a/types/operations/comparisons/LiteralComparators-inl.hpp b/types/operations/comparisons/LiteralComparators-inl.hpp
index 14844ac..31eec13 100644
--- a/types/operations/comparisons/LiteralComparators-inl.hpp
+++ b/types/operations/comparisons/LiteralComparators-inl.hpp
@@ -273,13 +273,32 @@ TupleIdSequence* LiteralUncheckedComparator<ComparisonFunctor,
       }
     } else {
       accessor->beginIteration();
-      while (accessor->next()) {
-        const void *left_value = accessor->template getUntypedValue<left_nullable>(left_id);
-        const void *right_value = accessor->template getUntypedValue<right_nullable>(right_id);
-        result->set(accessor->getCurrentPosition(),
-                    (!((left_nullable && (left_value == nullptr))
-                        || (right_nullable && (right_value == nullptr))))
-                            && this->compareDataPtrsHelper<true>(left_value, right_value));
+      if (accessor->isColumnAccessorSupported()) {
+        // If ColumnAccessor is supported on the underlying accessor, we have a fast strided
+        // column accessor available for the iteration on the underlying block.
+        std::unique_ptr<const ColumnAccessor<left_nullable>>
+            left_column_accessor(accessor->template getColumnAccessor<left_nullable>(left_id));
+        std::unique_ptr<const ColumnAccessor<right_nullable>>
+            right_column_accessor(accessor->template getColumnAccessor<right_nullable>(right_id));
+        DEBUG_ASSERT(left_column_accessor != nullptr);
+        DEBUG_ASSERT(right_column_accessor != nullptr);
+        while (accessor->next()) {
+          const void *left_value = left_column_accessor->getUntypedValue();
+          const void *right_value = right_column_accessor->getUntypedValue();
+          result->set(accessor->getCurrentPosition(),
+                      (!((left_nullable && (left_value == nullptr))
+                          || (right_nullable && (right_value == nullptr))))
+                          && this->compareDataPtrsHelper<true>(left_value, right_value));
+        }
+      } else {
+        while (accessor->next()) {
+          const void *left_value = accessor->template getUntypedValue<left_nullable>(left_id);
+          const void *right_value = accessor->template getUntypedValue<right_nullable>(right_id);
+          result->set(accessor->getCurrentPosition(),
+                      (!((left_nullable && (left_value == nullptr))
+                          || (right_nullable && (right_value == nullptr))))
+                          && this->compareDataPtrsHelper<true>(left_value, right_value));
+        }
       }
       if (!short_circuit && (filter != nullptr)) {
         result->intersectWith(*filter);
@@ -339,12 +358,27 @@ TupleIdSequence* LiteralUncheckedComparator<ComparisonFunctor,
       }
     } else {
       accessor->beginIteration();
-      while (accessor->next()) {
-        const void *va_value
-            = accessor->template getUntypedValue<va_nullable>(value_accessor_attr_id);
-        result->set(accessor->getCurrentPosition(),
-                    !(va_nullable && (va_value == nullptr))
-                        && this->compareDataPtrsHelper<value_accessor_on_left>(va_value, &literal));
+      if (accessor->isColumnAccessorSupported()) {
+        // If ColumnAccessor is supported on the underlying accessor, we have a fast strided
+        // column accessor available for the iteration on the underlying block.
+        std::unique_ptr<const ColumnAccessor<va_nullable>>
+            column_accessor(accessor->template getColumnAccessor<va_nullable>(value_accessor_attr_id));
+        DEBUG_ASSERT(column_accessor != nullptr);
+        while (accessor->next()) {
+          const void *va_value = column_accessor->getUntypedValue();
+          result->set(accessor->getCurrentPosition(),
+                      !(va_nullable && (va_value == nullptr))
+                          && this->compareDataPtrsHelper<value_accessor_on_left>(va_value, &literal));
+        }
+      } else {
+        while (accessor->next()) {
+          const void *va_value
+              = accessor->template getUntypedValue<va_nullable>(value_accessor_attr_id);
+          result->set(accessor->getCurrentPosition(),
+                      !(va_nullable && (va_value == nullptr))
+                          && this->compareDataPtrsHelper<value_accessor_on_left>(va_value,
+                                                                                 &literal));
+        }
       }
       if (!short_circuit && (filter != nullptr)) {
         result->intersectWith(*filter);
@@ -458,16 +492,36 @@ TupleIdSequence* LiteralUncheckedComparator<ComparisonFunctor,
       } else {
         accessor->beginIteration();
         std::size_t cv_pos = 0;
-        while (accessor->next()) {
-          const void *cv_value
-              = native_column_vector.getUntypedValue<cv_nullable>(cv_pos);
-          const void *va_value
-              = accessor->template getUntypedValue<va_nullable>(value_accessor_attr_id);
-          result->set(cv_pos,
-                      (!((cv_nullable && (cv_value == nullptr))
-                          || (va_nullable && (va_value == nullptr))))
-                              && this->compareDataPtrsHelper<column_vector_on_left>(cv_value, va_value));
-          ++cv_pos;
+        if (accessor->isColumnAccessorSupported()) {
+          // If ColumnAccessor is supported on the underlying accessor, we have a fast strided
+          // column accessor available for the iteration on the underlying block.
+          std::unique_ptr<const ColumnAccessor<va_nullable>>
+              column_accessor(accessor->template getColumnAccessor<va_nullable>(value_accessor_attr_id));
+          DEBUG_ASSERT(column_accessor != nullptr);
+          while (accessor->next()) {
+            const void *cv_value
+                = native_column_vector.getUntypedValue<cv_nullable>(cv_pos);
+            const void *va_value = column_accessor->getUntypedValue();
+            result->set(cv_pos,
+                        (!((cv_nullable && (cv_value == nullptr))
+                            || (va_nullable && (va_value == nullptr))))
+                            && this->compareDataPtrsHelper<column_vector_on_left>(cv_value,
+                                                                                  va_value));
+            ++cv_pos;
+          }
+        } else {
+          while (accessor->next()) {
+            const void *cv_value
+                = native_column_vector.getUntypedValue<cv_nullable>(cv_pos);
+            const void *va_value
+                = accessor->template getUntypedValue<va_nullable>(value_accessor_attr_id);
+            result->set(cv_pos,
+                        (!((cv_nullable && (cv_value == nullptr))
+                            || (va_nullable && (va_value == nullptr))))
+                            && this->compareDataPtrsHelper<column_vector_on_left>(cv_value,
+                                                                                  va_value));
+            ++cv_pos;
+          }
         }
       }
       if (!short_circuit && (filter != nullptr)) {
@@ -495,13 +549,30 @@ TypedValue LiteralUncheckedComparator<ComparisonFunctor,
       accessor,
       [&](auto *accessor) -> void {  // NOLINT(build/c++11)
     accessor->beginIteration();
-    while (accessor->next()) {
-      const void *va_value = accessor->template getUntypedValue<left_nullable>(value_accessor_id);
-      if (left_nullable && !va_value) {
-        continue;
+    if (accessor->isColumnAccessorSupported()) {
+      // If ColumnAccessor is supported on the underlying accessor, we have a fast strided
+      // column accessor available for the iteration on the underlying block.
+      std::unique_ptr<const ColumnAccessor<left_nullable>>
+          column_accessor(accessor->template getColumnAccessor<left_nullable>(value_accessor_id));
+      DEBUG_ASSERT(column_accessor != nullptr);
+      while (accessor->next()) {
+        const void *va_value = column_accessor->getUntypedValue();
+        if (left_nullable && !va_value) {
+          continue;
+        }
+        if (!current_literal || this->compareDataPtrsHelper<true>(va_value, current_literal)) {
+          current_literal = va_value;
+        }
       }
-      if (!current_literal || this->compareDataPtrsHelper<true>(va_value, current_literal)) {
-        current_literal = va_value;
+    } else {
+      while (accessor->next()) {
+        const void *va_value = accessor->template getUntypedValue<left_nullable>(value_accessor_id);
+        if (left_nullable && !va_value) {
+          continue;
+        }
+        if (!current_literal || this->compareDataPtrsHelper<true>(va_value, current_literal)) {
+          current_literal = va_value;
+        }
       }
     }
   });

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/743f6b0a/types/operations/comparisons/PatternMatchingComparators-inl.hpp
----------------------------------------------------------------------
diff --git a/types/operations/comparisons/PatternMatchingComparators-inl.hpp b/types/operations/comparisons/PatternMatchingComparators-inl.hpp
index 617eadf..ca0f45e 100644
--- a/types/operations/comparisons/PatternMatchingComparators-inl.hpp
+++ b/types/operations/comparisons/PatternMatchingComparators-inl.hpp
@@ -241,11 +241,25 @@ TupleIdSequence* PatternMatchingUncheckedComparator<is_like_pattern, is_negation
       }
     } else {
       accessor->beginIteration();
-      while (accessor->next()) {
-        const void *va_value
-            = accessor->template getUntypedValue<left_nullable>(value_accessor_attr_id);
-        result->set(accessor->getCurrentPosition(),
-                    this->matchDataPtrWithPattern(va_value, re2_pattern));
+      if (accessor->isColumnAccessorSupported()) {
+        // If ColumnAccessor is supported on the underlying accessor, we have a fast strided
+        // column accessor available for the iteration on the underlying block.
+        std::unique_ptr<const ColumnAccessor<left_nullable>>
+            column_accessor
+            (accessor->template getColumnAccessor<left_nullable>(value_accessor_attr_id));
+        DEBUG_ASSERT(column_accessor != nullptr);
+        while (accessor->next()) {
+          const void *va_value = column_accessor->getUntypedValue();
+          result->set(accessor->getCurrentPosition(),
+                      this->matchDataPtrWithPattern(va_value, re2_pattern));
+        }
+      } else {
+        while (accessor->next()) {
+          const void *va_value
+              = accessor->template getUntypedValue<left_nullable>(value_accessor_attr_id);
+          result->set(accessor->getCurrentPosition(),
+                      this->matchDataPtrWithPattern(va_value, re2_pattern));
+        }
       }
       if (!short_circuit && (filter != nullptr)) {
         result->intersectWith(*filter);



[2/9] incubator-quickstep git commit: IWYU fixes for QueryExecutionUtil.

Posted by hb...@apache.org.
IWYU fixes for QueryExecutionUtil.


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

Branch: refs/heads/partitioned-aggregate-new
Commit: b5dcb6d29805dce944c11d5ad0720a3267ad57cf
Parents: 2e02333
Author: Zuyu Zhang <zu...@apache.org>
Authored: Sun Oct 9 15:48:03 2016 -0700
Committer: Zuyu Zhang <zu...@apache.org>
Committed: Sun Oct 9 15:48:03 2016 -0700

----------------------------------------------------------------------
 query_execution/CMakeLists.txt         |  1 -
 query_execution/QueryExecutionUtil.hpp | 34 ++++++++++++++++-------------
 2 files changed, 19 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/b5dcb6d2/query_execution/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/query_execution/CMakeLists.txt b/query_execution/CMakeLists.txt
index 1b27194..6a84be1 100644
--- a/query_execution/CMakeLists.txt
+++ b/query_execution/CMakeLists.txt
@@ -217,7 +217,6 @@ target_link_libraries(quickstep_queryexecution_QueryExecutionTypedefs
 target_link_libraries(quickstep_queryexecution_QueryExecutionUtil
                       quickstep_queryexecution_AdmitRequestMessage
                       quickstep_queryexecution_QueryExecutionTypedefs
-                      quickstep_queryexecution_WorkerMessage
                       quickstep_utility_Macros
                       tmb)
 target_link_libraries(quickstep_queryexecution_QueryManagerBase

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/b5dcb6d2/query_execution/QueryExecutionUtil.hpp
----------------------------------------------------------------------
diff --git a/query_execution/QueryExecutionUtil.hpp b/query_execution/QueryExecutionUtil.hpp
index feb4cc0..7a3a3b3 100644
--- a/query_execution/QueryExecutionUtil.hpp
+++ b/query_execution/QueryExecutionUtil.hpp
@@ -20,26 +20,30 @@
 #ifndef QUICKSTEP_QUERY_EXECUTION_QUERY_EXECUTION_UTIL_HPP_
 #define QUICKSTEP_QUERY_EXECUTION_QUERY_EXECUTION_UTIL_HPP_
 
+#include <cstddef>
 #include <memory>
 #include <utility>
 
 #include "query_execution/AdmitRequestMessage.hpp"
 #include "query_execution/QueryExecutionTypedefs.hpp"
-#include "query_execution/WorkerMessage.hpp"
 #include "utility/Macros.hpp"
 
 #include "glog/logging.h"
 
 #include "tmb/address.h"
 #include "tmb/id_typedefs.h"
-#include "tmb/message_style.h"
 #include "tmb/message_bus.h"
+#include "tmb/message_style.h"
 #include "tmb/tagged_message.h"
 
 namespace quickstep {
 
 class QueryHandle;
 
+/** \addtogroup QueryExecution
+ *  @{
+ */
+
 /**
  * @brief A static class for reusable methods in query_execution module.
  **/
@@ -57,14 +61,14 @@ class QueryExecutionUtil {
    *         The caller should ensure that the status is SendStatus::kOK.
    **/
   static tmb::MessageBus::SendStatus SendTMBMessage(
-      MessageBus *bus,
-      client_id sender_id,
-      client_id receiver_id,
-      TaggedMessage &&tagged_message) {  // NOLINT(whitespace/operators)
-    Address receiver_address;
+      tmb::MessageBus *bus,
+      tmb::client_id sender_id,
+      tmb::client_id receiver_id,
+      tmb::TaggedMessage &&tagged_message) {  // NOLINT(whitespace/operators)
+    tmb::Address receiver_address;
     receiver_address.AddRecipient(receiver_id);
 
-    MessageStyle single_receiver_style;
+    tmb::MessageStyle single_receiver_style;
     return bus->Send(sender_id,
                      receiver_address,
                      single_receiver_style,
@@ -88,11 +92,11 @@ class QueryExecutionUtil {
       const tmb::client_id sender_id,
       const tmb::client_id receiver_id,
       QueryHandle *query_handle,
-      MessageBus *bus) {
+      tmb::MessageBus *bus) {
     std::unique_ptr<AdmitRequestMessage> request_message(
         new AdmitRequestMessage(query_handle));
     const std::size_t size_of_request_msg = sizeof(*request_message);
-    TaggedMessage admit_tagged_message(
+    tmb::TaggedMessage admit_tagged_message(
         request_message.release(), size_of_request_msg, kAdmitRequestMessage);
 
     return QueryExecutionUtil::SendTMBMessage(
@@ -111,9 +115,9 @@ class QueryExecutionUtil {
    **/
   static void ReceiveQueryCompletionMessage(const tmb::client_id receiver_id,
                                             tmb::MessageBus *bus) {
-    const AnnotatedMessage annotated_msg =
+    const tmb::AnnotatedMessage annotated_msg =
         bus->Receive(receiver_id, 0, true);
-    const TaggedMessage &tagged_message = annotated_msg.tagged_message;
+    const tmb::TaggedMessage &tagged_message = annotated_msg.tagged_message;
     DCHECK_EQ(kWorkloadCompletionMessage, tagged_message.message_type());
   }
 
@@ -122,11 +126,11 @@ class QueryExecutionUtil {
     // The sender thread broadcasts poison message to the workers and foreman.
     // Each worker dies after receiving poison message. The order of workers'
     // death is irrelavant.
-    MessageStyle style;
+    tmb::MessageStyle style;
     style.Broadcast(true);
-    Address address;
+    tmb::Address address;
     address.All(true);
-    TaggedMessage poison_tagged_message(kPoisonMessage);
+    tmb::TaggedMessage poison_tagged_message(kPoisonMessage);
 
     DLOG(INFO) << "TMB client ID " << sender_id
                << " broadcast PoisonMessage (typed '" << kPoisonMessage << "') to all";


[8/9] incubator-quickstep git commit: Refactor ScalarAttribute to take benefit of ColumnAccessors

Posted by hb...@apache.org.
Refactor ScalarAttribute to take benefit of ColumnAccessors


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

Branch: refs/heads/partitioned-aggregate-new
Commit: e84524686d77397912052772224d7cfe8dec824a
Parents: 262ad5a
Author: Saket Saurabh <ss...@cs.wisc.edu>
Authored: Fri Sep 23 12:42:40 2016 -0500
Committer: Saket Saurabh <ss...@cs.wisc.edu>
Committed: Tue Oct 11 11:36:57 2016 -0500

----------------------------------------------------------------------
 expressions/scalar/ScalarAttribute.cpp          | 43 ++++++++++++++++----
 storage/BasicColumnStoreValueAccessor.hpp       |  2 +-
 storage/PackedRowStoreValueAccessor.hpp         |  2 +-
 storage/ValueAccessor.hpp                       |  4 +-
 ...kedRowStoreTupleStorageSubBlock_unittest.cpp | 10 ++---
 .../comparisons/AsciiStringComparators-inl.hpp  |  8 ++--
 types/operations/comparisons/Comparison-inl.hpp |  4 +-
 .../comparisons/LiteralComparators-inl.hpp      | 10 ++---
 .../PatternMatchingComparators-inl.hpp          |  2 +-
 9 files changed, 55 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/e8452468/expressions/scalar/ScalarAttribute.cpp
----------------------------------------------------------------------
diff --git a/expressions/scalar/ScalarAttribute.cpp b/expressions/scalar/ScalarAttribute.cpp
index 08dc9dd..b29286b 100644
--- a/expressions/scalar/ScalarAttribute.cpp
+++ b/expressions/scalar/ScalarAttribute.cpp
@@ -100,18 +100,43 @@ ColumnVector* ScalarAttribute::getAllValues(ValueAccessor *accessor,
                                                           accessor->getNumTuples());
       accessor->beginIteration();
       if (result_type.isNullable()) {
-        while (accessor->next()) {
-          const void *value = accessor->template getUntypedValue<true>(attr_id);
-          if (value == nullptr) {
-            result->appendNullValue();
-          } else {
-            result->appendUntypedValue(value);
+        if (accessor->isColumnAccessorSupported()) {
+          // If ColumnAccessor is supported on the underlying accessor, we have a fast strided
+          // column accessor available for the iteration on the underlying block.
+          // Since the attributes can be null, ColumnAccessor template takes a 'true' argument.
+          std::unique_ptr<const ColumnAccessor<true>>
+              column_accessor(accessor->template getColumnAccessor<true>(attr_id));
+          while (accessor->next()) {
+            const void *value = column_accessor->getUntypedValue();  // Fast strided access.
+            if (value == nullptr) {
+              result->appendNullValue();
+            } else {
+              result->appendUntypedValue(value);
+            }
+          }
+        } else {
+          while (accessor->next()) {
+            const void *value = accessor->template getUntypedValue<true>(attr_id);
+            if (value == nullptr) {
+              result->appendNullValue();
+            } else {
+              result->appendUntypedValue(value);
+            }
           }
         }
       } else {
-        while (accessor->next()) {
-          result->appendUntypedValue(
-              accessor->template getUntypedValue<false>(attr_id));
+        if (accessor->isColumnAccessorSupported()) {
+          // Since the attributes cannot be null, ColumnAccessor template takes a 'false' argument.
+          std::unique_ptr<const ColumnAccessor<false>>
+              column_accessor(accessor->template getColumnAccessor<false>(attr_id));
+          while (accessor->next()) {
+            result->appendUntypedValue(column_accessor->getUntypedValue());  // Fast strided access.
+          }
+        } else {
+          while (accessor->next()) {
+            result->appendUntypedValue(
+                accessor->template getUntypedValue<false>(attr_id));
+          }
         }
       }
       return result;

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/e8452468/storage/BasicColumnStoreValueAccessor.hpp
----------------------------------------------------------------------
diff --git a/storage/BasicColumnStoreValueAccessor.hpp b/storage/BasicColumnStoreValueAccessor.hpp
index 22d3c0b..7516dc9 100644
--- a/storage/BasicColumnStoreValueAccessor.hpp
+++ b/storage/BasicColumnStoreValueAccessor.hpp
@@ -81,7 +81,7 @@ class BasicColumnStoreValueAccessorHelper {
   template <bool check_null = true>
   inline const ColumnAccessor<check_null>* getColumnAccessor(const tuple_id &current_tuple_position,
                                                              const attribute_id attr_id) const {
-    DEBUG_ASSERT(relation_.hasAttributeWithId(attr_id));
+    DCHECK(relation_.hasAttributeWithId(attr_id));
     const void* base_location = static_cast<const char*>(column_stripes_[attr_id]);
     const std::size_t stride = relation_.getAttributeById(attr_id)->getType().maximumByteLength();
     std::unique_ptr<ColumnAccessor<check_null>> column_accessor;

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/e8452468/storage/PackedRowStoreValueAccessor.hpp
----------------------------------------------------------------------
diff --git a/storage/PackedRowStoreValueAccessor.hpp b/storage/PackedRowStoreValueAccessor.hpp
index 7eb2d41..9d43955 100644
--- a/storage/PackedRowStoreValueAccessor.hpp
+++ b/storage/PackedRowStoreValueAccessor.hpp
@@ -78,7 +78,7 @@ class PackedRowStoreValueAccessorHelper {
   template <bool check_null = true>
   inline const ColumnAccessor<check_null>* getColumnAccessor(const tuple_id &current_tuple_position,
                                                              const attribute_id attr_id) const {
-    DEBUG_ASSERT(relation_.hasAttributeWithId(attr_id));
+    DCHECK(relation_.hasAttributeWithId(attr_id));
     const void* base_location = static_cast<const char*>(tuple_storage_)
         + relation_.getFixedLengthAttributeOffset(attr_id);
     const std::size_t stride = relation_.getFixedByteLength();

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/e8452468/storage/ValueAccessor.hpp
----------------------------------------------------------------------
diff --git a/storage/ValueAccessor.hpp b/storage/ValueAccessor.hpp
index 3b58a7c..e4a2906 100644
--- a/storage/ValueAccessor.hpp
+++ b/storage/ValueAccessor.hpp
@@ -1016,9 +1016,9 @@ class ColumnAccessor {
    * @return An untyped pointer to the attribute value for the current tuple.
    **/
   inline const void* getUntypedValue() const {
-    DEBUG_ASSERT(current_tuple_position_ < num_tuples_);
+    DCHECK(current_tuple_position_ < num_tuples_);
     if (check_null) {
-      DEBUG_ASSERT(null_bitmap_ != nullptr);
+      DCHECK(null_bitmap_ != nullptr);
       if ((nullable_base_ != -1)
           && null_bitmap_->getBit(current_tuple_position_ * nullable_stride_ + nullable_base_)) {
         return nullptr;

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/e8452468/storage/tests/PackedRowStoreTupleStorageSubBlock_unittest.cpp
----------------------------------------------------------------------
diff --git a/storage/tests/PackedRowStoreTupleStorageSubBlock_unittest.cpp b/storage/tests/PackedRowStoreTupleStorageSubBlock_unittest.cpp
index a6f6606..924f9b1 100644
--- a/storage/tests/PackedRowStoreTupleStorageSubBlock_unittest.cpp
+++ b/storage/tests/PackedRowStoreTupleStorageSubBlock_unittest.cpp
@@ -250,7 +250,7 @@ class PackedRowStoreTupleStorageSubBlockTest : public ::testing::TestWithParam<b
                                                     tuple_store_->getAttributeValueTyped(tid, 2)));
     }
   }
-  
+
   template<bool check_null>
   void checkColumnAccessor() {
     initializeNewBlock(kSubBlockSize);
@@ -269,7 +269,7 @@ class PackedRowStoreTupleStorageSubBlockTest : public ::testing::TestWithParam<b
       while (accessor->next()) {
         const void *va_value = column_accessor->getUntypedValue();
         std::unique_ptr<Tuple> expected_tuple(createSampleTuple(tid));
-         
+
         if (expected_tuple->getAttributeValue(value_accessor_id).isNull()) {
           ASSERT_TRUE(va_value == nullptr);
         } else {
@@ -406,11 +406,11 @@ TEST_P(PackedRowStoreTupleStorageSubBlockTest, InsertInBatchTest) {
   EXPECT_EQ(row_capacity - 1, tuple_store_->getMaxTupleID());
   EXPECT_EQ(row_capacity, tuple_store_->numTuples());
 }
-  
+
 TEST_P(PackedRowStoreTupleStorageSubBlockTest, ColumnAccessorTest) {
-  if (GetParam()) { // when true, the attributes can be nullable.
+  if (GetParam()) {   // when true, the attributes can be nullable.
     checkColumnAccessor<true>();
-  } else { // when false, the attributes are non-null.
+  } else {   // when false, the attributes are non-null.
     checkColumnAccessor<false>();
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/e8452468/types/operations/comparisons/AsciiStringComparators-inl.hpp
----------------------------------------------------------------------
diff --git a/types/operations/comparisons/AsciiStringComparators-inl.hpp b/types/operations/comparisons/AsciiStringComparators-inl.hpp
index b048c60..87d7168 100644
--- a/types/operations/comparisons/AsciiStringComparators-inl.hpp
+++ b/types/operations/comparisons/AsciiStringComparators-inl.hpp
@@ -280,8 +280,8 @@ TupleIdSequence* AsciiStringUncheckedComparator<ComparisonFunctor,
             left_column_accessor(accessor->template getColumnAccessor<left_nullable>(left_id));
         std::unique_ptr<const ColumnAccessor<right_nullable>>
             right_column_accessor(accessor->template getColumnAccessor<right_nullable>(right_id));
-        DEBUG_ASSERT(left_column_accessor != nullptr);
-        DEBUG_ASSERT(right_column_accessor != nullptr);
+        DCHECK(left_column_accessor != nullptr);
+        DCHECK(right_column_accessor != nullptr);
         while (accessor->next()) {
           const void *left_value = left_column_accessor->getUntypedValue();
           const void *right_value = right_column_accessor->getUntypedValue();
@@ -357,7 +357,7 @@ TupleIdSequence* AsciiStringUncheckedComparator<ComparisonFunctor,
         // column accessor available for the iteration on the underlying block.
         std::unique_ptr<const ColumnAccessor<va_nullable>>
             column_accessor(accessor->template getColumnAccessor<va_nullable>(value_accessor_attr_id));
-        DEBUG_ASSERT(column_accessor != nullptr);
+        DCHECK(column_accessor != nullptr);
         while (accessor->next()) {
           const void *va_value = column_accessor->getUntypedValue();
           result->set(accessor->getCurrentPosition(),
@@ -488,7 +488,7 @@ TupleIdSequence* AsciiStringUncheckedComparator<ComparisonFunctor,
             // column accessor available for the iteration on the underlying block.
             std::unique_ptr<const ColumnAccessor<va_nullable>>
                 column_accessor(accessor->template getColumnAccessor<va_nullable>(value_accessor_attr_id));
-            DEBUG_ASSERT(column_accessor != nullptr);
+            DCHECK(column_accessor != nullptr);
             while (accessor->next()) {
               const void *cv_value
                   = column_vector.template getUntypedValue<cv_nullable>(cv_pos);

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/e8452468/types/operations/comparisons/Comparison-inl.hpp
----------------------------------------------------------------------
diff --git a/types/operations/comparisons/Comparison-inl.hpp b/types/operations/comparisons/Comparison-inl.hpp
index 96771bf..c892a16 100644
--- a/types/operations/comparisons/Comparison-inl.hpp
+++ b/types/operations/comparisons/Comparison-inl.hpp
@@ -316,8 +316,8 @@ TupleIdSequence* UncheckedComparator::compareSingleValueAccessorDefaultImpl(
             left_column_accessor(accessor->template getColumnAccessor<left_nullable>(left_id));
         std::unique_ptr<const ColumnAccessor<right_nullable>>
             right_column_accessor(accessor->template getColumnAccessor<right_nullable>(right_id));
-        DEBUG_ASSERT(left_column_accessor != nullptr);
-        DEBUG_ASSERT(right_column_accessor != nullptr);
+        DCHECK(left_column_accessor != nullptr);
+        DCHECK(right_column_accessor != nullptr);
         while (accessor->next()) {
           result->set(accessor->getCurrentPosition(),
                       this->compareDataPtrs(

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/e8452468/types/operations/comparisons/LiteralComparators-inl.hpp
----------------------------------------------------------------------
diff --git a/types/operations/comparisons/LiteralComparators-inl.hpp b/types/operations/comparisons/LiteralComparators-inl.hpp
index 31eec13..fd59e2e 100644
--- a/types/operations/comparisons/LiteralComparators-inl.hpp
+++ b/types/operations/comparisons/LiteralComparators-inl.hpp
@@ -280,8 +280,8 @@ TupleIdSequence* LiteralUncheckedComparator<ComparisonFunctor,
             left_column_accessor(accessor->template getColumnAccessor<left_nullable>(left_id));
         std::unique_ptr<const ColumnAccessor<right_nullable>>
             right_column_accessor(accessor->template getColumnAccessor<right_nullable>(right_id));
-        DEBUG_ASSERT(left_column_accessor != nullptr);
-        DEBUG_ASSERT(right_column_accessor != nullptr);
+        DCHECK(left_column_accessor != nullptr);
+        DCHECK(right_column_accessor != nullptr);
         while (accessor->next()) {
           const void *left_value = left_column_accessor->getUntypedValue();
           const void *right_value = right_column_accessor->getUntypedValue();
@@ -363,7 +363,7 @@ TupleIdSequence* LiteralUncheckedComparator<ComparisonFunctor,
         // column accessor available for the iteration on the underlying block.
         std::unique_ptr<const ColumnAccessor<va_nullable>>
             column_accessor(accessor->template getColumnAccessor<va_nullable>(value_accessor_attr_id));
-        DEBUG_ASSERT(column_accessor != nullptr);
+        DCHECK(column_accessor != nullptr);
         while (accessor->next()) {
           const void *va_value = column_accessor->getUntypedValue();
           result->set(accessor->getCurrentPosition(),
@@ -497,7 +497,7 @@ TupleIdSequence* LiteralUncheckedComparator<ComparisonFunctor,
           // column accessor available for the iteration on the underlying block.
           std::unique_ptr<const ColumnAccessor<va_nullable>>
               column_accessor(accessor->template getColumnAccessor<va_nullable>(value_accessor_attr_id));
-          DEBUG_ASSERT(column_accessor != nullptr);
+          DCHECK(column_accessor != nullptr);
           while (accessor->next()) {
             const void *cv_value
                 = native_column_vector.getUntypedValue<cv_nullable>(cv_pos);
@@ -554,7 +554,7 @@ TypedValue LiteralUncheckedComparator<ComparisonFunctor,
       // column accessor available for the iteration on the underlying block.
       std::unique_ptr<const ColumnAccessor<left_nullable>>
           column_accessor(accessor->template getColumnAccessor<left_nullable>(value_accessor_id));
-      DEBUG_ASSERT(column_accessor != nullptr);
+      DCHECK(column_accessor != nullptr);
       while (accessor->next()) {
         const void *va_value = column_accessor->getUntypedValue();
         if (left_nullable && !va_value) {

http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/e8452468/types/operations/comparisons/PatternMatchingComparators-inl.hpp
----------------------------------------------------------------------
diff --git a/types/operations/comparisons/PatternMatchingComparators-inl.hpp b/types/operations/comparisons/PatternMatchingComparators-inl.hpp
index ca0f45e..a7f0777 100644
--- a/types/operations/comparisons/PatternMatchingComparators-inl.hpp
+++ b/types/operations/comparisons/PatternMatchingComparators-inl.hpp
@@ -247,7 +247,7 @@ TupleIdSequence* PatternMatchingUncheckedComparator<is_like_pattern, is_negation
         std::unique_ptr<const ColumnAccessor<left_nullable>>
             column_accessor
             (accessor->template getColumnAccessor<left_nullable>(value_accessor_attr_id));
-        DEBUG_ASSERT(column_accessor != nullptr);
+        DCHECK(column_accessor != nullptr);
         while (accessor->next()) {
           const void *va_value = column_accessor->getUntypedValue();
           result->set(accessor->getCurrentPosition(),