提交 674102df authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Do not use hash-based collections in aggregates

上级 6ae17fc2
...@@ -10,6 +10,7 @@ import java.util.Arrays; ...@@ -10,6 +10,7 @@ import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.TreeMap;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.command.dml.Select; import org.h2.command.dml.Select;
import org.h2.command.dml.SelectOrderBy; import org.h2.command.dml.SelectOrderBy;
...@@ -32,7 +33,6 @@ import org.h2.table.ColumnResolver; ...@@ -32,7 +33,6 @@ import org.h2.table.ColumnResolver;
import org.h2.table.Table; import org.h2.table.Table;
import org.h2.table.TableFilter; import org.h2.table.TableFilter;
import org.h2.util.StatementBuilder; import org.h2.util.StatementBuilder;
import org.h2.util.ValueHashMap;
import org.h2.value.CompareMode; import org.h2.value.CompareMode;
import org.h2.value.DataType; import org.h2.value.DataType;
import org.h2.value.TypeInfo; import org.h2.value.TypeInfo;
...@@ -512,13 +512,13 @@ public class Aggregate extends AbstractAggregate { ...@@ -512,13 +512,13 @@ public class Aggregate extends AbstractAggregate {
} }
private Value getHistogram(Session session, AggregateData data) { private Value getHistogram(Session session, AggregateData data) {
ValueHashMap<LongDataCounter> distinctValues = ((AggregateDataDistinctWithCounts) data).getValues(); TreeMap<Value, LongDataCounter> distinctValues = ((AggregateDataDistinctWithCounts) data).getValues();
if (distinctValues == null) { if (distinctValues == null) {
return ValueArray.getEmpty(); return ValueArray.getEmpty();
} }
ValueArray[] values = new ValueArray[distinctValues.size()]; ValueArray[] values = new ValueArray[distinctValues.size()];
int i = 0; int i = 0;
for (Entry<Value, LongDataCounter> entry : distinctValues.entries()) { for (Entry<Value, LongDataCounter> entry : distinctValues.entrySet()) {
LongDataCounter d = entry.getValue(); LongDataCounter d = entry.getValue();
values[i] = ValueArray.get(new Value[] { entry.getKey(), ValueLong.get(distinct ? 1L : d.count) }); values[i] = ValueArray.get(new Value[] { entry.getKey(), ValueLong.get(distinct ? 1L : d.count) });
i++; i++;
...@@ -539,14 +539,14 @@ public class Aggregate extends AbstractAggregate { ...@@ -539,14 +539,14 @@ public class Aggregate extends AbstractAggregate {
private Value getMode(Session session, AggregateData data) { private Value getMode(Session session, AggregateData data) {
Value v = ValueNull.INSTANCE; Value v = ValueNull.INSTANCE;
ValueHashMap<LongDataCounter> distinctValues = ((AggregateDataDistinctWithCounts) data).getValues(); TreeMap<Value, LongDataCounter> distinctValues = ((AggregateDataDistinctWithCounts) data).getValues();
if (distinctValues == null) { if (distinctValues == null) {
return v; return v;
} }
long count = 0L; long count = 0L;
if (orderByList != null) { if (orderByList != null) {
boolean desc = (orderByList.get(0).sortType & SortOrder.DESCENDING) != 0; boolean desc = (orderByList.get(0).sortType & SortOrder.DESCENDING) != 0;
for (Entry<Value, LongDataCounter> entry : distinctValues.entries()) { for (Entry<Value, LongDataCounter> entry : distinctValues.entrySet()) {
long c = entry.getValue().count; long c = entry.getValue().count;
if (c > count) { if (c > count) {
v = entry.getKey(); v = entry.getKey();
...@@ -565,7 +565,7 @@ public class Aggregate extends AbstractAggregate { ...@@ -565,7 +565,7 @@ public class Aggregate extends AbstractAggregate {
} }
} }
} else { } else {
for (Entry<Value, LongDataCounter> entry : distinctValues.entries()) { for (Entry<Value, LongDataCounter> entry : distinctValues.entrySet()) {
long c = entry.getValue().count; long c = entry.getValue().count;
if (c > count) { if (c > count) {
v = entry.getKey(); v = entry.getKey();
......
...@@ -8,8 +8,8 @@ package org.h2.expression.aggregate; ...@@ -8,8 +8,8 @@ package org.h2.expression.aggregate;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.TreeSet;
import org.h2.engine.Database; import org.h2.engine.Database;
import org.h2.value.Value; import org.h2.value.Value;
...@@ -47,7 +47,7 @@ class AggregateDataCollecting extends AggregateData implements Iterable<Value> { ...@@ -47,7 +47,7 @@ class AggregateDataCollecting extends AggregateData implements Iterable<Value> {
} }
Collection<Value> c = values; Collection<Value> c = values;
if (c == null) { if (c == null) {
values = c = distinct ? new HashSet<Value>() : new ArrayList<Value>(); values = c = distinct ? new TreeSet<>(database.getCompareMode()) : new ArrayList<Value>();
} }
c.add(v); c.add(v);
} }
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
*/ */
package org.h2.expression.aggregate; package org.h2.expression.aggregate;
import java.util.TreeMap;
import org.h2.engine.Database; import org.h2.engine.Database;
import org.h2.util.ValueHashMap;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueNull; import org.h2.value.ValueNull;
...@@ -20,7 +20,7 @@ class AggregateDataDistinctWithCounts extends AggregateData { ...@@ -20,7 +20,7 @@ class AggregateDataDistinctWithCounts extends AggregateData {
private final int maxDistinctCount; private final int maxDistinctCount;
private ValueHashMap<LongDataCounter> values; private TreeMap<Value, LongDataCounter> values;
/** /**
* Creates new instance of data for aggregate that needs distinct values * Creates new instance of data for aggregate that needs distinct values
...@@ -42,7 +42,7 @@ class AggregateDataDistinctWithCounts extends AggregateData { ...@@ -42,7 +42,7 @@ class AggregateDataDistinctWithCounts extends AggregateData {
return; return;
} }
if (values == null) { if (values == null) {
values = new ValueHashMap<>(); values = new TreeMap<>(database.getCompareMode());
} }
LongDataCounter a = values.get(v); LongDataCounter a = values.get(v);
if (a == null) { if (a == null) {
...@@ -65,7 +65,7 @@ class AggregateDataDistinctWithCounts extends AggregateData { ...@@ -65,7 +65,7 @@ class AggregateDataDistinctWithCounts extends AggregateData {
* *
* @return map with values and their counts * @return map with values and their counts
*/ */
ValueHashMap<LongDataCounter> getValues() { TreeMap<Value, LongDataCounter> getValues() {
return values; return values;
} }
......
...@@ -104,3 +104,18 @@ SELECT X, COUNT(*) OVER (ORDER BY X) C FROM VALUES (1), (1), (2), (2), (3) V(X); ...@@ -104,3 +104,18 @@ SELECT X, COUNT(*) OVER (ORDER BY X) C FROM VALUES (1), (1), (2), (2), (3) V(X);
> 2 4 > 2 4
> 3 5 > 3 5
> rows: 5 > rows: 5
CREATE TABLE TEST (N NUMERIC) AS VALUES (0), (0.0), (NULL);
> ok
SELECT COUNT(*) FROM TEST;
>> 3
SELECT COUNT(N) FROM TEST;
>> 2
SELECT COUNT(DISTINCT N) FROM TEST;
>> 1
DROP TABLE TEST;
> ok
...@@ -57,3 +57,12 @@ SELECT MODE() WITHIN GROUP(ORDER BY V DESC) FROM TEST; ...@@ -57,3 +57,12 @@ SELECT MODE() WITHIN GROUP(ORDER BY V DESC) FROM TEST;
DROP TABLE TEST; DROP TABLE TEST;
> ok > ok
CREATE TABLE TEST (N NUMERIC) AS VALUES (0), (0.0), (NULL);
> ok
SELECT MODE(N) FROM TEST;
>> 0
DROP TABLE TEST;
> ok
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论