[Groonga-commit] groonga/groonga at 4f04976 [master] Add support for in_values() estimation

Back to archive index
Kouhei Sutou null+****@clear*****
Thu Apr 25 16:38:20 JST 2019


Kouhei Sutou	2019-04-25 16:38:20 +0900 (Thu, 25 Apr 2019)

  Revision: 4f0497672afe133d151653b258f1d8b1870ace82
  https://github.com/groonga/groonga/commit/4f0497672afe133d151653b258f1d8b1870ace82

  Message:
    Add support for in_values() estimation

  Modified files:
    lib/mrb/scripts/expression_tree/binary_operation.rb
    lib/mrb/scripts/expression_tree/function_call.rb
    test/mruby/suite/query_optimizer/test_estimate_size.rb

  Modified: lib/mrb/scripts/expression_tree/binary_operation.rb (+28 -0)
===================================================================
--- lib/mrb/scripts/expression_tree/binary_operation.rb    2019-04-25 16:19:29 +0900 (3431e9821)
+++ lib/mrb/scripts/expression_tree/binary_operation.rb    2019-04-25 16:38:20 +0900 (052d1086a)
@@ -51,6 +51,8 @@ module Groonga
       ]
       def estimate_size(table)
         case @operator
+        when Operator::EQUAL
+          estimate_size_equal(table)
         when *RANGE_OPERATORS
           estimate_size_range(table)
         when *QUERY_OPERATIONS
@@ -63,6 +65,32 @@ module Groonga
       end
 
       private
+      def estimate_size_equal(table)
+        return table.size unles****@left*****_a?(Variable)
+        return table.size unles****@right*****_a?(Constant)
+
+        column =****@left*****
+        value =****@right*****
+        index_info = column.find_index(@operator)
+        return table.size if index_info.nil?
+
+        index_column = index_info.index
+        return table.size unless index_column.respond_to?(:lexicon)
+
+        lexicon = index_column.lexicon
+        term = value.value
+        if value.domain == lexicon.id
+          term_id = term.id
+        else
+          term_id = lexicon[term]
+        end
+        if term_id.nil?
+          0
+        else
+          index_column.estimate_size(term_id: term_id)
+        end
+      end
+
       def estimate_size_range(table)
         return table.size unles****@left*****_a?(Variable)
         return table.size unles****@right*****_a?(Constant)

  Modified: lib/mrb/scripts/expression_tree/function_call.rb (+19 -1)
===================================================================
--- lib/mrb/scripts/expression_tree/function_call.rb    2019-04-25 16:19:29 +0900 (23c04b6f6)
+++ lib/mrb/scripts/expression_tree/function_call.rb    2019-04-25 16:38:20 +0900 (50ff3754e)
@@ -21,8 +21,18 @@ module Groonga
       end
 
       def estimate_size(table)
-        return table.size unles****@proce***** == "between"
+        case****@proce*****
+        when "between"
+          estimate_size_between(table)
+        when "in_values"
+          estimate_size_in_values(table)
+        else
+          table.size
+        end
+      end
 
+      private
+      def estimate_size_between(table)
         column, min, min_border, max, max_border = @arguments
 
         if column.is_a?(Groonga::ExpressionTree::IndexColumn)
@@ -65,6 +75,14 @@ module Groonga
           index_column.estimate_size(:lexicon_cursor => cursor)
         end
       end
+
+      def estimate_size_in_values(table)
+        column, *values = @arguments
+        values.inject(0) do |sum, value|
+          node = BinaryOperation.new(Operator::EQUAL, column, value)
+          sum + node.estimate_size(table)
+        end
+      end
     end
   end
 end

  Modified: test/mruby/suite/query_optimizer/test_estimate_size.rb (+41 -0)
===================================================================
--- test/mruby/suite/query_optimizer/test_estimate_size.rb    2019-04-25 16:19:29 +0900 (3515349b6)
+++ test/mruby/suite/query_optimizer/test_estimate_size.rb    2019-04-25 16:38:20 +0900 (5804eb116)
@@ -270,6 +270,47 @@ class TestEstimateSize < QueryOptimizerTestCase
     end
   end
 
+  class TestInValuesSearch < self
+    def setup
+      Groonga::Schema.define do |schema|
+        schema.create_table("Logs") do |table|
+          table.time("timestamp")
+        end
+
+        schema.create_table("Times",
+                            :type => :patricia_trie,
+                            :key_type => :time) do |table|
+          table.index("Logs", "timestamp")
+        end
+      end
+      super
+    end
+
+    def test_no_record
+      assert_equal(0,
+                   estimate_size("in_values(timestamp, " +
+                                 "'2015-02-19 02:18:00', " +
+                                 "'2015-02-19 02:20:00')"))
+    end
+
+    def test_have_record
+      @logs.add(:timestamp => "2015-02-19 02:17:00")
+      @logs.add(:timestamp => "2015-02-19 02:17:00")
+      @logs.add(:timestamp => "2015-02-19 02:18:00")
+      @logs.add(:timestamp => "2015-02-19 02:18:00")
+      @logs.add(:timestamp => "2015-02-19 02:19:00")
+      @logs.add(:timestamp => "2015-02-19 02:19:00")
+      @logs.add(:timestamp => "2015-02-19 02:20:00")
+      @logs.add(:timestamp => "2015-02-19 02:20:00")
+      @logs.add(:timestamp => "2015-02-19 02:21:00")
+      @logs.add(:timestamp => "2015-02-19 02:21:00")
+      assert_equal(8,
+                   estimate_size("in_values(timestamp, " +
+                                 "'2015-02-19 02:18:00', " +
+                                 "'2015-02-19 02:20:00')"))
+    end
+  end
+
   class TestAnd < self
     def setup
       Groonga::Schema.define do |schema|
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.osdn.me/mailman/archives/groonga-commit/attachments/20190425/6b279074/attachment-0001.html>


More information about the Groonga-commit mailing list
Back to archive index