├── sql ├── count_distinct--3.0.0--3.0.1.sql ├── count_distinct--3.0.1--3.0.2.sql ├── count_distinct--1.3.1--1.3.2.sql ├── count_distinct--1.3.2--1.3.3.sql ├── count_distinct--2.0.0--3.0.0.sql ├── count_distinct--3.0.2.sql └── count_distinct--1.3.3--2.0.0.sql ├── .gitignore ├── count_distinct.control ├── test ├── sql │ ├── window.sql │ ├── setup │ │ └── setup.sql │ ├── array_agg.sql │ └── base.sql └── expected │ ├── window.out │ ├── base.out │ └── array_agg.out ├── .github └── workflows │ ├── ci.yml │ └── mirror.yml ├── Makefile ├── META.json ├── LICENSE ├── benchmark ├── create-tables.sql ├── bench-native.sql └── bench-count-distinct.sql ├── README.md └── count_distinct.c /sql/count_distinct--3.0.0--3.0.1.sql: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sql/count_distinct--3.0.1--3.0.2.sql: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .deps 2 | results 3 | *.so 4 | *.o 5 | -------------------------------------------------------------------------------- /sql/count_distinct--1.3.1--1.3.2.sql: -------------------------------------------------------------------------------- 1 | -- empty 2 | -------------------------------------------------------------------------------- /sql/count_distinct--1.3.2--1.3.3.sql: -------------------------------------------------------------------------------- 1 | -- empty 2 | -------------------------------------------------------------------------------- /count_distinct.control: -------------------------------------------------------------------------------- 1 | # count_distinct aggregate 2 | comment = 'An alternative to COUNT(DISTINCT ...) aggregate, usable with HashAggregate' 3 | default_version = '3.0.2' 4 | relocatable = true 5 | -------------------------------------------------------------------------------- /test/sql/window.sql: -------------------------------------------------------------------------------- 1 | \set ECHO none 2 | \i test/sql/setup/setup.sql 3 | 4 | select count_distinct(x) over (order by x rows between unbounded preceding and current row) 5 | from test_data_1_20; 6 | 7 | select count_distinct(x) over (order by x rows between 10 preceding and 10 following) 8 | from test_data_1_25; 9 | 10 | ROLLBACK; 11 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: make installcheck 2 | on: [push, pull_request] 3 | jobs: 4 | test: 5 | strategy: 6 | matrix: 7 | pg: [17, 16, 15, 14, 13, 12, 11, 10, 9.6] 8 | name: PostgreSQL ${{ matrix.pg }} 9 | runs-on: ubuntu-latest 10 | container: pgxn/pgxn-tools 11 | steps: 12 | 13 | - name: Start PostgreSQL ${{ matrix.pg }} 14 | run: pg-start ${{ matrix.pg }} 15 | 16 | - name: Check out the repo 17 | uses: actions/checkout@v2 18 | 19 | - name: Test on PostgreSQL ${{ matrix.pg }} 20 | run: pg-build-test 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | MODULE_big = count_distinct 2 | OBJS = count_distinct.o 3 | 4 | EXTENSION = count_distinct 5 | DATA = sql/count_distinct--3.0.2.sql sql/count_distinct--1.3.1--1.3.2.sql \ 6 | sql/count_distinct--1.3.2--1.3.3.sql sql/count_distinct--1.3.3--2.0.0.sql \ 7 | sql/count_distinct--2.0.0--3.0.0.sql sql/count_distinct--3.0.0--3.0.1.sql \ 8 | sql/count_distinct--3.0.1--3.0.2.sql 9 | MODULES = count_distinct 10 | 11 | CFLAGS=`pg_config --includedir-server` 12 | 13 | TESTS = $(wildcard test/sql/*.sql) 14 | REGRESS = $(patsubst test/sql/%.sql,%,$(TESTS)) 15 | REGRESS_OPTS = --inputdir=test 16 | 17 | PG_CONFIG = pg_config 18 | PGXS := $(shell $(PG_CONFIG) --pgxs) 19 | include $(PGXS) 20 | -------------------------------------------------------------------------------- /.github/workflows/mirror.yml: -------------------------------------------------------------------------------- 1 | # Sync repo to the codeberg mirror 2 | name: Repo sync (GitHub -> Codeberg) 3 | on: 4 | push: 5 | branches: 6 | - '**' 7 | workflow_dispatch: # Manual dispatch 8 | schedule: 9 | - cron: "0 */6 * * *" 10 | 11 | jobs: 12 | sync-repo-to-codeberg: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: "Checkout" 16 | uses: actions/checkout@v2 17 | with: 18 | fetch-depth: 0 19 | - name: "Gather facts" 20 | run: | 21 | echo "Repo variables:" 22 | echo " CODEBERG_URL: ${{ vars.CODEBERG_URL }}" 23 | echo " CODEBERG_USERNAME: ${{ vars.CODEBERG_USERNAME }}" 24 | - name: "Sync repo" 25 | uses: yesolutions/mirror-action@master 26 | with: 27 | REMOTE: "${{ vars.CODEBERG_URL }}" 28 | GIT_USERNAME: ${{ vars.CODEBERG_USERNAME }} 29 | GIT_SSH_PRIVATE_KEY: ${{ secrets.CODEBERG_SSH_KEY }} 30 | GIT_SSH_NO_VERIFY_HOST: "true" 31 | -------------------------------------------------------------------------------- /test/expected/window.out: -------------------------------------------------------------------------------- 1 | \set ECHO none 2 | select count_distinct(x) over (order by x rows between unbounded preceding and current row) 3 | from test_data_1_20; 4 | count_distinct 5 | ---------------- 6 | 1 7 | 2 8 | 3 9 | 4 10 | 5 11 | 6 12 | 7 13 | 8 14 | 9 15 | 10 16 | 11 17 | 12 18 | 13 19 | 14 20 | 15 21 | 16 22 | 17 23 | 18 24 | 19 25 | 20 26 | (20 rows) 27 | 28 | select count_distinct(x) over (order by x rows between 10 preceding and 10 following) 29 | from test_data_1_25; 30 | count_distinct 31 | ---------------- 32 | 11 33 | 12 34 | 13 35 | 14 36 | 15 37 | 16 38 | 17 39 | 18 40 | 19 41 | 20 42 | 21 43 | 21 44 | 21 45 | 21 46 | 21 47 | 20 48 | 19 49 | 18 50 | 17 51 | 16 52 | 15 53 | 14 54 | 13 55 | 12 56 | 11 57 | (25 rows) 58 | 59 | ROLLBACK; 60 | -------------------------------------------------------------------------------- /META.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "count_distinct", 3 | "abstract": "Aggregate for computing number of distinct values using a sorted set.", 4 | "description": "The regular COUNT(DISTINCT ...) always performs a regular sort internally, which results in bad performance if there's a lot of duplicate values. This extension implements custom count_distinct aggregate function that uses an optimized sorted set to achieve the same purpose. The extension currently supports only data types passed by value", 5 | "version": "3.0.2", 6 | "maintainer": [ 7 | "Tomas Vondra ", 8 | "Alexey Bashtanov " 9 | ], 10 | "license": "bsd", 11 | "prereqs": { 12 | "runtime": { 13 | "requires": { 14 | "PostgreSQL": "9.6.0" 15 | } 16 | } 17 | }, 18 | "provides": { 19 | "count_distinct": { 20 | "file": "sql/count_distinct--3.0.2.sql", 21 | "docfile" : "README.md", 22 | "version": "3.0.2" 23 | } 24 | }, 25 | "resources": { 26 | "repository": { 27 | "url": "https://github.com/tvondra/count_distinct.git", 28 | "web": "http://github.com/tvondra/count_distinct", 29 | "type": "git" 30 | } 31 | }, 32 | "tags" : ["count", "distinct", "aggregate"], 33 | "meta-spec": { 34 | "version": "1.0.0", 35 | "url": "http://pgxn.org/meta/spec.txt" 36 | }, 37 | "release_status" : "testing" 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2011, Tomas Vondra (tv@fuzzy.cz). All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are 4 | permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of 7 | conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 10 | of conditions and the following disclaimer in the documentation and/or other materials 11 | provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY TOMAS VONDRA ''AS IS'' AND ANY EXPRESS OR IMPLIED 14 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 15 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOMAS VONDRA OR 16 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 17 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 18 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 19 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 20 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 21 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | The views and conclusions contained in the software and documentation are those of the 24 | authors and should not be interpreted as representing official policies, either expressed 25 | or implied, of Tomas Vondra. -------------------------------------------------------------------------------- /test/sql/setup/setup.sql: -------------------------------------------------------------------------------- 1 | \set ECHO none 2 | 3 | BEGIN; 4 | 5 | -- install the module 6 | \i sql/count_distinct--3.0.2.sql 7 | 8 | -- create and analyze tables (parallel plans work only on real tables, not on SRFs) 9 | create table test_data_1_20 as select generate_series(1,20) x; 10 | create table test_data_1_25 as select generate_series(1,25) x; 11 | create table test_data_0_50 as select generate_series(0,50) x; 12 | create table test_data_1_50 as select generate_series(1,50) x; 13 | create table test_data_1_1000 as select generate_series(1,1000) x; 14 | create table test_data_0_1000 as select generate_series(0,1000) x; 15 | analyze test_data_1_20; 16 | analyze test_data_1_25; 17 | analyze test_data_0_50; 18 | analyze test_data_1_50; 19 | analyze test_data_1_1000; 20 | analyze test_data_0_1000; 21 | 22 | -- force parallel execution and check if it works 23 | do $$ 24 | declare 25 | t text; 26 | cfg text = case when current_setting('server_version_num')::int >= 100000 then 'min_parallel_table_scan_size' else 'min_parallel_relation_size' end; 27 | begin 28 | perform set_config(cfg, '0', true), 29 | set_config('parallel_setup_cost', '0', true), 30 | set_config('parallel_tuple_cost', '0', true), 31 | set_config('max_parallel_workers_per_gather', '22', true); 32 | 33 | for t in explain select count(*) from test_data_1_20 loop 34 | if t like '%Gather%' then 35 | -- Here we can see parallel execution is on 36 | return; 37 | end if; 38 | end loop; 39 | raise 'Looks like parallel aggregation is off'; 40 | end; 41 | $$; 42 | 43 | \set ECHO all 44 | -------------------------------------------------------------------------------- /test/sql/array_agg.sql: -------------------------------------------------------------------------------- 1 | \set ECHO none 2 | \i test/sql/setup/setup.sql 3 | 4 | -- int 5 | SELECT array_agg(a order by a) FROM (SELECT unnest(array_agg_distinct(x::int)) a FROM test_data_1_50)_; 6 | SELECT array_agg(a order by a) FROM (SELECT unnest(array_agg_distinct(mod(x,10)::int)) a FROM test_data_1_50)_; 7 | 8 | -- bigint 9 | SELECT array_agg(a order by a) FROM (SELECT unnest(array_agg_distinct(x::bigint)) a FROM test_data_1_50)_; 10 | SELECT array_agg(a order by a) FROM (SELECT unnest(array_agg_distinct(mod(x,10)::bigint)) a FROM test_data_1_50)_; 11 | 12 | -- timestamp 13 | SELECT unnest(array_agg(a order by a)) FROM (SELECT unnest(array_agg_distinct('epoch'::timestamp + (x || ' days')::interval)) a FROM test_data_1_50)_; 14 | SELECT unnest(array_agg(a order by a)) FROM (SELECT unnest(array_agg_distinct('epoch'::timestamptz + (x || ' days')::interval)) a FROM test_data_1_50)_; 15 | 16 | -- bool 17 | SELECT array_agg(a order by a) FROM (SELECT unnest(array_agg_distinct(mod(x,2)::bool)) a FROM test_data_1_50)_; 18 | 19 | -- bool w/nulls 20 | SELECT array_agg(a order by a) FROM (SELECT unnest(array_agg_distinct(nullif(mod(x,2), 0)::bool)) a FROM test_data_0_50)_; 21 | 22 | -- int2 23 | SELECT array_agg(a order by a) FROM (SELECT unnest(array_agg_distinct(x::int2)) a FROM test_data_1_50)_; 24 | 25 | -- array_agg_elements: nulls only 26 | SELECT array_agg_distinct_elements(array[null::int2]) a FROM generate_series(1, 10) x; 27 | 28 | -- array_agg_elements: nulls and non-nulls 29 | SELECT array_agg(a order by a) FROM (SELECT unnest(array_agg_distinct_elements(array[x::int2, null, -x::int2])) a FROM test_data_0_50)_; 30 | 31 | ROLLBACK; 32 | -------------------------------------------------------------------------------- /sql/count_distinct--2.0.0--3.0.0.sql: -------------------------------------------------------------------------------- 1 | /* drop aggregate functions */ 2 | DROP AGGREGATE count_distinct(anyelement); 3 | DROP AGGREGATE array_agg_distinct(anynonarray); 4 | DROP AGGREGATE count_distinct_elements(anyarray); 5 | DROP AGGREGATE array_agg_distinct_elements(anyarray); 6 | 7 | /* create parallel aggregation support functions */ 8 | /* serialize data */ 9 | CREATE OR REPLACE FUNCTION count_distinct_serial(p_pointer internal) 10 | RETURNS bytea 11 | AS 'count_distinct', 'count_distinct_serial' 12 | LANGUAGE C IMMUTABLE STRICT; 13 | 14 | /* deserialize data */ 15 | CREATE OR REPLACE FUNCTION count_distinct_deserial(p_value bytea, p_dummy internal) 16 | RETURNS internal 17 | AS 'count_distinct', 'count_distinct_deserial' 18 | LANGUAGE C IMMUTABLE STRICT; 19 | 20 | /* combine data */ 21 | CREATE OR REPLACE FUNCTION count_distinct_combine(p_state_1 internal, p_state_2 internal) 22 | RETURNS internal 23 | AS 'count_distinct', 'count_distinct_combine' 24 | LANGUAGE C IMMUTABLE; 25 | 26 | /* rereate the aggregate functions */ 27 | CREATE AGGREGATE count_distinct(anyelement) ( 28 | SFUNC = count_distinct_append, 29 | STYPE = internal, 30 | FINALFUNC = count_distinct, 31 | COMBINEFUNC = count_distinct_combine, 32 | SERIALFUNC = count_distinct_serial, 33 | DESERIALFUNC = count_distinct_deserial, 34 | PARALLEL = SAFE 35 | ); 36 | 37 | CREATE AGGREGATE array_agg_distinct(anynonarray) ( 38 | SFUNC = count_distinct_append, 39 | STYPE = internal, 40 | FINALFUNC = array_agg_distinct, 41 | FINALFUNC_EXTRA, 42 | COMBINEFUNC = count_distinct_combine, 43 | SERIALFUNC = count_distinct_serial, 44 | DESERIALFUNC = count_distinct_deserial, 45 | PARALLEL = SAFE 46 | ); 47 | 48 | CREATE AGGREGATE count_distinct_elements(anyarray) ( 49 | SFUNC = count_distinct_elements_append, 50 | STYPE = internal, 51 | FINALFUNC = count_distinct, 52 | COMBINEFUNC = count_distinct_combine, 53 | SERIALFUNC = count_distinct_serial, 54 | DESERIALFUNC = count_distinct_deserial, 55 | PARALLEL = SAFE 56 | ); 57 | 58 | CREATE AGGREGATE array_agg_distinct_elements(anyarray) ( 59 | SFUNC = count_distinct_elements_append, 60 | STYPE = internal, 61 | FINALFUNC = array_agg_distinct, 62 | FINALFUNC_EXTRA, 63 | COMBINEFUNC = count_distinct_combine, 64 | SERIALFUNC = count_distinct_serial, 65 | DESERIALFUNC = count_distinct_deserial, 66 | PARALLEL = SAFE 67 | ); 68 | -------------------------------------------------------------------------------- /test/sql/base.sql: -------------------------------------------------------------------------------- 1 | \set ECHO none 2 | \i test/sql/setup/setup.sql 3 | 4 | -- int 5 | SELECT count_distinct(x::int) FROM test_data_1_1000; 6 | SELECT count_distinct(mod(x,10)::int) FROM test_data_1_1000; 7 | 8 | -- bigint 9 | SELECT count_distinct(x::bigint) FROM test_data_1_1000; 10 | SELECT count_distinct(mod(x,10)::bigint) FROM test_data_1_1000; 11 | 12 | -- timestamp 13 | select count_distinct(now()::timestamp + (x || ' days')::interval) from test_data_1_1000; 14 | select count_distinct(now() + (x || ' days')::interval) from test_data_1_1000; 15 | 16 | -- bool 17 | select count_distinct(x::bool) from test_data_0_1000; 18 | 19 | -- int2 20 | select count_distinct(x::int2) from test_data_1_1000; 21 | 22 | -- array of int 23 | SELECT count_distinct_elements(z) FROM ( 24 | SELECT ARRAY[x::int, (x+1)::int] AS z FROM generate_series(1,1000) s(x) 25 | ) foo; 26 | 27 | SELECT count_distinct_elements(z) FROM ( 28 | SELECT ARRAY[mod(x,10)::int, mod(x+1,10)::int] AS z FROM generate_series(1,1000) s(x) 29 | ) foo; 30 | 31 | -- array of bigint 32 | SELECT count_distinct_elements(z) FROM ( 33 | SELECT ARRAY[x::bigint, (x+1)::bigint] AS z FROM generate_series(1,1000) s(x) 34 | ) foo; 35 | 36 | SELECT count_distinct_elements(z) FROM ( 37 | SELECT ARRAY[mod(x,10)::bigint, mod(x+1,10)::bigint] AS z FROM generate_series(1,1000) s(x) 38 | ) foo; 39 | 40 | -- array of timestamp 41 | SELECT count_distinct_elements(z) FROM ( 42 | SELECT ARRAY[now()::timestamp + (x || ' days')::interval, 43 | now()::timestamp + ((x + 1) || ' days')::interval] AS z 44 | FROM generate_series(1,1000) s(x) 45 | ) foo; 46 | 47 | SELECT count_distinct_elements(z) FROM ( 48 | SELECT ARRAY[now() + (x || ' days')::interval, 49 | now() + ((x + 1) || ' days')::interval] AS z 50 | FROM generate_series(1,1000) s(x) 51 | ) foo; 52 | 53 | -- array of bool 54 | SELECT count_distinct_elements(z) FROM ( 55 | SELECT ARRAY[x::bool, (x+1)::bool] AS z FROM generate_series(1,1000) s(x) 56 | ) foo; 57 | 58 | SELECT count_distinct_elements(z) FROM ( 59 | SELECT ARRAY[mod(x,10)::bool, mod(x+1,10)::bool] AS z FROM generate_series(1,1000) s(x) 60 | ) foo; 61 | 62 | -- array of int2 with nulls 63 | SELECT count_distinct_elements(z) FROM ( 64 | SELECT ARRAY[NULL, NULL, NULL, NULL]::int2[] AS z FROM generate_series(1,1000) s(x) 65 | ) foo; 66 | 67 | SELECT count_distinct_elements(z) FROM ( 68 | SELECT ARRAY[[NULL, x::int2, NULL], [NULL, (x+1)::int2, NULL]] AS z FROM generate_series(1,1000) s(x) 69 | ) foo; 70 | 71 | SELECT count_distinct_elements(z) FROM ( 72 | SELECT ARRAY[mod(x,10)::int2, mod(x+1,10)::int2] AS z FROM generate_series(1,1000) s(x) 73 | ) foo; 74 | 75 | -- This way a problem with combine function called with both arguments nulls was reproduced. 76 | SELECT sum(cnt) FROM ( 77 | SELECT x, 78 | count_distinct(NULL::int) cnt 79 | FROM test_data_0_1000 80 | GROUP BY x 81 | ) _; 82 | 83 | ROLLBACK; 84 | -------------------------------------------------------------------------------- /sql/count_distinct--3.0.2.sql: -------------------------------------------------------------------------------- 1 | /* count_distinct for int and bigint */ 2 | 3 | CREATE OR REPLACE FUNCTION count_distinct_append(internal, anyelement) 4 | RETURNS internal 5 | AS 'count_distinct', 'count_distinct_append' 6 | LANGUAGE C IMMUTABLE; 7 | 8 | CREATE OR REPLACE FUNCTION count_distinct_elements_append(internal, anyarray) 9 | RETURNS internal 10 | AS 'count_distinct', 'count_distinct_elements_append' 11 | LANGUAGE C IMMUTABLE; 12 | 13 | CREATE OR REPLACE FUNCTION count_distinct(internal) 14 | RETURNS bigint 15 | AS 'count_distinct', 'count_distinct' 16 | LANGUAGE C IMMUTABLE; 17 | 18 | CREATE OR REPLACE FUNCTION array_agg_distinct(internal, anynonarray) 19 | RETURNS anyarray 20 | AS 'count_distinct', 'array_agg_distinct_type_by_element' 21 | LANGUAGE C IMMUTABLE; 22 | 23 | CREATE OR REPLACE FUNCTION array_agg_distinct(internal, anyarray) 24 | RETURNS anyarray 25 | AS 'count_distinct', 'array_agg_distinct_type_by_array' 26 | LANGUAGE C IMMUTABLE; 27 | 28 | /* Server supports parallel aggregation (9.6+) */ 29 | 30 | /* serialize data */ 31 | CREATE OR REPLACE FUNCTION count_distinct_serial(p_pointer internal) 32 | RETURNS bytea 33 | AS 'count_distinct', 'count_distinct_serial' 34 | LANGUAGE C IMMUTABLE STRICT; 35 | 36 | /* deserialize data */ 37 | CREATE OR REPLACE FUNCTION count_distinct_deserial(p_value bytea, p_dummy internal) 38 | RETURNS internal 39 | AS 'count_distinct', 'count_distinct_deserial' 40 | LANGUAGE C IMMUTABLE STRICT; 41 | 42 | /* combine data */ 43 | CREATE OR REPLACE FUNCTION count_distinct_combine(p_state_1 internal, p_state_2 internal) 44 | RETURNS internal 45 | AS 'count_distinct', 'count_distinct_combine' 46 | LANGUAGE C IMMUTABLE; 47 | 48 | /* Create the aggregate functions */ 49 | CREATE AGGREGATE count_distinct(anyelement) ( 50 | SFUNC = count_distinct_append, 51 | STYPE = internal, 52 | FINALFUNC = count_distinct, 53 | COMBINEFUNC = count_distinct_combine, 54 | SERIALFUNC = count_distinct_serial, 55 | DESERIALFUNC = count_distinct_deserial, 56 | PARALLEL = SAFE 57 | ); 58 | 59 | CREATE AGGREGATE array_agg_distinct(anynonarray) ( 60 | SFUNC = count_distinct_append, 61 | STYPE = internal, 62 | FINALFUNC = array_agg_distinct, 63 | FINALFUNC_EXTRA, 64 | COMBINEFUNC = count_distinct_combine, 65 | SERIALFUNC = count_distinct_serial, 66 | DESERIALFUNC = count_distinct_deserial, 67 | PARALLEL = SAFE 68 | ); 69 | 70 | CREATE AGGREGATE count_distinct_elements(anyarray) ( 71 | SFUNC = count_distinct_elements_append, 72 | STYPE = internal, 73 | FINALFUNC = count_distinct, 74 | COMBINEFUNC = count_distinct_combine, 75 | SERIALFUNC = count_distinct_serial, 76 | DESERIALFUNC = count_distinct_deserial, 77 | PARALLEL = SAFE 78 | ); 79 | 80 | CREATE AGGREGATE array_agg_distinct_elements(anyarray) ( 81 | SFUNC = count_distinct_elements_append, 82 | STYPE = internal, 83 | FINALFUNC = array_agg_distinct, 84 | FINALFUNC_EXTRA, 85 | COMBINEFUNC = count_distinct_combine, 86 | SERIALFUNC = count_distinct_serial, 87 | DESERIALFUNC = count_distinct_deserial, 88 | PARALLEL = SAFE 89 | ); 90 | -------------------------------------------------------------------------------- /test/expected/base.out: -------------------------------------------------------------------------------- 1 | \set ECHO none 2 | -- int 3 | SELECT count_distinct(x::int) FROM test_data_1_1000; 4 | count_distinct 5 | ---------------- 6 | 1000 7 | (1 row) 8 | 9 | SELECT count_distinct(mod(x,10)::int) FROM test_data_1_1000; 10 | count_distinct 11 | ---------------- 12 | 10 13 | (1 row) 14 | 15 | -- bigint 16 | SELECT count_distinct(x::bigint) FROM test_data_1_1000; 17 | count_distinct 18 | ---------------- 19 | 1000 20 | (1 row) 21 | 22 | SELECT count_distinct(mod(x,10)::bigint) FROM test_data_1_1000; 23 | count_distinct 24 | ---------------- 25 | 10 26 | (1 row) 27 | 28 | -- timestamp 29 | select count_distinct(now()::timestamp + (x || ' days')::interval) from test_data_1_1000; 30 | count_distinct 31 | ---------------- 32 | 1000 33 | (1 row) 34 | 35 | select count_distinct(now() + (x || ' days')::interval) from test_data_1_1000; 36 | count_distinct 37 | ---------------- 38 | 1000 39 | (1 row) 40 | 41 | -- bool 42 | select count_distinct(x::bool) from test_data_0_1000; 43 | count_distinct 44 | ---------------- 45 | 2 46 | (1 row) 47 | 48 | -- int2 49 | select count_distinct(x::int2) from test_data_1_1000; 50 | count_distinct 51 | ---------------- 52 | 1000 53 | (1 row) 54 | 55 | -- array of int 56 | SELECT count_distinct_elements(z) FROM ( 57 | SELECT ARRAY[x::int, (x+1)::int] AS z FROM generate_series(1,1000) s(x) 58 | ) foo; 59 | count_distinct_elements 60 | ------------------------- 61 | 1001 62 | (1 row) 63 | 64 | SELECT count_distinct_elements(z) FROM ( 65 | SELECT ARRAY[mod(x,10)::int, mod(x+1,10)::int] AS z FROM generate_series(1,1000) s(x) 66 | ) foo; 67 | count_distinct_elements 68 | ------------------------- 69 | 10 70 | (1 row) 71 | 72 | -- array of bigint 73 | SELECT count_distinct_elements(z) FROM ( 74 | SELECT ARRAY[x::bigint, (x+1)::bigint] AS z FROM generate_series(1,1000) s(x) 75 | ) foo; 76 | count_distinct_elements 77 | ------------------------- 78 | 1001 79 | (1 row) 80 | 81 | SELECT count_distinct_elements(z) FROM ( 82 | SELECT ARRAY[mod(x,10)::bigint, mod(x+1,10)::bigint] AS z FROM generate_series(1,1000) s(x) 83 | ) foo; 84 | count_distinct_elements 85 | ------------------------- 86 | 10 87 | (1 row) 88 | 89 | -- array of timestamp 90 | SELECT count_distinct_elements(z) FROM ( 91 | SELECT ARRAY[now()::timestamp + (x || ' days')::interval, 92 | now()::timestamp + ((x + 1) || ' days')::interval] AS z 93 | FROM generate_series(1,1000) s(x) 94 | ) foo; 95 | count_distinct_elements 96 | ------------------------- 97 | 1001 98 | (1 row) 99 | 100 | SELECT count_distinct_elements(z) FROM ( 101 | SELECT ARRAY[now() + (x || ' days')::interval, 102 | now() + ((x + 1) || ' days')::interval] AS z 103 | FROM generate_series(1,1000) s(x) 104 | ) foo; 105 | count_distinct_elements 106 | ------------------------- 107 | 1001 108 | (1 row) 109 | 110 | -- array of bool 111 | SELECT count_distinct_elements(z) FROM ( 112 | SELECT ARRAY[x::bool, (x+1)::bool] AS z FROM generate_series(1,1000) s(x) 113 | ) foo; 114 | count_distinct_elements 115 | ------------------------- 116 | 1 117 | (1 row) 118 | 119 | SELECT count_distinct_elements(z) FROM ( 120 | SELECT ARRAY[mod(x,10)::bool, mod(x+1,10)::bool] AS z FROM generate_series(1,1000) s(x) 121 | ) foo; 122 | count_distinct_elements 123 | ------------------------- 124 | 2 125 | (1 row) 126 | 127 | -- array of int2 with nulls 128 | SELECT count_distinct_elements(z) FROM ( 129 | SELECT ARRAY[NULL, NULL, NULL, NULL]::int2[] AS z FROM generate_series(1,1000) s(x) 130 | ) foo; 131 | count_distinct_elements 132 | ------------------------- 133 | 134 | (1 row) 135 | 136 | SELECT count_distinct_elements(z) FROM ( 137 | SELECT ARRAY[[NULL, x::int2, NULL], [NULL, (x+1)::int2, NULL]] AS z FROM generate_series(1,1000) s(x) 138 | ) foo; 139 | count_distinct_elements 140 | ------------------------- 141 | 1001 142 | (1 row) 143 | 144 | SELECT count_distinct_elements(z) FROM ( 145 | SELECT ARRAY[mod(x,10)::int2, mod(x+1,10)::int2] AS z FROM generate_series(1,1000) s(x) 146 | ) foo; 147 | count_distinct_elements 148 | ------------------------- 149 | 10 150 | (1 row) 151 | 152 | -- This way a problem with combine function called with both arguments nulls was reproduced. 153 | SELECT sum(cnt) FROM ( 154 | SELECT x, 155 | count_distinct(NULL::int) cnt 156 | FROM test_data_0_1000 157 | GROUP BY x 158 | ) _; 159 | sum 160 | ----- 161 | 162 | (1 row) 163 | 164 | ROLLBACK; 165 | -------------------------------------------------------------------------------- /sql/count_distinct--1.3.3--2.0.0.sql: -------------------------------------------------------------------------------- 1 | CREATE OR REPLACE FUNCTION count_distinct_elements_append(internal, anyarray) 2 | RETURNS internal 3 | AS 'count_distinct', 'count_distinct_elements_append' 4 | LANGUAGE C IMMUTABLE; 5 | 6 | CREATE OR REPLACE FUNCTION array_agg_distinct(internal, anynonarray) 7 | RETURNS anyarray 8 | AS 'count_distinct', 'array_agg_distinct_type_by_element' 9 | LANGUAGE C IMMUTABLE; 10 | 11 | CREATE OR REPLACE FUNCTION array_agg_distinct(internal, anyarray) 12 | RETURNS anyarray 13 | AS 'count_distinct', 'array_agg_distinct_type_by_array' 14 | LANGUAGE C IMMUTABLE; 15 | 16 | DO $$ 17 | BEGIN 18 | IF ( 19 | SELECT TRUE 20 | FROM pg_attribute 21 | WHERE attrelid = 'pg_catalog.pg_aggregate'::regclass 22 | AND attname = 'aggcombinefn' 23 | ) 24 | THEN 25 | DROP AGGREGATE count_distinct(anyelement); 26 | /* Server supports parallel aggregation (9.6+) */ 27 | 28 | /* serialize data */ 29 | CREATE OR REPLACE FUNCTION count_distinct_serial(p_pointer internal) 30 | RETURNS bytea 31 | AS 'count_distinct', 'count_distinct_serial' 32 | LANGUAGE C IMMUTABLE STRICT; 33 | 34 | /* deserialize data */ 35 | CREATE OR REPLACE FUNCTION count_distinct_deserial(p_value bytea, p_dummy internal) 36 | RETURNS internal 37 | AS 'count_distinct', 'count_distinct_deserial' 38 | LANGUAGE C IMMUTABLE STRICT; 39 | 40 | /* combine data */ 41 | CREATE OR REPLACE FUNCTION count_distinct_combine(p_state_1 internal, p_state_2 internal) 42 | RETURNS internal 43 | AS 'count_distinct', 'count_distinct_combine' 44 | LANGUAGE C IMMUTABLE; 45 | 46 | /* Create the aggregate functions */ 47 | CREATE AGGREGATE count_distinct(anyelement) ( 48 | SFUNC = count_distinct_append, 49 | STYPE = internal, 50 | FINALFUNC = count_distinct, 51 | COMBINEFUNC = count_distinct_combine, 52 | SERIALFUNC = count_distinct_serial, 53 | DESERIALFUNC = count_distinct_deserial, 54 | PARALLEL = SAFE 55 | ); 56 | 57 | CREATE AGGREGATE array_agg_distinct(anynonarray) ( 58 | SFUNC = count_distinct_append, 59 | STYPE = internal, 60 | FINALFUNC = array_agg_distinct, 61 | FINALFUNC_EXTRA, 62 | COMBINEFUNC = count_distinct_combine, 63 | SERIALFUNC = count_distinct_serial, 64 | DESERIALFUNC = count_distinct_deserial, 65 | PARALLEL = SAFE 66 | ); 67 | 68 | CREATE AGGREGATE count_distinct_elements(anyarray) ( 69 | SFUNC = count_distinct_elements_append, 70 | STYPE = internal, 71 | FINALFUNC = count_distinct, 72 | COMBINEFUNC = count_distinct_combine, 73 | SERIALFUNC = count_distinct_serial, 74 | DESERIALFUNC = count_distinct_deserial, 75 | PARALLEL = SAFE 76 | ); 77 | 78 | CREATE AGGREGATE array_agg_distinct_elements(anyarray) ( 79 | SFUNC = count_distinct_elements_append, 80 | STYPE = internal, 81 | FINALFUNC = array_agg_distinct, 82 | FINALFUNC_EXTRA, 83 | COMBINEFUNC = count_distinct_combine, 84 | SERIALFUNC = count_distinct_serial, 85 | DESERIALFUNC = count_distinct_deserial, 86 | PARALLEL = SAFE 87 | ); 88 | ELSE 89 | /* Server does not support parallel aggregation (pre-9.6) */ 90 | 91 | /* Create the aggregate function */ 92 | CREATE AGGREGATE array_agg_distinct(anynonarray) ( 93 | SFUNC = count_distinct_append, 94 | STYPE = internal, 95 | FINALFUNC = array_agg_distinct, 96 | FINALFUNC_EXTRA 97 | ); 98 | 99 | CREATE AGGREGATE count_distinct_elements(anyarray) ( 100 | SFUNC = count_distinct_elements_append, 101 | STYPE = internal, 102 | FINALFUNC = count_distinct 103 | ); 104 | 105 | CREATE AGGREGATE array_agg_distinct_elements(anyarray) ( 106 | SFUNC = count_distinct_elements_append, 107 | STYPE = internal, 108 | FINALFUNC = array_agg_distinct, 109 | FINALFUNC_EXTRA 110 | ); 111 | END IF; 112 | END; 113 | $$; 114 | -------------------------------------------------------------------------------- /benchmark/create-tables.sql: -------------------------------------------------------------------------------- 1 | -- SMALL DATASET (100k rows) 2 | 3 | -- correlated columns, same cardinality (identity) 4 | CREATE TABLE small_1 ( 5 | col_a INT, 6 | col_b INT 7 | ); 8 | 9 | INSERT INTO small_1 SELECT i, i FROM generate_series(1,100000) s(i); 10 | 11 | -- different cardinality (second column 10 values) 12 | CREATE TABLE small_10 ( 13 | col_a INT, 14 | col_b INT 15 | ); 16 | 17 | INSERT INTO small_10 SELECT i, mod(i,10) FROM generate_series(1,100000) s(i); 18 | 19 | -- different cardinality (second column 100 values) 20 | CREATE TABLE small_100 ( 21 | col_a INT, 22 | col_b INT 23 | ); 24 | 25 | INSERT INTO small_100 SELECT i, mod(i,100) FROM generate_series(1,100000) s(i); 26 | 27 | -- different cardinality (second column 10000 values) 28 | CREATE TABLE small_10000 ( 29 | col_a INT, 30 | col_b INT 31 | ); 32 | 33 | INSERT INTO small_10000 SELECT i, mod(i,10000) FROM generate_series(1,100000) s(i); 34 | 35 | -- columns with random values and different cardinalities (100k values, 1000 values and 10 values) 36 | CREATE TABLE small_random ( 37 | col_a INT, 38 | col_b INT, 39 | col_c INT 40 | ); 41 | 42 | INSERT INTO small_random SELECT (100000*random())::int, (1000*random()*random())::int, (10*random()*random())::int FROM generate_series(1,100000) s(i); 43 | 44 | -- two random columns, but generated to be correlated 45 | CREATE TABLE small_correlated ( 46 | col_a INT, 47 | col_b INT 48 | ); 49 | 50 | INSERT INTO small_correlated SELECT (i + 100*random())::int, i/1000 FROM generate_series(1,100000) s(i); 51 | 52 | 53 | ANALYZE small_1; 54 | ANALYZE small_10; 55 | ANALYZE small_100; 56 | ANALYZE small_10000; 57 | ANALYZE small_random; 58 | ANALYZE small_correlated; 59 | 60 | 61 | 62 | -- MEDIUM DATASET (10M rows) 63 | 64 | -- correlated columns, same cardinality (identity) 65 | CREATE TABLE medium_1 ( 66 | col_a INT, 67 | col_b INT 68 | ); 69 | 70 | INSERT INTO medium_1 SELECT i, i FROM generate_series(1,10000000) s(i); 71 | 72 | -- different cardinality (second column 10 values) 73 | CREATE TABLE medium_10 ( 74 | col_a INT, 75 | col_b INT 76 | ); 77 | 78 | INSERT INTO medium_10 SELECT i, mod(i,10) FROM generate_series(1,10000000) s(i); 79 | 80 | -- different cardinality (second column 100 values) 81 | CREATE TABLE medium_100 ( 82 | col_a INT, 83 | col_b INT 84 | ); 85 | 86 | INSERT INTO medium_100 SELECT i, mod(i,100) FROM generate_series(1,10000000) s(i); 87 | 88 | -- different cardinality (second column 10000 values) 89 | CREATE TABLE medium_10000 ( 90 | col_a INT, 91 | col_b INT 92 | ); 93 | 94 | INSERT INTO medium_10000 SELECT i, mod(i,10000) FROM generate_series(1,10000000) s(i); 95 | 96 | -- columns with random values and different cardinalities (100k values, 1000 values and 10 values) 97 | CREATE TABLE medium_random ( 98 | col_a INT, 99 | col_b INT, 100 | col_c INT 101 | ); 102 | 103 | INSERT INTO medium_random SELECT (10000000*random())::int, (1000*random()*random())::int, (10*random()*random())::int FROM generate_series(1,10000000) s(i); 104 | 105 | -- two random columns, but generated to be correlated 106 | CREATE TABLE medium_correlated ( 107 | col_a INT, 108 | col_b INT 109 | ); 110 | 111 | INSERT INTO medium_correlated SELECT (i + 100*random())::int, i/1000 FROM generate_series(1,10000000) s(i); 112 | 113 | 114 | ANALYZE medium_1; 115 | ANALYZE medium_10; 116 | ANALYZE medium_100; 117 | ANALYZE medium_10000; 118 | ANALYZE medium_random; 119 | ANALYZE medium_correlated; 120 | 121 | 122 | 123 | -- LARGE DATASET (100M rows) 124 | 125 | -- correlated columns, same cardinality (identity) 126 | CREATE TABLE large_1 ( 127 | col_a INT, 128 | col_b INT 129 | ); 130 | 131 | INSERT INTO large_1 SELECT i, i FROM generate_series(1,100000000) s(i); 132 | 133 | -- different cardinality (second column 10 values) 134 | CREATE TABLE large_10 ( 135 | col_a INT, 136 | col_b INT 137 | ); 138 | 139 | INSERT INTO large_10 SELECT i, mod(i,10) FROM generate_series(1,100000000) s(i); 140 | 141 | -- different cardinality (second column 100 values) 142 | CREATE TABLE large_100 ( 143 | col_a INT, 144 | col_b INT 145 | ); 146 | 147 | INSERT INTO large_100 SELECT i, mod(i,100) FROM generate_series(1,100000000) s(i); 148 | 149 | -- different cardinality (second column 10000 values) 150 | CREATE TABLE large_10000 ( 151 | col_a INT, 152 | col_b INT 153 | ); 154 | 155 | INSERT INTO large_10000 SELECT i, mod(i,10000) FROM generate_series(1,100000000) s(i); 156 | 157 | -- columns with random values and different cardinalities (100k values, 1000 values and 10 values) 158 | CREATE TABLE large_random ( 159 | col_a INT, 160 | col_b INT, 161 | col_c INT 162 | ); 163 | 164 | INSERT INTO large_random SELECT (100000000*random())::int, (1000*random()*random())::int, (10*random()*random())::int FROM generate_series(1,100000000) s(i); 165 | 166 | -- two random columns, but generated to be correlated 167 | CREATE TABLE large_correlated ( 168 | col_a INT, 169 | col_b INT 170 | ); 171 | 172 | INSERT INTO large_correlated SELECT (i + 100*random())::int, i/1000 FROM generate_series(1,100000000) s(i); 173 | 174 | 175 | ANALYZE large_1; 176 | ANALYZE large_10; 177 | ANALYZE large_100; 178 | ANALYZE large_10000; 179 | ANALYZE large_random; 180 | ANALYZE large_correlated; -------------------------------------------------------------------------------- /test/expected/array_agg.out: -------------------------------------------------------------------------------- 1 | \set ECHO none 2 | -- int 3 | SELECT array_agg(a order by a) FROM (SELECT unnest(array_agg_distinct(x::int)) a FROM test_data_1_50)_; 4 | array_agg 5 | ------------------------------------------------------------------------------------------------------------------------------------------------ 6 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50} 7 | (1 row) 8 | 9 | SELECT array_agg(a order by a) FROM (SELECT unnest(array_agg_distinct(mod(x,10)::int)) a FROM test_data_1_50)_; 10 | array_agg 11 | ----------------------- 12 | {0,1,2,3,4,5,6,7,8,9} 13 | (1 row) 14 | 15 | -- bigint 16 | SELECT array_agg(a order by a) FROM (SELECT unnest(array_agg_distinct(x::bigint)) a FROM test_data_1_50)_; 17 | array_agg 18 | ------------------------------------------------------------------------------------------------------------------------------------------------ 19 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50} 20 | (1 row) 21 | 22 | SELECT array_agg(a order by a) FROM (SELECT unnest(array_agg_distinct(mod(x,10)::bigint)) a FROM test_data_1_50)_; 23 | array_agg 24 | ----------------------- 25 | {0,1,2,3,4,5,6,7,8,9} 26 | (1 row) 27 | 28 | -- timestamp 29 | SELECT unnest(array_agg(a order by a)) FROM (SELECT unnest(array_agg_distinct('epoch'::timestamp + (x || ' days')::interval)) a FROM test_data_1_50)_; 30 | unnest 31 | -------------------------- 32 | Fri Jan 02 00:00:00 1970 33 | Sat Jan 03 00:00:00 1970 34 | Sun Jan 04 00:00:00 1970 35 | Mon Jan 05 00:00:00 1970 36 | Tue Jan 06 00:00:00 1970 37 | Wed Jan 07 00:00:00 1970 38 | Thu Jan 08 00:00:00 1970 39 | Fri Jan 09 00:00:00 1970 40 | Sat Jan 10 00:00:00 1970 41 | Sun Jan 11 00:00:00 1970 42 | Mon Jan 12 00:00:00 1970 43 | Tue Jan 13 00:00:00 1970 44 | Wed Jan 14 00:00:00 1970 45 | Thu Jan 15 00:00:00 1970 46 | Fri Jan 16 00:00:00 1970 47 | Sat Jan 17 00:00:00 1970 48 | Sun Jan 18 00:00:00 1970 49 | Mon Jan 19 00:00:00 1970 50 | Tue Jan 20 00:00:00 1970 51 | Wed Jan 21 00:00:00 1970 52 | Thu Jan 22 00:00:00 1970 53 | Fri Jan 23 00:00:00 1970 54 | Sat Jan 24 00:00:00 1970 55 | Sun Jan 25 00:00:00 1970 56 | Mon Jan 26 00:00:00 1970 57 | Tue Jan 27 00:00:00 1970 58 | Wed Jan 28 00:00:00 1970 59 | Thu Jan 29 00:00:00 1970 60 | Fri Jan 30 00:00:00 1970 61 | Sat Jan 31 00:00:00 1970 62 | Sun Feb 01 00:00:00 1970 63 | Mon Feb 02 00:00:00 1970 64 | Tue Feb 03 00:00:00 1970 65 | Wed Feb 04 00:00:00 1970 66 | Thu Feb 05 00:00:00 1970 67 | Fri Feb 06 00:00:00 1970 68 | Sat Feb 07 00:00:00 1970 69 | Sun Feb 08 00:00:00 1970 70 | Mon Feb 09 00:00:00 1970 71 | Tue Feb 10 00:00:00 1970 72 | Wed Feb 11 00:00:00 1970 73 | Thu Feb 12 00:00:00 1970 74 | Fri Feb 13 00:00:00 1970 75 | Sat Feb 14 00:00:00 1970 76 | Sun Feb 15 00:00:00 1970 77 | Mon Feb 16 00:00:00 1970 78 | Tue Feb 17 00:00:00 1970 79 | Wed Feb 18 00:00:00 1970 80 | Thu Feb 19 00:00:00 1970 81 | Fri Feb 20 00:00:00 1970 82 | (50 rows) 83 | 84 | SELECT unnest(array_agg(a order by a)) FROM (SELECT unnest(array_agg_distinct('epoch'::timestamptz + (x || ' days')::interval)) a FROM test_data_1_50)_; 85 | unnest 86 | ------------------------------ 87 | Thu Jan 01 16:00:00 1970 PST 88 | Fri Jan 02 16:00:00 1970 PST 89 | Sat Jan 03 16:00:00 1970 PST 90 | Sun Jan 04 16:00:00 1970 PST 91 | Mon Jan 05 16:00:00 1970 PST 92 | Tue Jan 06 16:00:00 1970 PST 93 | Wed Jan 07 16:00:00 1970 PST 94 | Thu Jan 08 16:00:00 1970 PST 95 | Fri Jan 09 16:00:00 1970 PST 96 | Sat Jan 10 16:00:00 1970 PST 97 | Sun Jan 11 16:00:00 1970 PST 98 | Mon Jan 12 16:00:00 1970 PST 99 | Tue Jan 13 16:00:00 1970 PST 100 | Wed Jan 14 16:00:00 1970 PST 101 | Thu Jan 15 16:00:00 1970 PST 102 | Fri Jan 16 16:00:00 1970 PST 103 | Sat Jan 17 16:00:00 1970 PST 104 | Sun Jan 18 16:00:00 1970 PST 105 | Mon Jan 19 16:00:00 1970 PST 106 | Tue Jan 20 16:00:00 1970 PST 107 | Wed Jan 21 16:00:00 1970 PST 108 | Thu Jan 22 16:00:00 1970 PST 109 | Fri Jan 23 16:00:00 1970 PST 110 | Sat Jan 24 16:00:00 1970 PST 111 | Sun Jan 25 16:00:00 1970 PST 112 | Mon Jan 26 16:00:00 1970 PST 113 | Tue Jan 27 16:00:00 1970 PST 114 | Wed Jan 28 16:00:00 1970 PST 115 | Thu Jan 29 16:00:00 1970 PST 116 | Fri Jan 30 16:00:00 1970 PST 117 | Sat Jan 31 16:00:00 1970 PST 118 | Sun Feb 01 16:00:00 1970 PST 119 | Mon Feb 02 16:00:00 1970 PST 120 | Tue Feb 03 16:00:00 1970 PST 121 | Wed Feb 04 16:00:00 1970 PST 122 | Thu Feb 05 16:00:00 1970 PST 123 | Fri Feb 06 16:00:00 1970 PST 124 | Sat Feb 07 16:00:00 1970 PST 125 | Sun Feb 08 16:00:00 1970 PST 126 | Mon Feb 09 16:00:00 1970 PST 127 | Tue Feb 10 16:00:00 1970 PST 128 | Wed Feb 11 16:00:00 1970 PST 129 | Thu Feb 12 16:00:00 1970 PST 130 | Fri Feb 13 16:00:00 1970 PST 131 | Sat Feb 14 16:00:00 1970 PST 132 | Sun Feb 15 16:00:00 1970 PST 133 | Mon Feb 16 16:00:00 1970 PST 134 | Tue Feb 17 16:00:00 1970 PST 135 | Wed Feb 18 16:00:00 1970 PST 136 | Thu Feb 19 16:00:00 1970 PST 137 | (50 rows) 138 | 139 | -- bool 140 | SELECT array_agg(a order by a) FROM (SELECT unnest(array_agg_distinct(mod(x,2)::bool)) a FROM test_data_1_50)_; 141 | array_agg 142 | ----------- 143 | {f,t} 144 | (1 row) 145 | 146 | -- bool w/nulls 147 | SELECT array_agg(a order by a) FROM (SELECT unnest(array_agg_distinct(nullif(mod(x,2), 0)::bool)) a FROM test_data_0_50)_; 148 | array_agg 149 | ----------- 150 | {t} 151 | (1 row) 152 | 153 | -- int2 154 | SELECT array_agg(a order by a) FROM (SELECT unnest(array_agg_distinct(x::int2)) a FROM test_data_1_50)_; 155 | array_agg 156 | ------------------------------------------------------------------------------------------------------------------------------------------------ 157 | {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50} 158 | (1 row) 159 | 160 | -- array_agg_elements: nulls only 161 | SELECT array_agg_distinct_elements(array[null::int2]) a FROM generate_series(1, 10) x; 162 | a 163 | ---- 164 | {} 165 | (1 row) 166 | 167 | -- array_agg_elements: nulls and non-nulls 168 | SELECT array_agg(a order by a) FROM (SELECT unnest(array_agg_distinct_elements(array[x::int2, null, -x::int2])) a FROM test_data_0_50)_; 169 | array_agg 170 | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 171 | {-50,-49,-48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,-32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50} 172 | (1 row) 173 | 174 | ROLLBACK; 175 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | COUNT_DISTINCT aggregate 2 | ======================== 3 | 4 | [![make installcheck](https://github.com/tvondra/count_distinct/actions/workflows/ci.yml/badge.svg)](https://github.com/tvondra/count_distinct/actions/workflows/ci.yml) 5 | 6 | This extension provides an alternative to COUNT(DISTINCT ...) which for large 7 | amounts of data often ends in sorting and poor performance. 8 | 9 | 10 | Functions 11 | --------- 12 | There are two polymorphic aggregate functions, handling fixed length 13 | data types passed by value (i.e. up to 8B values on 64-bit machines): 14 | 15 | * `count_distinct(p_value anyelement)` 16 | * `array_agg_distinct(p_value anyelement)` 17 | 18 | Two more functions accept arrays of the same types: 19 | 20 | * `count_distinct_elements(p_value anyarray)` 21 | * `array_agg_distinct_elements(p_value anyarray)` 22 | 23 | and work with the elements of the input array (instead of the array 24 | value itself). 25 | 26 | Extending this approach to other data types (passed by reference) shoul 27 | be rather straight-forward. But it's important to be very careful about 28 | memory consumption, as the approach keeps everything in RAM. This issue 29 | is discussed in more detail in one of the following sections. 30 | 31 | Performance 32 | ----------- 33 | So, what's wrong with plain `COUNT(DISTINCT ...)`? Let's use this table 34 | for some tests 35 | 36 | ```sql 37 | CREATE TABLE test_table (id INT, val INT); 38 | 39 | INSERT INTO test_table 40 | SELECT mod(i, 1000), (1000 * random())::int 41 | FROM generate_series(1,10000000) s(i); 42 | 43 | ANALYZE test_table; 44 | ``` 45 | 46 | Now, let's try this query 47 | 48 | ```sql 49 | SELECT id, COUNT(DISTINCT val) FROM test_table GROUP BY 1 50 | ``` 51 | 52 | which is executed like this 53 | 54 | GroupAggregate (cost=1443649.74..1518660.10 rows=1000 width=8) 55 | -> Sort (cost=1443649.74..1468649.86 rows=10000048 width=8) 56 | Sort Key: id 57 | -> Seq Scan on test_table (cost=0.00..144248.48 rows=... 58 | (4 rows) 59 | 60 | On my machine, it takes between 11.5 and 12 seconds, no matter what, and 61 | about ~90% of the time is spent on the sort. So let's see if we can do 62 | that without the sort faster using the COUNT_DISTINCT() aggregate: 63 | 64 | SELECT id, COUNT_DISTINCT(val) FROM test_table GROUP BY 1 65 | 66 | which results in an explain plan like this: 67 | 68 | HashAggregate (cost=194248.72..194261.22 rows=1000 width=8) 69 | -> Seq Scan on test_table (cost=0.00..144248.48 rows=10000048 ... 70 | (2 rows) 71 | 72 | This aggregate function takes ~4.1 seconds and produces exactly the same 73 | results (but unsorted). 74 | 75 | 76 | Should I use this extension? 77 | ---------------------------- 78 | Answering this question is not entirely easy, and you need to consider a 79 | couple of things: 80 | 81 | * Do you need just `COUNT(DISTINCT ...)` or also `array_agg_distinct()`? 82 | 83 | If you only care about `COUNT(DISTINCT ...)`, then using the built-in 84 | stuff from PostgreSQL is an option, and you need to look at the rest 85 | of this section. If you need the `array_agg_distinct()` part, then 86 | using this extension is probably the right thing to do irrespective 87 | of the other questions. 88 | 89 | * How much data are you dealing with? 90 | 91 | If you're only dealing with small amounts of data (a couple megabytes 92 | per group, or so), this extension is unlikely to be much faster than 93 | the built-in `COUNT(DISTINCT ...)` and may actually be slower. 94 | 95 | * What is the data distribution? 96 | 97 | The main metric you need to look at is number of distinct values vs. 98 | number of rows in a group. The higher this value is, the less likely 99 | this extension will be a win, compared to `COUNT(DISTINCT ...)`. But 100 | if there's a lot of redundancy, the deduplication can save a lot. 101 | 102 | * How serious is the OOM risk? 103 | 104 | There's no reasonable way to enforce `work_mem` for user aggregates, 105 | both during planning and execution. Depending on the aggregate method 106 | picked by planner (sort vs. hash) we may end up keeping all data or 107 | the current group in memory. For data sets with many groups and/or 108 | large number of distinct values in a group, this may end up by OOM. 109 | 110 | You need to judge how serious the OOM risk is, considering your data 111 | set, memory available on the system and workload characteristics (how 112 | many queries are running concurrently, etc.). 113 | 114 | * Which PostgreSQL release are you using? 115 | 116 | On older PostgreSQL releases (9.x) this extension was almost always a 117 | clear win, compared to `COUNT(DISTINCT ...)`. But the performance got 118 | much better over time, so if you're using a reasonably recent release 119 | (say, 11+), then maybe just try using PostgreSQL. The speed is likely 120 | on par with this extension and handles memory consumption better. 121 | 122 | The one remaining advantage is support for parallel aggregation, which 123 | the built-in `COUNT(DISTINCT )` code does not support and it may block 124 | parallel aggregation for other aggregates in the same query. 125 | 126 | Ultimately, the best thing you can do is do some testing ... 127 | 128 | 129 | Benchmark 130 | --------- 131 | The `benchmark` directory contains a couple of very simple benchmarking 132 | scripts. The script `create-tables.sql` creates tables of different size 133 | that are then used by queries in `bench-native.sql` (which is running 134 | `COUNT(DISTINCT ...)`) and `bench-count-distinct.sql` (this extension). 135 | 136 | An example of results from one particular machine (CPU Intel i5-2500k, 137 | 8GB RAM, SSD) on PostgreSQL 12 is in the following table. 138 | 139 | | scale | query | native | serial | parallel | serial | parallel | 140 | |--------|-------|--------|--------|----------|--------|----------| 141 | | small | 1 | 10 | 27 | 27 | 272% | 272% | 142 | | | 2 | 10 | 27 | 27 | 270% | 270% | 143 | | | 3 | 44 | 33 | 33 | 75% | 75% | 144 | | | 4 | 93 | 60 | 61 | 65% | 66% | 145 | | | 5 | 45 | 29 | 29 | 64% | 64% | 146 | | | 6 | 93 | 60 | 61 | 65% | 66% | 147 | | | 7 | 50 | 47 | 48 | 94% | 95% | 148 | | | 8 | 93 | 60 | 61 | 65% | 65% | 149 | | | 9 | 99 | 65 | 66 | 67% | 67% | 150 | | | 10 | 93 | 60 | 61 | 65% | 65% | 151 | | | 11 | 47 | 49 | 49 | 105% | 105% | 152 | | | 12 | 90 | 68 | 68 | 76% | 76% | 153 | | | 13 | 44 | 46 | 46 | 104% | 104% | 154 | | | 14 | 47 | 49 | 49 | 105% | 105% | 155 | | | 15 | 39 | 27 | 27 | 68% | 69% | 156 | | | 16 | 79 | 58 | 58 | 73% | 74% | 157 | |--------|-------|--------|--------|----------|--------|----------| 158 | | medium | 1 | 2378 | 3602 | 1341 | 151% | 56% | 159 | | | 2 | 2401 | 3630 | 1325 | 151% | 55% | 160 | | | 3 | 6557 | 4045 | 1524 | 62% | 23% | 161 | | | 4 | 10522 | 7206 | 7406 | 68% | 70% | 162 | | | 5 | 6047 | 3827 | 1456 | 63% | 24% | 163 | | | 6 | 10523 | 7232 | 7362 | 69% | 70% | 164 | | | 7 | 5995 | 6482 | 1832 | 108% | 31% | 165 | | | 8 | 10522 | 7246 | 7369 | 69% | 70% | 166 | | | 9 | 11074 | 7759 | 7761 | 70% | 70% | 167 | | | 10 | 10515 | 7212 | 7281 | 69% | 69% | 168 | | | 11 | 6359 | 6997 | 1963 | 110% | 31% | 169 | | | 12 | 10838 | 8675 | 8661 | 80% | 80% | 170 | | | 13 | 5535 | 5692 | 1459 | 103% | 26% | 171 | | | 14 | 6346 | 6993 | 2020 | 110% | 32% | 172 | | | 15 | 5103 | 5455 | 1446 | 107% | 28% | 173 | | | 16 | 9111 | 6960 | 6975 | 76% | 77% | 174 | |--------|-------|--------|--------|----------|--------|----------| 175 | | large | 1 | 33655 | 38990 | 16370 | 116% | 49% | 176 | | | 2 | 33733 | 39244 | 16341 | 116% | 48% | 177 | | | 3 | 85952 | 45148 | 17881 | 53% | 21% | 178 | | | 4 | 118266 | 85194 | 56260 | 72% | 48% | 179 | | | 5 | 81632 | 42123 | 16852 | 52% | 21% | 180 | | | 6 | 118185 | 84921 | 55843 | 72% | 47% | 181 | | | 7 | 76657 | 83903 | 22802 | 109% | 30% | 182 | | | 8 | 118012 | 85217 | 55288 | 72% | 47% | 183 | | | 9 | 124608 | 91788 | 56302 | 74% | 45% | 184 | | | 10 | 118311 | 85219 | 55101 | 72% | 47% | 185 | | | 11 | 83338 | 88766 | 28569 | 107% | 34% | 186 | | | 12 | 124434 | 102602 | 60438 | 82% | 49% | 187 | | | 13 | 71783 | 70960 | 16877 | 99% | 24% | 188 | | | 14 | 82105 | 87466 | 27524 | 107% | 34% | 189 | | | 15 | 63803 | 67240 | 17426 | 105% | 27% | 190 | | | 16 | 103516 | 82305 | 47196 | 80% | 46% | 191 | 192 | The scale specifies how large the table is - 100k, 1M or 10M rows. There 193 | are 16 different queries. The following three columns show timing (in 194 | milliseconds), median of 6 runs. `native` means `COUNT(DISTINCT ...)`, 195 | while `serial` and `parallel` means functions from this extension, with 196 | parallel queries disabled and enabled. The last two columns are simply 197 | timing compared to `native`. 198 | 199 | It's clear that in serial mode `count_distinct` does perform roughly the 200 | same as `COUNT(DISTINCT ...)` - sometimes it's 2x fast, sometimes a bit 201 | slower than `native`. The `parallel` case however shows significant and 202 | consistent improvements. 203 | 204 | 205 | Issues 206 | ------ 207 | The current implementation works only with fixed-length values passed by 208 | value (i.e. limited by the pointer size), but it should be rather simple 209 | to extend this to other data types. One way to overcome this limitation 210 | is hashing the value into a 32/64-bit integers, and then passing these 211 | hash values to count_distinct (see https://github.com/tvondra/pghashlib 212 | for a good library of hash functions). However be careful as this 213 | effectively turns `count_distinct` into an estimator. 214 | 215 | If an estimator is sufficient for you, maybe 216 | [postgresql-hll](https://github.com/aggregateknowledge/postgresql-hll) 217 | or one of the estimators at [distinct_estimators](https://github.com/tvondra/distinct_estimators) 218 | would be a better solution for you? 219 | 220 | 221 | With the previous implementation (based on hash tables), memory consumption 222 | was a big problem. For example when counting 80M unique 32-bit integers, 223 | it was common to see more than 5GB of RAM allocated (which is way more than 224 | the 320MB necessary for the values, and ~1.6GB when including some hash 225 | table related overhead (buckets, pointers, ...). This was mostly due to 226 | clashing with MemoryContext internals, etc. 227 | 228 | With the new implementation significantly improves this, and the memory 229 | consumption is a fraction (usually less than 10-20% of what it used to be). 230 | 231 | 232 | Still, it may happen that you run out of memory. It's not very likely 233 | because for large number of groups planner will switch to GroupAggregate 234 | (effectively keeping a single group in memory), but it's possible. 235 | 236 | Sadly, that is not something the extension could handle internally in 237 | a reasonable way. The only actual solution is to implement this into 238 | HashAggregate itself (some people are working on this, but don't hold 239 | your breath - it won't happen before 9.5). 240 | 241 | So in short - if you're dealing with a lot of distinct values, you need 242 | a lot of RAM in the machine. 243 | 244 | Versions 245 | -------- 246 | * 1.3.x (branch REL1_3_STABLE) is legacy and supports PostgreSQL 8.4+, 247 | only `count_distinct` aggregate function is provided. 248 | * 2.0.x (branch REL2_0_STABLE) works on PostgreSQL 9.4+ and, in addition to `count_distinct`, 249 | provides the following aggregate functions: 250 | * `count_distinct_elements` (for counting distinct elements in arrays) 251 | * `array_agg_distinct` (for aggregating distinct elements into an array) 252 | * `array_agg_distinct_elements` (for aggregating distinct elements of arrays into a single array) 253 | * 3.0.x (master) requires PostgreSQL 9.6+ and supports parallel aggregation. 254 | 255 | Installation 256 | ------------ 257 | Installing this is very simple, especially if you're using pgxn client. 258 | All you need to do is this: 259 | 260 | $ pgxn install count_distinct 261 | $ pgxn load -d mydb count_distinct 262 | 263 | and you're done. You may also install the extension manually: 264 | 265 | $ make install 266 | $ psql dbname -c "CREATE EXTENSION count_distinct" 267 | 268 | And if you're on an older version (pre-9.1), you have to run the SQL 269 | script manually 270 | 271 | $ psql dbname < `pg_config --sharedir`/contrib/count_distinct--2.0.0.sql 272 | 273 | That's all. 274 | 275 | 276 | License 277 | ------- 278 | This software is distributed under the terms of BSD 2-clause license. 279 | See LICENSE or http://www.opensource.org/licenses/bsd-license.php for 280 | more details. 281 | -------------------------------------------------------------------------------- /count_distinct.c: -------------------------------------------------------------------------------- 1 | /* 2 | * count_distinct.c - alternative to COUNT(DISTINCT ...) 3 | * Copyright (C) Tomas Vondra, 2013 - 2016 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "postgres.h" 15 | #include "utils/array.h" 16 | #include "utils/lsyscache.h" 17 | #include "utils/memutils.h" 18 | #include "access/tupmacs.h" 19 | 20 | PG_MODULE_MAGIC; 21 | 22 | /* if set to 1, the table resize will be profiled */ 23 | #define DEBUG_PROFILE 0 24 | 25 | #define GET_AGG_CONTEXT(fname, fcinfo, aggcontext) \ 26 | if (! AggCheckCallContext(fcinfo, &aggcontext)) { \ 27 | elog(ERROR, "%s called in non-aggregate context", fname); \ 28 | } 29 | 30 | #define CHECK_AGG_CONTEXT(fname, fcinfo) \ 31 | if (! AggCheckCallContext(fcinfo, NULL)) { \ 32 | elog(ERROR, "%s called in non-aggregate context", fname); \ 33 | } 34 | 35 | /* 36 | * This count_distinct implementation uses a simple, partially sorted array. 37 | * 38 | * It's considerably simpler than the hash-table based version, and the main 39 | * goals of this design is to: 40 | * 41 | * (a) minimize the palloc overhead - the whole array is allocated as a whole, 42 | * and thus has a single palloc header (while in the hash table, each 43 | * bucket had at least one such header) 44 | * 45 | * (b) optimal L2/L3 cache utilization - once the hash table can't fit into 46 | * the CPU caches, it get's considerably slower because of cache misses, 47 | * and it's impossible to improve the hash implementation (because for 48 | * large hash tables it naturally leads to cache misses) 49 | * 50 | * Hash tables are great when you need to immediately query the structure 51 | * (e.g. to immediately check whether the key is already in the table), but 52 | * in count_distint it's not really necessary. We can accumulate some elements 53 | * first (into a buffer), and then process all of them at once - this approach 54 | * improves the CPU cache hit ratios. Also, the palloc overhead is much lower. 55 | * 56 | * The data array is split into three sections - sorted items, unsorted items, 57 | * and unused. 58 | * 59 | * ---------------------------------------------- 60 | * | sorted | unsorted | free | 61 | * ---------------------------------------------- 62 | * 63 | * Initially, the sorted / unsorted sections are empty, of course. 64 | * 65 | * ---------------------------------------------- 66 | * | free | 67 | * ---------------------------------------------- 68 | * 69 | * New values are simply accumulated into the unsorted section, which grows. 70 | * 71 | * ---------------------------------------------- 72 | * | unsorted --> | free | 73 | * ---------------------------------------------- 74 | * 75 | * Once there's no more space for new items, the unsorted items are 'compacted' 76 | * which means the values are sorted, duplicates are removed and the result 77 | * is merged into the sorted section (unless it's empty). The 'merge' is just 78 | * a simple 'merge-sort' of the two sorted inputs, with removal of duplicates. 79 | * 80 | * Once the compaction completes, it's checked whether enough space was freed, 81 | * where 'enough' means ~20% of the array needs to be free. Using low values 82 | * (e.g. space for at least one value) might cause 'oscillation' - imagine 83 | * compaction that removes a single item, causing compaction on the very next 84 | * addition. Using non-trivial threshold (like the 20%) should prevent such 85 | * frequent compactions - which is quite expensive operation. 86 | * 87 | * If there's not enough free space, the array grows (twice the size). 88 | * 89 | * The compaction needs to be performed at the very end, when computing the 90 | * actual result of the aggregate (distinct value in the array). 91 | */ 92 | typedef struct element_set_t 93 | { 94 | /* aggregation memory context (so we don't need to do lookups repeatedly) */ 95 | MemoryContext aggctx; 96 | 97 | Size nbytes; /* size of the data array (number of bytes) */ 98 | uint32 nsorted; /* number of items in the sorted part */ 99 | uint32 nall; /* number of all items (sorted + unsorted) */ 100 | 101 | /* used for arrays only (cache for get_typlenbyvalalign results) */ 102 | int16 typlen; 103 | bool typbyval; 104 | char typalign; 105 | 106 | /* array of elements */ 107 | char *data; /* nsorted items first, then unsorted ones */ 108 | } element_set_t; 109 | 110 | /* 111 | * Initial size of the array (in bytes). This should be larger than the 112 | * minimum chunk size, which for AllocSet is 8B. As the element_set_t 113 | * struct has a fairly significant overhead (~40B) the 32B seems like a 114 | * reasonable value. 115 | */ 116 | #define ARRAY_INIT_SIZE 32 117 | 118 | /* we want >= 20% free space after compaction (mostly arbitrary value) */ 119 | #define ARRAY_FREE_FRACT 0.2 120 | 121 | /* 122 | * prototypes 123 | */ 124 | 125 | /* transition functions */ 126 | PG_FUNCTION_INFO_V1(count_distinct_append); 127 | PG_FUNCTION_INFO_V1(count_distinct_elements_append); 128 | 129 | /* parallel aggregation support functions */ 130 | PG_FUNCTION_INFO_V1(count_distinct_serial); 131 | PG_FUNCTION_INFO_V1(count_distinct_deserial); 132 | PG_FUNCTION_INFO_V1(count_distinct_combine); 133 | 134 | /* final functions */ 135 | PG_FUNCTION_INFO_V1(count_distinct); 136 | PG_FUNCTION_INFO_V1(array_agg_distinct_type_by_element); 137 | PG_FUNCTION_INFO_V1(array_agg_distinct_type_by_array); 138 | 139 | /* supplementary subroutines */ 140 | static void add_element(element_set_t *eset, char *value); 141 | static element_set_t *init_set(int16 typlen, bool typbyval, char typalign, MemoryContext ctx); 142 | static element_set_t *copy_set(element_set_t *eset); 143 | 144 | static int compare_items(const void *a, const void *b, void *size); 145 | static void compact_set(element_set_t *eset, bool need_space); 146 | static Datum build_array(element_set_t *eset, Oid input_type); 147 | 148 | 149 | Datum 150 | count_distinct_append(PG_FUNCTION_ARGS) 151 | { 152 | element_set_t *eset; 153 | 154 | /* info for anyelement */ 155 | Oid element_type = get_fn_expr_argtype(fcinfo->flinfo, 1); 156 | Datum element = PG_GETARG_DATUM(1); 157 | 158 | /* memory contexts */ 159 | MemoryContext oldcontext; 160 | MemoryContext aggcontext; 161 | 162 | /* 163 | * If the new value is NULL, we simply return the current aggregate state 164 | * (it might be NULL, so check it). 165 | */ 166 | if (PG_ARGISNULL(1) && PG_ARGISNULL(0)) 167 | PG_RETURN_NULL(); 168 | else if (PG_ARGISNULL(1)) 169 | PG_RETURN_DATUM(PG_GETARG_DATUM(0)); 170 | 171 | /* from now on we know the new value is not NULL */ 172 | 173 | /* switch to the per-group hash-table memory context */ 174 | GET_AGG_CONTEXT("count_distinct_append", fcinfo, aggcontext); 175 | 176 | oldcontext = MemoryContextSwitchTo(aggcontext); 177 | 178 | /* init the hash table, if needed */ 179 | if (PG_ARGISNULL(0)) 180 | { 181 | int16 typlen; 182 | bool typbyval; 183 | char typalign; 184 | 185 | /* get type information for the second parameter (anyelement item) */ 186 | get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign); 187 | 188 | /* we can't handle varlena types yet or values passed by reference */ 189 | if ((typlen < 0) || (! typbyval)) 190 | elog(ERROR, "count_distinct handles only fixed-length types passed by value"); 191 | 192 | eset = init_set(typlen, typbyval, typalign, aggcontext); 193 | } else 194 | eset = (element_set_t *) PG_GETARG_POINTER(0); 195 | 196 | /* add the value into the set */ 197 | add_element(eset, (char *) &element); 198 | 199 | MemoryContextSwitchTo(oldcontext); 200 | 201 | PG_RETURN_POINTER(eset); 202 | } 203 | 204 | Datum 205 | count_distinct_elements_append(PG_FUNCTION_ARGS) 206 | { 207 | int i; 208 | element_set_t *eset = NULL; 209 | 210 | /* info for anyarray */ 211 | Oid input_type; 212 | Oid element_type; 213 | 214 | /* array data */ 215 | ArrayType *input; 216 | Datum *elements; 217 | bool *nulls; 218 | int nelements; 219 | 220 | /* needed for array deconstruction */ 221 | int16 typlen; 222 | bool typbyval; 223 | char typalign; 224 | 225 | /* memory contexts */ 226 | MemoryContext oldcontext; 227 | MemoryContext aggcontext; 228 | 229 | /* 230 | * If the new value is NULL, we simply return the current aggregate state 231 | * (it might be NULL, so check it). In this case we don't really care about 232 | * the types etc. 233 | * 234 | * We may still get NULL elements in the array, but to check that we would 235 | * have to walk the array, which does not qualify as cheap check. Also we 236 | * assume that there's at least one non-NULL element, and we'll walk the 237 | * array just once. It's possible we'll get empty set this way. 238 | */ 239 | if (PG_ARGISNULL(1) && PG_ARGISNULL(0)) 240 | PG_RETURN_NULL(); 241 | else if (PG_ARGISNULL(1)) 242 | PG_RETURN_DATUM(PG_GETARG_DATUM(0)); 243 | 244 | /* from now on we know the new value is not NULL */ 245 | 246 | /* get the type of array elements */ 247 | input_type = get_fn_expr_argtype(fcinfo->flinfo, 1); 248 | element_type = get_element_type(input_type); 249 | 250 | /* make sure we're running as part of aggregate function */ 251 | GET_AGG_CONTEXT("count_distinct_elements_append", fcinfo, aggcontext); 252 | 253 | oldcontext = MemoryContextSwitchTo(aggcontext); 254 | 255 | /* get existing state, if any (otherwise leave it NULL) */ 256 | if (!PG_ARGISNULL(0)) 257 | eset = (element_set_t *) PG_GETARG_POINTER(0); 258 | 259 | /* parse the array contents (we know we got non-NULL value) */ 260 | input = PG_GETARG_ARRAYTYPE_P(1); 261 | 262 | /* 263 | * get type information for the second parameter (anyelement item), from 264 | * the existing state or from cache. 265 | */ 266 | if (eset) 267 | { 268 | typlen = eset->typlen; 269 | typbyval = eset->typbyval; 270 | typalign = eset->typalign; 271 | } 272 | else 273 | get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign); 274 | 275 | /* we can't handle varlena types yet or values passed by reference */ 276 | if ((typlen < 0) || (! typbyval)) 277 | elog(ERROR, "count_distinct handles only fixed-length types passed by value"); 278 | 279 | deconstruct_array(input, 280 | element_type, typlen, typbyval, typalign, 281 | &elements, &nulls, &nelements); 282 | 283 | /* add all non-NULL array elements to the set */ 284 | for (i = 0; i < nelements; i++) 285 | { 286 | Datum value; 287 | 288 | /* ignore nulls */ 289 | if (nulls[i]) 290 | continue; 291 | 292 | /* init the hash table, if needed */ 293 | if (!eset) 294 | eset = init_set(typlen, typbyval, typalign, aggcontext); 295 | 296 | /* 297 | * We need to copy just the significant bytes - we can't use memcpy 298 | * directly, as that assumes little endian behavior. store_att_byval 299 | * does almost what we need, but it requires properly aligned buffer. 300 | * We simply use a local Datum variable (which does guarante proper 301 | * alignment), and then copy the value from it. 302 | */ 303 | store_att_byval(&value, elements[i], eset->typlen); 304 | 305 | add_element(eset, (char *) &value); 306 | } 307 | 308 | MemoryContextSwitchTo(oldcontext); 309 | 310 | /* free arrays allocated by deconstruct_array */ 311 | pfree(elements); 312 | pfree(nulls); 313 | 314 | if (eset == NULL) 315 | PG_RETURN_NULL(); 316 | 317 | PG_RETURN_POINTER(eset); 318 | } 319 | 320 | Datum 321 | count_distinct_serial(PG_FUNCTION_ARGS) 322 | { 323 | element_set_t *eset = (element_set_t *) PG_GETARG_POINTER(0); 324 | Size hlen = offsetof(element_set_t, data); /* header */ 325 | Size dlen; /* elements */ 326 | bytea *out; /* output */ 327 | char *ptr; 328 | 329 | Assert(eset != NULL); 330 | 331 | CHECK_AGG_CONTEXT("count_distinct_serial", fcinfo); 332 | 333 | /* 334 | * force compaction, so that we serialize the smallest amount of data 335 | * and also make sure the data is sorted (and the sort happens in the 336 | * parallel workers, ot distribute the CPU better) 337 | */ 338 | compact_set(eset, false); 339 | 340 | Assert(eset->nall > 0); 341 | Assert(eset->nall == eset->nsorted); 342 | 343 | dlen = eset->nall * eset->typlen; 344 | 345 | out = (bytea *) palloc(VARHDRSZ + dlen + hlen); 346 | 347 | SET_VARSIZE(out, VARHDRSZ + dlen + hlen); 348 | ptr = VARDATA(out); 349 | 350 | memcpy(ptr, eset, hlen); 351 | ptr += hlen; 352 | 353 | memcpy(ptr, eset->data, dlen); 354 | 355 | PG_RETURN_BYTEA_P(out); 356 | } 357 | 358 | Datum 359 | count_distinct_deserial(PG_FUNCTION_ARGS) 360 | { 361 | element_set_t *eset = (element_set_t *) palloc(sizeof(element_set_t)); 362 | bytea *state = (bytea *) PG_GETARG_POINTER(0); 363 | Size len PG_USED_FOR_ASSERTS_ONLY = VARSIZE_ANY_EXHDR(state); 364 | char *ptr = VARDATA_ANY(state); 365 | 366 | CHECK_AGG_CONTEXT("count_distinct_deserial", fcinfo); 367 | 368 | Assert(len > 0); 369 | Assert((len - offsetof(element_set_t, data)) > 0); 370 | 371 | /* copy the header */ 372 | memcpy(eset, ptr, offsetof(element_set_t, data)); 373 | ptr += offsetof(element_set_t, data); 374 | 375 | Assert((eset->nall > 0) && (eset->nall == eset->nsorted)); 376 | Assert(len == offsetof(element_set_t, data) + eset->nall * eset->typlen); 377 | 378 | /* we only allocate the necessary space */ 379 | eset->data = palloc(eset->nall * eset->typlen); 380 | eset->nbytes = eset->nall * eset->typlen; 381 | 382 | memcpy((void *) eset->data, ptr, eset->nall * eset->typlen); 383 | 384 | PG_RETURN_POINTER(eset); 385 | } 386 | 387 | Datum 388 | count_distinct_combine(PG_FUNCTION_ARGS) 389 | { 390 | int i; 391 | char *data, 392 | *tmp, 393 | *ptr1, 394 | *ptr2, 395 | *prev; 396 | element_set_t *eset1; 397 | element_set_t *eset2; 398 | MemoryContext agg_context; 399 | MemoryContext old_context; 400 | 401 | GET_AGG_CONTEXT("count_distinct_combine", fcinfo, agg_context); 402 | 403 | eset1 = PG_ARGISNULL(0) ? NULL : (element_set_t *) PG_GETARG_POINTER(0); 404 | eset2 = PG_ARGISNULL(1) ? NULL : (element_set_t *) PG_GETARG_POINTER(1); 405 | 406 | if (eset2 == NULL) { 407 | /* pass eset1 down the line */ 408 | if (eset1 == NULL) 409 | PG_RETURN_NULL(); 410 | else 411 | PG_RETURN_POINTER(eset1); 412 | } 413 | 414 | if (eset1 == NULL) 415 | { 416 | old_context = MemoryContextSwitchTo(agg_context); 417 | 418 | eset1 = copy_set(eset2); 419 | 420 | MemoryContextSwitchTo(old_context); 421 | 422 | PG_RETURN_POINTER(eset1); 423 | } 424 | 425 | Assert((eset1 != NULL) && (eset2 != NULL)); 426 | Assert((eset1->typlen > 0) && (eset1->typlen == eset2->typlen)); 427 | 428 | /* make sure both states are sorted */ 429 | compact_set(eset1, false); 430 | compact_set(eset2, false); 431 | 432 | data = MemoryContextAlloc(agg_context, (eset1->nbytes + eset2->nbytes)); 433 | tmp = data; 434 | 435 | /* merge the two arrays */ 436 | ptr1 = eset1->data; 437 | ptr2 = eset2->data; 438 | prev = NULL; 439 | 440 | for (i = 0; i < eset1->nall + eset2->nall; i++) 441 | { 442 | char *element; 443 | 444 | Assert(ptr1 <= (eset1->data + eset1->nbytes)); 445 | Assert(ptr2 <= (eset2->data + eset2->nbytes)); 446 | 447 | if ((ptr1 < (eset1->data + eset1->nbytes)) && 448 | (ptr2 < (eset2->data + eset2->nbytes))) 449 | { 450 | if (memcmp(ptr1, ptr2, eset1->typlen) <= 0) 451 | { 452 | element = ptr1; 453 | ptr1 += eset1->typlen; 454 | } 455 | else 456 | { 457 | element = ptr2; 458 | ptr2 += eset1->typlen; 459 | } 460 | } 461 | else if (ptr1 < (eset1->data + eset1->nbytes)) 462 | { 463 | element = ptr1; 464 | ptr1 += eset1->typlen; 465 | } 466 | else if (ptr2 < (eset2->data + eset2->nbytes)) 467 | { 468 | element = ptr2; 469 | ptr2 += eset2->typlen; 470 | } 471 | else 472 | elog(ERROR, "unexpected"); 473 | 474 | /* 475 | * Now figure out what to do with the element - we need to compare it 476 | * to the last value, and only keep it if it's different (and it better 477 | * be greater than the last value). 478 | */ 479 | if (tmp == data) 480 | { 481 | /* first value, so just copy */ 482 | memcpy(tmp, element, eset1->typlen); 483 | prev = tmp; 484 | tmp += eset1->typlen; 485 | } 486 | else if (memcmp(prev, element, eset1->typlen) != 0) 487 | { 488 | /* not equal to the last one, so should be greater */ 489 | Assert(memcmp(prev, element, eset1->typlen) < 0); 490 | 491 | /* first value, so just copy */ 492 | memcpy(tmp, element, eset1->typlen); 493 | prev = tmp; 494 | tmp += eset1->typlen; 495 | } 496 | } 497 | 498 | /* we must have processed the input arrays completely */ 499 | Assert(ptr1 == (eset1->data + (eset1->nall * eset1->typlen))); 500 | Assert(ptr2 == (eset2->data + (eset2->nall * eset2->typlen))); 501 | 502 | /* we might have eliminated some duplicate elements */ 503 | Assert((tmp - data) <= ((eset1->nall + eset2->nall) * eset1->typlen)); 504 | 505 | pfree(eset1->data); 506 | eset1->data = data; 507 | 508 | /* and finally compute the current number of elements */ 509 | eset1->nbytes = tmp - data; 510 | eset1->nall = eset1->nbytes / eset1->typlen; 511 | eset1->nsorted = eset1->nall; 512 | 513 | PG_RETURN_POINTER(eset1); 514 | } 515 | 516 | Datum 517 | count_distinct(PG_FUNCTION_ARGS) 518 | { 519 | element_set_t *eset; 520 | 521 | CHECK_AGG_CONTEXT("count_distinct", fcinfo); 522 | 523 | if (PG_ARGISNULL(0)) 524 | PG_RETURN_NULL(); 525 | 526 | eset = (element_set_t *) PG_GETARG_POINTER(0); 527 | 528 | /* do the compaction */ 529 | compact_set(eset, false); 530 | 531 | PG_RETURN_INT64(eset->nall); 532 | } 533 | 534 | Datum 535 | array_agg_distinct_type_by_element(PG_FUNCTION_ARGS) 536 | { 537 | element_set_t *eset; 538 | Oid element_type; 539 | 540 | /* get element type for the dummy second parameter (anynonarray item) */ 541 | eset = (element_set_t *) PG_GETARG_POINTER(0); 542 | element_type = get_fn_expr_argtype(fcinfo->flinfo, 1); 543 | 544 | CHECK_AGG_CONTEXT("count_distinct", fcinfo); 545 | 546 | /* return empty array if the state was not initialized */ 547 | if (PG_ARGISNULL(0)) 548 | PG_RETURN_DATUM(PointerGetDatum(construct_empty_array(element_type))); 549 | 550 | PG_RETURN_DATUM(build_array(eset, element_type)); 551 | } 552 | 553 | Datum 554 | array_agg_distinct_type_by_array(PG_FUNCTION_ARGS) 555 | { 556 | element_set_t *eset; 557 | Oid input_type; 558 | Oid element_type; 559 | 560 | /* get element type for the dummy second parameter (anyarray item) */ 561 | eset = (element_set_t *) PG_GETARG_POINTER(0); 562 | input_type = get_fn_expr_argtype(fcinfo->flinfo, 1); 563 | element_type = get_element_type(input_type); 564 | 565 | CHECK_AGG_CONTEXT("count_distinct", fcinfo); 566 | 567 | /* return empty array if the state was not initialized */ 568 | if (PG_ARGISNULL(0)) 569 | PG_RETURN_DATUM(PointerGetDatum(construct_empty_array(element_type))); 570 | 571 | PG_RETURN_DATUM(build_array(eset, element_type)); 572 | } 573 | 574 | static Datum 575 | build_array(element_set_t *eset, Oid element_type) 576 | { 577 | Datum *array_of_datums; 578 | ArrayType *array; 579 | int i; 580 | 581 | /* do the compaction */ 582 | compact_set(eset, false); 583 | 584 | /* 585 | * Copy data from compact array to array of Datums 586 | * A bit suboptimal way, spends excessive memory. 587 | */ 588 | array_of_datums = palloc0(eset->nsorted * sizeof(Datum)); 589 | for (i = 0; i < eset->nsorted; i++) 590 | memcpy(array_of_datums + i, eset->data + (eset->typlen * i), eset->typlen); 591 | 592 | /* build and return the array */ 593 | array = construct_array(array_of_datums, eset->nsorted, element_type, 594 | eset->typlen, eset->typbyval, eset->typalign); 595 | 596 | /* free the array (not needed anymore) */ 597 | pfree(array_of_datums); 598 | 599 | return PointerGetDatum(array); 600 | } 601 | 602 | /* 603 | * performs compaction of the sorted set 604 | * 605 | * Sorts the unsorted data, removes duplicate values and then merges it 606 | * into the already sorted part (skipping duplicate values). 607 | * 608 | * Finally, it checks whether at least ARRAY_FREE_FRACT (20%) of the array 609 | * is empty, and if not then resizes it. 610 | */ 611 | static void 612 | compact_set(element_set_t *eset, bool need_space) 613 | { 614 | char *base = eset->data + (eset->nsorted * eset->typlen); 615 | char *last = base; 616 | char *curr; 617 | int i; 618 | int cnt = 1; 619 | double free_fract; 620 | 621 | Assert(eset->nall > 0); 622 | Assert(eset->data != NULL); 623 | Assert(eset->nsorted <= eset->nall); 624 | Assert(eset->nall * eset->typlen <= eset->nbytes); 625 | 626 | /* if there are no new (unsorted) items, we don't need to sort */ 627 | if (eset->nall > eset->nsorted) 628 | { 629 | /* 630 | * sort the array with new items, but only when not already sorted 631 | * 632 | * TODO Consider replacing this insert-sort for small number of items 633 | * (for <64 items it might be faster than qsort) 634 | */ 635 | qsort_arg(eset->data + eset->nsorted * eset->typlen, 636 | eset->nall - eset->nsorted, eset->typlen, 637 | compare_items, &eset->typlen); 638 | 639 | /* 640 | * Remove duplicate values from the sorted array. That is - walk through 641 | * the array, compare each item with the preceding one, and only keep it 642 | * if they differ. We skip the first value, as it's always unique (there 643 | * is no preceding value it might be equal to). 644 | */ 645 | for (i = 1; i < eset->nall - eset->nsorted; i++) 646 | { 647 | curr = base + (i * eset->typlen); 648 | 649 | /* items differ (keep the item) */ 650 | if (memcmp(last, curr, eset->typlen) != 0) 651 | { 652 | last += eset->typlen; 653 | cnt += 1; 654 | 655 | /* only copy if really needed */ 656 | if (last != curr) 657 | memcpy(last, curr, eset->typlen); 658 | } 659 | } 660 | 661 | /* duplicities removed -> update the number of items in this part */ 662 | eset->nall = eset->nsorted + cnt; 663 | 664 | /* If this is the first sorted part, we can just use it as the 'sorted' part. */ 665 | if (eset->nsorted == 0) 666 | eset->nsorted = eset->nall; 667 | 668 | /* 669 | * TODO Another optimization opportunity is that we don't really need to 670 | * merge the arrays, if we freed enough space by processing the new 671 | * items. We may postpone that until the last call (when finalizing 672 | * the aggregate). OTOH if that happens, it shouldn't be that 673 | * expensive to merge because the number of new items will be small 674 | * (as we've removed a enough duplicities). But we still need to 675 | * shuffle the data around, which wastes memory bandwidth. 676 | */ 677 | 678 | /* If a merge is needed, walk through the arrays and keep unique values. */ 679 | if (eset->nsorted < eset->nall) 680 | { 681 | MemoryContext oldctx = MemoryContextSwitchTo(eset->aggctx); 682 | 683 | /* allocate new array for the result */ 684 | char * data = palloc(eset->nbytes); 685 | char * ptr = data; 686 | 687 | /* already sorted array */ 688 | char * a = eset->data; 689 | char * a_max = eset->data + eset->nsorted * eset->typlen; 690 | 691 | /* the new array */ 692 | char * b = eset->data + (eset->nsorted * eset->typlen); 693 | char * b_max = eset->data + eset->nall * eset->typlen; 694 | 695 | MemoryContextSwitchTo(oldctx); 696 | 697 | /* 698 | * TODO There's a possibility for optimization - if we get already 699 | * sorted items (e.g. because of a subplan), we can just copy the 700 | * arrays. The check is as simple as checking 701 | * 702 | * (a_first > b_last) || (a_last < b_first). 703 | * 704 | * OTOH this is probably very unlikely to happen in practice. 705 | */ 706 | 707 | while (true) 708 | { 709 | int r = memcmp(a, b, eset->typlen); 710 | 711 | /* 712 | * If both values are the same, copy one of them into the result and increment 713 | * both. Otherwise, increment only the smaller value. 714 | */ 715 | if (r == 0) 716 | { 717 | memcpy(ptr, a, eset->typlen); 718 | a += eset->typlen; 719 | b += eset->typlen; 720 | } 721 | else if (r < 0) 722 | { 723 | memcpy(ptr, a, eset->typlen); 724 | a += eset->typlen; 725 | } 726 | else 727 | { 728 | memcpy(ptr, b, eset->typlen); 729 | b += eset->typlen; 730 | } 731 | 732 | ptr += eset->typlen; 733 | 734 | /* 735 | * If we reached the end of (at least) one of the arrays, copy all 736 | * the remaining items and we're done. 737 | */ 738 | if ((a == a_max) || (b == b_max)) 739 | { 740 | if (a != a_max) /* b ended -> copy rest of a */ 741 | { 742 | memcpy(ptr, a, a_max - a); 743 | ptr += (a_max - a); 744 | } 745 | else if (b != b_max) /* a ended -> copy rest of b */ 746 | { 747 | memcpy(ptr, b, b_max - b); 748 | ptr += (b_max - b); 749 | } 750 | 751 | break; 752 | } 753 | } 754 | 755 | Assert((ptr - data) <= (eset->nall * eset->typlen)); 756 | 757 | /* 758 | * Update the counts with the result of the merge (there might be 759 | * duplicities between the two parts, and we have eliminated them). 760 | */ 761 | eset->nsorted = (ptr - data) / eset->typlen; 762 | eset->nall = eset->nsorted; 763 | pfree(eset->data); 764 | eset->data = data; 765 | } 766 | } 767 | 768 | Assert(eset->nall == eset->nsorted); 769 | 770 | /* compute free space as a fraction of the total size */ 771 | free_fract 772 | = (eset->nbytes - eset->nall * eset->typlen) * 1.0 / eset->nbytes; 773 | 774 | /* 775 | * If we need space for more items (e.g. not when finalizing the aggregate 776 | * result), enlarge the array when needed. We require ARRAY_FREE_FRACT of 777 | * the space to be free. 778 | */ 779 | if (need_space && (free_fract < ARRAY_FREE_FRACT)) 780 | { 781 | /* 782 | * For small requests, we simply double the array size, because that's 783 | * what AllocSet will give use anyway. No point in trying to save 784 | * memory by growing the array slower. 785 | * 786 | * After reaching ALLOCSET_SEPARATE_THRESHOLD, the memory is allocated 787 | * in separate blocks, thus we can be smarter and grow the memory 788 | * a bit slower (just enough to get the 20% free space). 789 | * 790 | * XXX If the memory context uses smaller blocks, the switch to special 791 | * blocks may happen before ALLOCSET_SEPARATE_THRESHOLD. This limit 792 | * is simply global guarantee for all possible AllocSets. 793 | */ 794 | if ((eset->nbytes / 0.8) < ALLOCSET_SEPARATE_THRESHOLD) 795 | eset->nbytes *= 2; 796 | else 797 | eset->nbytes /= 0.8; 798 | 799 | eset->data = repalloc(eset->data, eset->nbytes); 800 | } 801 | 802 | #if DEBUG_PROFILE 803 | elog(WARNING, "compact_set: bytes=%lu item=%d all=%d sorted=%d", 804 | eset->nbytes, eset->typlen, eset->nall, eset->nsorted); 805 | #endif 806 | } 807 | 808 | static void 809 | add_element(element_set_t *eset, char *value) 810 | { 811 | /* 812 | * If there's not enough space for another item, perform compaction 813 | * (this also allocates enough free space for new entries). 814 | */ 815 | if (eset->typlen * (eset->nall + 1) > eset->nbytes) 816 | compact_set(eset, true); 817 | 818 | /* there needs to be space for at least one more value (thanks to the compaction) */ 819 | Assert(eset->nbytes >= eset->typlen * (eset->nall + 1)); 820 | 821 | /* now we're sure there's enough space */ 822 | memcpy(eset->data + (eset->typlen * eset->nall), value, eset->typlen); 823 | eset->nall += 1; 824 | } 825 | 826 | /* XXX make sure the whole method is called within the aggregate context */ 827 | static element_set_t * 828 | init_set(int16 typlen, bool typbyval, char typalign, MemoryContext ctx) 829 | { 830 | element_set_t * eset = (element_set_t *) palloc(sizeof(element_set_t)); 831 | 832 | eset->typlen = typlen; 833 | eset->typbyval = typbyval; 834 | eset->typalign = typalign; 835 | eset->nsorted = 0; 836 | eset->nall = 0; 837 | eset->nbytes = ARRAY_INIT_SIZE; 838 | eset->aggctx = ctx; 839 | 840 | eset->data = palloc(eset->nbytes); 841 | 842 | return eset; 843 | } 844 | 845 | static element_set_t * 846 | copy_set(element_set_t *eset) 847 | { 848 | element_set_t *copy; 849 | 850 | copy = (element_set_t *) palloc(sizeof(element_set_t)); 851 | copy->typlen = eset->typlen; 852 | copy->typalign = eset->typalign; 853 | copy->typbyval = eset->typbyval; 854 | copy->nsorted = eset->nsorted; 855 | copy->nall = eset->nall; 856 | copy->nbytes = eset->nbytes; 857 | 858 | copy->data = palloc(eset->nbytes); 859 | 860 | memcpy(copy->data, eset->data, eset->nbytes); 861 | 862 | return copy; 863 | } 864 | 865 | /* just compare the data directly using memcmp */ 866 | static int 867 | compare_items(const void *a, const void *b, void *size) 868 | { 869 | return memcmp(a, b, *(int *) size); 870 | } 871 | -------------------------------------------------------------------------------- /benchmark/bench-native.sql: -------------------------------------------------------------------------------- 1 | \timing off 2 | 3 | EXPLAIN SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM small_1) AS foo; 4 | EXPLAIN SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM small_1) AS foo; 5 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_10 GROUP BY col_b) AS foo; 6 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_10 GROUP BY col_a) AS foo; 7 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_100 GROUP BY col_b) AS foo; 8 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_100 GROUP BY col_a) AS foo; 9 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_10000 GROUP BY col_b) AS foo; 10 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_10000 GROUP BY col_a) AS foo; 11 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_1 GROUP BY col_b) AS foo; 12 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_1 GROUP BY col_a) AS foo; 13 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_random GROUP BY col_b) AS foo; 14 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_random GROUP BY col_a) AS foo; 15 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM small_random GROUP BY col_b) AS foo; 16 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_random GROUP BY col_b) AS foo; 17 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_correlated GROUP BY col_b) AS foo; 18 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_correlated GROUP BY col_a) AS foo; 19 | 20 | EXPLAIN SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM medium_1) AS foo; 21 | EXPLAIN SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM medium_1) AS foo; 22 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_10 GROUP BY col_b) AS foo; 23 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_10 GROUP BY col_a) AS foo; 24 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_100 GROUP BY col_b) AS foo; 25 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_100 GROUP BY col_a) AS foo; 26 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_10000 GROUP BY col_b) AS foo; 27 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_10000 GROUP BY col_a) AS foo; 28 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_1 GROUP BY col_b) AS foo; 29 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_1 GROUP BY col_a) AS foo; 30 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 31 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_random GROUP BY col_a) AS foo; 32 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM medium_random GROUP BY col_b) AS foo; 33 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 34 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_correlated GROUP BY col_b) AS foo; 35 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_correlated GROUP BY col_a) AS foo; 36 | 37 | EXPLAIN SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM large_1) AS foo; 38 | EXPLAIN SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM large_1) AS foo; 39 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_10 GROUP BY col_b) AS foo; 40 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_10 GROUP BY col_a) AS foo; 41 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_100 GROUP BY col_b) AS foo; 42 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_100 GROUP BY col_a) AS foo; 43 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_10000 GROUP BY col_b) AS foo; 44 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_10000 GROUP BY col_a) AS foo; 45 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_1 GROUP BY col_b) AS foo; 46 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_1 GROUP BY col_a) AS foo; 47 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_random GROUP BY col_b) AS foo; 48 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM large_random GROUP BY col_b) AS foo; 49 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_random GROUP BY col_b) AS foo; 50 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_correlated GROUP BY col_b) AS foo; 51 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_correlated GROUP BY col_a) AS foo; 52 | 53 | \timing on 54 | 55 | \echo SMALL QUERY 1 56 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM small_1) AS foo; 57 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM small_1) AS foo; 58 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM small_1) AS foo; 59 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM small_1) AS foo; 60 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM small_1) AS foo; 61 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM small_1) AS foo; 62 | 63 | \echo SMALL QUERY 2 64 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM small_1) AS foo; 65 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM small_1) AS foo; 66 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM small_1) AS foo; 67 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM small_1) AS foo; 68 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM small_1) AS foo; 69 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM small_1) AS foo; 70 | 71 | \echo SMALL QUERY 3 72 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_10 GROUP BY col_b) AS foo; 73 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_10 GROUP BY col_b) AS foo; 74 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_10 GROUP BY col_b) AS foo; 75 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_10 GROUP BY col_b) AS foo; 76 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_10 GROUP BY col_b) AS foo; 77 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_10 GROUP BY col_b) AS foo; 78 | 79 | \echo SMALL QUERY 4 80 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_10 GROUP BY col_a) AS foo; 81 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_10 GROUP BY col_a) AS foo; 82 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_10 GROUP BY col_a) AS foo; 83 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_10 GROUP BY col_a) AS foo; 84 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_10 GROUP BY col_a) AS foo; 85 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_10 GROUP BY col_a) AS foo; 86 | 87 | \echo SMALL QUERY 5 88 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_100 GROUP BY col_b) AS foo; 89 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_100 GROUP BY col_b) AS foo; 90 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_100 GROUP BY col_b) AS foo; 91 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_100 GROUP BY col_b) AS foo; 92 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_100 GROUP BY col_b) AS foo; 93 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_100 GROUP BY col_b) AS foo; 94 | 95 | \echo SMALL QUERY 6 96 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_100 GROUP BY col_a) AS foo; 97 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_100 GROUP BY col_a) AS foo; 98 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_100 GROUP BY col_a) AS foo; 99 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_100 GROUP BY col_a) AS foo; 100 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_100 GROUP BY col_a) AS foo; 101 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_100 GROUP BY col_a) AS foo; 102 | 103 | \echo SMALL QUERY 7 104 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_10000 GROUP BY col_b) AS foo; 105 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_10000 GROUP BY col_b) AS foo; 106 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_10000 GROUP BY col_b) AS foo; 107 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_10000 GROUP BY col_b) AS foo; 108 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_10000 GROUP BY col_b) AS foo; 109 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_10000 GROUP BY col_b) AS foo; 110 | 111 | \echo SMALL QUERY 8 112 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_10000 GROUP BY col_a) AS foo; 113 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_10000 GROUP BY col_a) AS foo; 114 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_10000 GROUP BY col_a) AS foo; 115 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_10000 GROUP BY col_a) AS foo; 116 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_10000 GROUP BY col_a) AS foo; 117 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_10000 GROUP BY col_a) AS foo; 118 | 119 | \echo SMALL QUERY 9 120 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_1 GROUP BY col_b) AS foo; 121 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_1 GROUP BY col_b) AS foo; 122 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_1 GROUP BY col_b) AS foo; 123 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_1 GROUP BY col_b) AS foo; 124 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_1 GROUP BY col_b) AS foo; 125 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_1 GROUP BY col_b) AS foo; 126 | 127 | \echo SMALL QUERY 10 128 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_1 GROUP BY col_a) AS foo; 129 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_1 GROUP BY col_a) AS foo; 130 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_1 GROUP BY col_a) AS foo; 131 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_1 GROUP BY col_a) AS foo; 132 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_1 GROUP BY col_a) AS foo; 133 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_1 GROUP BY col_a) AS foo; 134 | 135 | \echo SMALL QUERY 11 136 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_random GROUP BY col_b) AS foo; 137 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_random GROUP BY col_b) AS foo; 138 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_random GROUP BY col_b) AS foo; 139 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_random GROUP BY col_b) AS foo; 140 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_random GROUP BY col_b) AS foo; 141 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_random GROUP BY col_b) AS foo; 142 | 143 | \echo SMALL QUERY 12 144 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_random GROUP BY col_a) AS foo; 145 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_random GROUP BY col_a) AS foo; 146 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_random GROUP BY col_a) AS foo; 147 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_random GROUP BY col_a) AS foo; 148 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_random GROUP BY col_a) AS foo; 149 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_random GROUP BY col_a) AS foo; 150 | 151 | \echo SMALL QUERY 13 152 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM small_random GROUP BY col_b) AS foo; 153 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM small_random GROUP BY col_b) AS foo; 154 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM small_random GROUP BY col_b) AS foo; 155 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM small_random GROUP BY col_b) AS foo; 156 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM small_random GROUP BY col_b) AS foo; 157 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM small_random GROUP BY col_b) AS foo; 158 | 159 | \echo SMALL QUERY 14 160 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_random GROUP BY col_b) AS foo; 161 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_random GROUP BY col_b) AS foo; 162 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_random GROUP BY col_b) AS foo; 163 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_random GROUP BY col_b) AS foo; 164 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_random GROUP BY col_b) AS foo; 165 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_random GROUP BY col_b) AS foo; 166 | 167 | \echo SMALL QUERY 15 168 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_correlated GROUP BY col_b) AS foo; 169 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_correlated GROUP BY col_b) AS foo; 170 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_correlated GROUP BY col_b) AS foo; 171 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_correlated GROUP BY col_b) AS foo; 172 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_correlated GROUP BY col_b) AS foo; 173 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM small_correlated GROUP BY col_b) AS foo; 174 | 175 | \echo SMALL QUERY 16 176 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_correlated GROUP BY col_a) AS foo; 177 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_correlated GROUP BY col_a) AS foo; 178 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_correlated GROUP BY col_a) AS foo; 179 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_correlated GROUP BY col_a) AS foo; 180 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_correlated GROUP BY col_a) AS foo; 181 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM small_correlated GROUP BY col_a) AS foo; 182 | 183 | 184 | \echo MEDIUM QUERY 1 185 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM medium_1) AS foo; 186 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM medium_1) AS foo; 187 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM medium_1) AS foo; 188 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM medium_1) AS foo; 189 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM medium_1) AS foo; 190 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM medium_1) AS foo; 191 | 192 | \echo MEDIUM QUERY 2 193 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM medium_1) AS foo; 194 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM medium_1) AS foo; 195 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM medium_1) AS foo; 196 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM medium_1) AS foo; 197 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM medium_1) AS foo; 198 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM medium_1) AS foo; 199 | 200 | \echo MEDIUM QUERY 3 201 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_10 GROUP BY col_b) AS foo; 202 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_10 GROUP BY col_b) AS foo; 203 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_10 GROUP BY col_b) AS foo; 204 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_10 GROUP BY col_b) AS foo; 205 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_10 GROUP BY col_b) AS foo; 206 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_10 GROUP BY col_b) AS foo; 207 | 208 | \echo MEDIUM QUERY 4 209 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_10 GROUP BY col_a) AS foo; 210 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_10 GROUP BY col_a) AS foo; 211 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_10 GROUP BY col_a) AS foo; 212 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_10 GROUP BY col_a) AS foo; 213 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_10 GROUP BY col_a) AS foo; 214 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_10 GROUP BY col_a) AS foo; 215 | 216 | \echo MEDIUM QUERY 5 217 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_100 GROUP BY col_b) AS foo; 218 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_100 GROUP BY col_b) AS foo; 219 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_100 GROUP BY col_b) AS foo; 220 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_100 GROUP BY col_b) AS foo; 221 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_100 GROUP BY col_b) AS foo; 222 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_100 GROUP BY col_b) AS foo; 223 | 224 | \echo MEDIUM QUERY 6 225 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_100 GROUP BY col_a) AS foo; 226 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_100 GROUP BY col_a) AS foo; 227 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_100 GROUP BY col_a) AS foo; 228 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_100 GROUP BY col_a) AS foo; 229 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_100 GROUP BY col_a) AS foo; 230 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_100 GROUP BY col_a) AS foo; 231 | 232 | \echo MEDIUM QUERY 7 233 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_10000 GROUP BY col_b) AS foo; 234 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_10000 GROUP BY col_b) AS foo; 235 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_10000 GROUP BY col_b) AS foo; 236 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_10000 GROUP BY col_b) AS foo; 237 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_10000 GROUP BY col_b) AS foo; 238 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_10000 GROUP BY col_b) AS foo; 239 | 240 | \echo MEDIUM QUERY 8 241 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_10000 GROUP BY col_a) AS foo; 242 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_10000 GROUP BY col_a) AS foo; 243 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_10000 GROUP BY col_a) AS foo; 244 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_10000 GROUP BY col_a) AS foo; 245 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_10000 GROUP BY col_a) AS foo; 246 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_10000 GROUP BY col_a) AS foo; 247 | 248 | \echo MEDIUM QUERY 9 249 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_1 GROUP BY col_b) AS foo; 250 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_1 GROUP BY col_b) AS foo; 251 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_1 GROUP BY col_b) AS foo; 252 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_1 GROUP BY col_b) AS foo; 253 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_1 GROUP BY col_b) AS foo; 254 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_1 GROUP BY col_b) AS foo; 255 | 256 | \echo MEDIUM QUERY 10 257 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_1 GROUP BY col_a) AS foo; 258 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_1 GROUP BY col_a) AS foo; 259 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_1 GROUP BY col_a) AS foo; 260 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_1 GROUP BY col_a) AS foo; 261 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_1 GROUP BY col_a) AS foo; 262 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_1 GROUP BY col_a) AS foo; 263 | 264 | \echo MEDIUM QUERY 11 265 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 266 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 267 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 268 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 269 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 270 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 271 | 272 | \echo MEDIUM QUERY 12 273 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_random GROUP BY col_a) AS foo; 274 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_random GROUP BY col_a) AS foo; 275 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_random GROUP BY col_a) AS foo; 276 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_random GROUP BY col_a) AS foo; 277 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_random GROUP BY col_a) AS foo; 278 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_random GROUP BY col_a) AS foo; 279 | 280 | \echo MEDIUM QUERY 13 281 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM medium_random GROUP BY col_b) AS foo; 282 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM medium_random GROUP BY col_b) AS foo; 283 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM medium_random GROUP BY col_b) AS foo; 284 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM medium_random GROUP BY col_b) AS foo; 285 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM medium_random GROUP BY col_b) AS foo; 286 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM medium_random GROUP BY col_b) AS foo; 287 | 288 | \echo MEDIUM QUERY 14 289 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 290 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 291 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 292 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 293 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 294 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 295 | 296 | \echo MEDIUM QUERY 15 297 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_correlated GROUP BY col_b) AS foo; 298 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_correlated GROUP BY col_b) AS foo; 299 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_correlated GROUP BY col_b) AS foo; 300 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_correlated GROUP BY col_b) AS foo; 301 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_correlated GROUP BY col_b) AS foo; 302 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM medium_correlated GROUP BY col_b) AS foo; 303 | 304 | \echo MEDIUM QUERY 16 305 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_correlated GROUP BY col_a) AS foo; 306 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_correlated GROUP BY col_a) AS foo; 307 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_correlated GROUP BY col_a) AS foo; 308 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_correlated GROUP BY col_a) AS foo; 309 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_correlated GROUP BY col_a) AS foo; 310 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM medium_correlated GROUP BY col_a) AS foo; 311 | 312 | 313 | 314 | \echo LARGE QUERY 1 315 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM large_1) AS foo; 316 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM large_1) AS foo; 317 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM large_1) AS foo; 318 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM large_1) AS foo; 319 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM large_1) AS foo; 320 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_a) AS b FROM large_1) AS foo; 321 | 322 | \echo LARGE QUERY 2 323 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM large_1) AS foo; 324 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM large_1) AS foo; 325 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM large_1) AS foo; 326 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM large_1) AS foo; 327 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM large_1) AS foo; 328 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT(DISTINCT col_b) AS b FROM large_1) AS foo; 329 | 330 | \echo LARGE QUERY 3 331 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_10 GROUP BY col_b) AS foo; 332 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_10 GROUP BY col_b) AS foo; 333 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_10 GROUP BY col_b) AS foo; 334 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_10 GROUP BY col_b) AS foo; 335 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_10 GROUP BY col_b) AS foo; 336 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_10 GROUP BY col_b) AS foo; 337 | 338 | \echo LARGE QUERY 4 339 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_10 GROUP BY col_a) AS foo; 340 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_10 GROUP BY col_a) AS foo; 341 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_10 GROUP BY col_a) AS foo; 342 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_10 GROUP BY col_a) AS foo; 343 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_10 GROUP BY col_a) AS foo; 344 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_10 GROUP BY col_a) AS foo; 345 | 346 | \echo LARGE QUERY 5 347 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_100 GROUP BY col_b) AS foo; 348 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_100 GROUP BY col_b) AS foo; 349 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_100 GROUP BY col_b) AS foo; 350 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_100 GROUP BY col_b) AS foo; 351 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_100 GROUP BY col_b) AS foo; 352 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_100 GROUP BY col_b) AS foo; 353 | 354 | \echo LARGE QUERY 6 355 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_100 GROUP BY col_a) AS foo; 356 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_100 GROUP BY col_a) AS foo; 357 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_100 GROUP BY col_a) AS foo; 358 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_100 GROUP BY col_a) AS foo; 359 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_100 GROUP BY col_a) AS foo; 360 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_100 GROUP BY col_a) AS foo; 361 | 362 | \echo LARGE QUERY 7 363 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_10000 GROUP BY col_b) AS foo; 364 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_10000 GROUP BY col_b) AS foo; 365 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_10000 GROUP BY col_b) AS foo; 366 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_10000 GROUP BY col_b) AS foo; 367 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_10000 GROUP BY col_b) AS foo; 368 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_10000 GROUP BY col_b) AS foo; 369 | 370 | \echo LARGE QUERY 8 371 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_10000 GROUP BY col_a) AS foo; 372 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_10000 GROUP BY col_a) AS foo; 373 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_10000 GROUP BY col_a) AS foo; 374 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_10000 GROUP BY col_a) AS foo; 375 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_10000 GROUP BY col_a) AS foo; 376 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_10000 GROUP BY col_a) AS foo; 377 | 378 | \echo LARGE QUERY 9 379 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_1 GROUP BY col_b) AS foo; 380 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_1 GROUP BY col_b) AS foo; 381 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_1 GROUP BY col_b) AS foo; 382 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_1 GROUP BY col_b) AS foo; 383 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_1 GROUP BY col_b) AS foo; 384 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_1 GROUP BY col_b) AS foo; 385 | 386 | \echo LARGE QUERY 10 387 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_1 GROUP BY col_a) AS foo; 388 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_1 GROUP BY col_a) AS foo; 389 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_1 GROUP BY col_a) AS foo; 390 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_1 GROUP BY col_a) AS foo; 391 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_1 GROUP BY col_a) AS foo; 392 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_1 GROUP BY col_a) AS foo; 393 | 394 | \echo LARGE QUERY 11 395 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_random GROUP BY col_b) AS foo; 396 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_random GROUP BY col_b) AS foo; 397 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_random GROUP BY col_b) AS foo; 398 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_random GROUP BY col_b) AS foo; 399 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_random GROUP BY col_b) AS foo; 400 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_random GROUP BY col_b) AS foo; 401 | 402 | \echo LARGE QUERY 12 403 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_random GROUP BY col_a) AS foo; 404 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_random GROUP BY col_a) AS foo; 405 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_random GROUP BY col_a) AS foo; 406 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_random GROUP BY col_a) AS foo; 407 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_random GROUP BY col_a) AS foo; 408 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_random GROUP BY col_a) AS foo; 409 | 410 | \echo LARGE QUERY 13 411 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM large_random GROUP BY col_b) AS foo; 412 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM large_random GROUP BY col_b) AS foo; 413 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM large_random GROUP BY col_b) AS foo; 414 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM large_random GROUP BY col_b) AS foo; 415 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM large_random GROUP BY col_b) AS foo; 416 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_c) AS b FROM large_random GROUP BY col_b) AS foo; 417 | 418 | \echo LARGE QUERY 14 419 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_random GROUP BY col_b) AS foo; 420 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_random GROUP BY col_b) AS foo; 421 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_random GROUP BY col_b) AS foo; 422 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_random GROUP BY col_b) AS foo; 423 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_random GROUP BY col_b) AS foo; 424 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_random GROUP BY col_b) AS foo; 425 | 426 | \echo LARGE QUERY 15 427 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_correlated GROUP BY col_b) AS foo; 428 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_correlated GROUP BY col_b) AS foo; 429 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_correlated GROUP BY col_b) AS foo; 430 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_correlated GROUP BY col_b) AS foo; 431 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_correlated GROUP BY col_b) AS foo; 432 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT(DISTINCT col_a) AS b FROM large_correlated GROUP BY col_b) AS foo; 433 | 434 | \echo LARGE QUERY 16 435 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_correlated GROUP BY col_a) AS foo; 436 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_correlated GROUP BY col_a) AS foo; 437 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_correlated GROUP BY col_a) AS foo; 438 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_correlated GROUP BY col_a) AS foo; 439 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_correlated GROUP BY col_a) AS foo; 440 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT(DISTINCT col_b) AS b FROM large_correlated GROUP BY col_a) AS foo; 441 | -------------------------------------------------------------------------------- /benchmark/bench-count-distinct.sql: -------------------------------------------------------------------------------- 1 | \timing off 2 | 3 | EXPLAIN SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM small_1) AS foo; 4 | EXPLAIN SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM small_1) AS foo; 5 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_10 GROUP BY col_b) AS foo; 6 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_10 GROUP BY col_a) AS foo; 7 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_100 GROUP BY col_b) AS foo; 8 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_100 GROUP BY col_a) AS foo; 9 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_10000 GROUP BY col_b) AS foo; 10 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_10000 GROUP BY col_a) AS foo; 11 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_1 GROUP BY col_b) AS foo; 12 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_1 GROUP BY col_a) AS foo; 13 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_random GROUP BY col_b) AS foo; 14 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_random GROUP BY col_a) AS foo; 15 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM small_random GROUP BY col_b) AS foo; 16 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_random GROUP BY col_b) AS foo; 17 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_correlated GROUP BY col_b) AS foo; 18 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_correlated GROUP BY col_a) AS foo; 19 | 20 | EXPLAIN SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM medium_1) AS foo; 21 | EXPLAIN SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM medium_1) AS foo; 22 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_10 GROUP BY col_b) AS foo; 23 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_10 GROUP BY col_a) AS foo; 24 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_100 GROUP BY col_b) AS foo; 25 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_100 GROUP BY col_a) AS foo; 26 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_10000 GROUP BY col_b) AS foo; 27 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_10000 GROUP BY col_a) AS foo; 28 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_1 GROUP BY col_b) AS foo; 29 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_1 GROUP BY col_a) AS foo; 30 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 31 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_random GROUP BY col_a) AS foo; 32 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM medium_random GROUP BY col_b) AS foo; 33 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 34 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_correlated GROUP BY col_b) AS foo; 35 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_correlated GROUP BY col_a) AS foo; 36 | 37 | EXPLAIN SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM large_1) AS foo; 38 | EXPLAIN SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM large_1) AS foo; 39 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_10 GROUP BY col_b) AS foo; 40 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_10 GROUP BY col_a) AS foo; 41 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_100 GROUP BY col_b) AS foo; 42 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_100 GROUP BY col_a) AS foo; 43 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_10000 GROUP BY col_b) AS foo; 44 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_10000 GROUP BY col_a) AS foo; 45 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_1 GROUP BY col_b) AS foo; 46 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_1 GROUP BY col_a) AS foo; 47 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_random GROUP BY col_b) AS foo; 48 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM large_random GROUP BY col_b) AS foo; 49 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_random GROUP BY col_b) AS foo; 50 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_correlated GROUP BY col_b) AS foo; 51 | EXPLAIN SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_correlated GROUP BY col_a) AS foo; 52 | 53 | \timing on 54 | 55 | \echo SMALL QUERY 1 56 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM small_1) AS foo; 57 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM small_1) AS foo; 58 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM small_1) AS foo; 59 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM small_1) AS foo; 60 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM small_1) AS foo; 61 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM small_1) AS foo; 62 | 63 | \echo SMALL QUERY 2 64 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM small_1) AS foo; 65 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM small_1) AS foo; 66 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM small_1) AS foo; 67 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM small_1) AS foo; 68 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM small_1) AS foo; 69 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM small_1) AS foo; 70 | 71 | \echo SMALL QUERY 3 72 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_10 GROUP BY col_b) AS foo; 73 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_10 GROUP BY col_b) AS foo; 74 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_10 GROUP BY col_b) AS foo; 75 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_10 GROUP BY col_b) AS foo; 76 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_10 GROUP BY col_b) AS foo; 77 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_10 GROUP BY col_b) AS foo; 78 | 79 | \echo SMALL QUERY 4 80 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_10 GROUP BY col_a) AS foo; 81 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_10 GROUP BY col_a) AS foo; 82 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_10 GROUP BY col_a) AS foo; 83 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_10 GROUP BY col_a) AS foo; 84 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_10 GROUP BY col_a) AS foo; 85 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_10 GROUP BY col_a) AS foo; 86 | 87 | \echo SMALL QUERY 5 88 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_100 GROUP BY col_b) AS foo; 89 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_100 GROUP BY col_b) AS foo; 90 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_100 GROUP BY col_b) AS foo; 91 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_100 GROUP BY col_b) AS foo; 92 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_100 GROUP BY col_b) AS foo; 93 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_100 GROUP BY col_b) AS foo; 94 | 95 | \echo SMALL QUERY 6 96 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_100 GROUP BY col_a) AS foo; 97 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_100 GROUP BY col_a) AS foo; 98 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_100 GROUP BY col_a) AS foo; 99 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_100 GROUP BY col_a) AS foo; 100 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_100 GROUP BY col_a) AS foo; 101 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_100 GROUP BY col_a) AS foo; 102 | 103 | \echo SMALL QUERY 7 104 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_10000 GROUP BY col_b) AS foo; 105 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_10000 GROUP BY col_b) AS foo; 106 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_10000 GROUP BY col_b) AS foo; 107 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_10000 GROUP BY col_b) AS foo; 108 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_10000 GROUP BY col_b) AS foo; 109 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_10000 GROUP BY col_b) AS foo; 110 | 111 | \echo SMALL QUERY 8 112 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_10000 GROUP BY col_a) AS foo; 113 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_10000 GROUP BY col_a) AS foo; 114 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_10000 GROUP BY col_a) AS foo; 115 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_10000 GROUP BY col_a) AS foo; 116 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_10000 GROUP BY col_a) AS foo; 117 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_10000 GROUP BY col_a) AS foo; 118 | 119 | \echo SMALL QUERY 9 120 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_1 GROUP BY col_b) AS foo; 121 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_1 GROUP BY col_b) AS foo; 122 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_1 GROUP BY col_b) AS foo; 123 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_1 GROUP BY col_b) AS foo; 124 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_1 GROUP BY col_b) AS foo; 125 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_1 GROUP BY col_b) AS foo; 126 | 127 | \echo SMALL QUERY 10 128 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_1 GROUP BY col_a) AS foo; 129 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_1 GROUP BY col_a) AS foo; 130 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_1 GROUP BY col_a) AS foo; 131 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_1 GROUP BY col_a) AS foo; 132 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_1 GROUP BY col_a) AS foo; 133 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_1 GROUP BY col_a) AS foo; 134 | 135 | \echo SMALL QUERY 11 136 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_random GROUP BY col_b) AS foo; 137 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_random GROUP BY col_b) AS foo; 138 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_random GROUP BY col_b) AS foo; 139 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_random GROUP BY col_b) AS foo; 140 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_random GROUP BY col_b) AS foo; 141 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_random GROUP BY col_b) AS foo; 142 | 143 | \echo SMALL QUERY 12 144 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_random GROUP BY col_a) AS foo; 145 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_random GROUP BY col_a) AS foo; 146 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_random GROUP BY col_a) AS foo; 147 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_random GROUP BY col_a) AS foo; 148 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_random GROUP BY col_a) AS foo; 149 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_random GROUP BY col_a) AS foo; 150 | 151 | \echo SMALL QUERY 13 152 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM small_random GROUP BY col_b) AS foo; 153 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM small_random GROUP BY col_b) AS foo; 154 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM small_random GROUP BY col_b) AS foo; 155 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM small_random GROUP BY col_b) AS foo; 156 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM small_random GROUP BY col_b) AS foo; 157 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM small_random GROUP BY col_b) AS foo; 158 | 159 | \echo SMALL QUERY 14 160 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_random GROUP BY col_b) AS foo; 161 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_random GROUP BY col_b) AS foo; 162 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_random GROUP BY col_b) AS foo; 163 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_random GROUP BY col_b) AS foo; 164 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_random GROUP BY col_b) AS foo; 165 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_random GROUP BY col_b) AS foo; 166 | 167 | \echo SMALL QUERY 15 168 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_correlated GROUP BY col_b) AS foo; 169 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_correlated GROUP BY col_b) AS foo; 170 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_correlated GROUP BY col_b) AS foo; 171 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_correlated GROUP BY col_b) AS foo; 172 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_correlated GROUP BY col_b) AS foo; 173 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM small_correlated GROUP BY col_b) AS foo; 174 | 175 | \echo SMALL QUERY 16 176 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_correlated GROUP BY col_a) AS foo; 177 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_correlated GROUP BY col_a) AS foo; 178 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_correlated GROUP BY col_a) AS foo; 179 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_correlated GROUP BY col_a) AS foo; 180 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_correlated GROUP BY col_a) AS foo; 181 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM small_correlated GROUP BY col_a) AS foo; 182 | 183 | 184 | \echo MEDIUM QUERY 1 185 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM medium_1) AS foo; 186 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM medium_1) AS foo; 187 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM medium_1) AS foo; 188 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM medium_1) AS foo; 189 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM medium_1) AS foo; 190 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM medium_1) AS foo; 191 | 192 | \echo MEDIUM QUERY 2 193 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM medium_1) AS foo; 194 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM medium_1) AS foo; 195 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM medium_1) AS foo; 196 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM medium_1) AS foo; 197 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM medium_1) AS foo; 198 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM medium_1) AS foo; 199 | 200 | \echo MEDIUM QUERY 3 201 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_10 GROUP BY col_b) AS foo; 202 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_10 GROUP BY col_b) AS foo; 203 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_10 GROUP BY col_b) AS foo; 204 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_10 GROUP BY col_b) AS foo; 205 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_10 GROUP BY col_b) AS foo; 206 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_10 GROUP BY col_b) AS foo; 207 | 208 | \echo MEDIUM QUERY 4 209 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_10 GROUP BY col_a) AS foo; 210 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_10 GROUP BY col_a) AS foo; 211 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_10 GROUP BY col_a) AS foo; 212 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_10 GROUP BY col_a) AS foo; 213 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_10 GROUP BY col_a) AS foo; 214 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_10 GROUP BY col_a) AS foo; 215 | 216 | \echo MEDIUM QUERY 5 217 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_100 GROUP BY col_b) AS foo; 218 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_100 GROUP BY col_b) AS foo; 219 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_100 GROUP BY col_b) AS foo; 220 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_100 GROUP BY col_b) AS foo; 221 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_100 GROUP BY col_b) AS foo; 222 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_100 GROUP BY col_b) AS foo; 223 | 224 | \echo MEDIUM QUERY 6 225 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_100 GROUP BY col_a) AS foo; 226 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_100 GROUP BY col_a) AS foo; 227 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_100 GROUP BY col_a) AS foo; 228 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_100 GROUP BY col_a) AS foo; 229 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_100 GROUP BY col_a) AS foo; 230 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_100 GROUP BY col_a) AS foo; 231 | 232 | \echo MEDIUM QUERY 7 233 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_10000 GROUP BY col_b) AS foo; 234 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_10000 GROUP BY col_b) AS foo; 235 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_10000 GROUP BY col_b) AS foo; 236 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_10000 GROUP BY col_b) AS foo; 237 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_10000 GROUP BY col_b) AS foo; 238 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_10000 GROUP BY col_b) AS foo; 239 | 240 | \echo MEDIUM QUERY 8 241 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_10000 GROUP BY col_a) AS foo; 242 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_10000 GROUP BY col_a) AS foo; 243 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_10000 GROUP BY col_a) AS foo; 244 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_10000 GROUP BY col_a) AS foo; 245 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_10000 GROUP BY col_a) AS foo; 246 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_10000 GROUP BY col_a) AS foo; 247 | 248 | \echo MEDIUM QUERY 9 249 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_1 GROUP BY col_b) AS foo; 250 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_1 GROUP BY col_b) AS foo; 251 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_1 GROUP BY col_b) AS foo; 252 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_1 GROUP BY col_b) AS foo; 253 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_1 GROUP BY col_b) AS foo; 254 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_1 GROUP BY col_b) AS foo; 255 | 256 | \echo MEDIUM QUERY 10 257 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_1 GROUP BY col_a) AS foo; 258 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_1 GROUP BY col_a) AS foo; 259 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_1 GROUP BY col_a) AS foo; 260 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_1 GROUP BY col_a) AS foo; 261 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_1 GROUP BY col_a) AS foo; 262 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_1 GROUP BY col_a) AS foo; 263 | 264 | \echo MEDIUM QUERY 11 265 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 266 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 267 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 268 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 269 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 270 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 271 | 272 | \echo MEDIUM QUERY 12 273 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_random GROUP BY col_a) AS foo; 274 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_random GROUP BY col_a) AS foo; 275 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_random GROUP BY col_a) AS foo; 276 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_random GROUP BY col_a) AS foo; 277 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_random GROUP BY col_a) AS foo; 278 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_random GROUP BY col_a) AS foo; 279 | 280 | \echo MEDIUM QUERY 13 281 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM medium_random GROUP BY col_b) AS foo; 282 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM medium_random GROUP BY col_b) AS foo; 283 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM medium_random GROUP BY col_b) AS foo; 284 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM medium_random GROUP BY col_b) AS foo; 285 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM medium_random GROUP BY col_b) AS foo; 286 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM medium_random GROUP BY col_b) AS foo; 287 | 288 | \echo MEDIUM QUERY 14 289 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 290 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 291 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 292 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 293 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 294 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_random GROUP BY col_b) AS foo; 295 | 296 | \echo MEDIUM QUERY 15 297 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_correlated GROUP BY col_b) AS foo; 298 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_correlated GROUP BY col_b) AS foo; 299 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_correlated GROUP BY col_b) AS foo; 300 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_correlated GROUP BY col_b) AS foo; 301 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_correlated GROUP BY col_b) AS foo; 302 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM medium_correlated GROUP BY col_b) AS foo; 303 | 304 | \echo MEDIUM QUERY 16 305 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_correlated GROUP BY col_a) AS foo; 306 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_correlated GROUP BY col_a) AS foo; 307 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_correlated GROUP BY col_a) AS foo; 308 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_correlated GROUP BY col_a) AS foo; 309 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_correlated GROUP BY col_a) AS foo; 310 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM medium_correlated GROUP BY col_a) AS foo; 311 | 312 | 313 | 314 | \echo LARGE QUERY 1 315 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM large_1) AS foo; 316 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM large_1) AS foo; 317 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM large_1) AS foo; 318 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM large_1) AS foo; 319 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM large_1) AS foo; 320 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_a) AS b FROM large_1) AS foo; 321 | 322 | \echo LARGE QUERY 2 323 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM large_1) AS foo; 324 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM large_1) AS foo; 325 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM large_1) AS foo; 326 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM large_1) AS foo; 327 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM large_1) AS foo; 328 | SELECT COUNT(*), AVG(b), SUM(b) FROM (SELECT COUNT_DISTINCT(col_b) AS b FROM large_1) AS foo; 329 | 330 | \echo LARGE QUERY 3 331 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_10 GROUP BY col_b) AS foo; 332 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_10 GROUP BY col_b) AS foo; 333 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_10 GROUP BY col_b) AS foo; 334 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_10 GROUP BY col_b) AS foo; 335 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_10 GROUP BY col_b) AS foo; 336 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_10 GROUP BY col_b) AS foo; 337 | 338 | \echo LARGE QUERY 4 339 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_10 GROUP BY col_a) AS foo; 340 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_10 GROUP BY col_a) AS foo; 341 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_10 GROUP BY col_a) AS foo; 342 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_10 GROUP BY col_a) AS foo; 343 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_10 GROUP BY col_a) AS foo; 344 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_10 GROUP BY col_a) AS foo; 345 | 346 | \echo LARGE QUERY 5 347 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_100 GROUP BY col_b) AS foo; 348 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_100 GROUP BY col_b) AS foo; 349 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_100 GROUP BY col_b) AS foo; 350 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_100 GROUP BY col_b) AS foo; 351 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_100 GROUP BY col_b) AS foo; 352 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_100 GROUP BY col_b) AS foo; 353 | 354 | \echo LARGE QUERY 6 355 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_100 GROUP BY col_a) AS foo; 356 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_100 GROUP BY col_a) AS foo; 357 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_100 GROUP BY col_a) AS foo; 358 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_100 GROUP BY col_a) AS foo; 359 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_100 GROUP BY col_a) AS foo; 360 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_100 GROUP BY col_a) AS foo; 361 | 362 | \echo LARGE QUERY 7 363 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_10000 GROUP BY col_b) AS foo; 364 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_10000 GROUP BY col_b) AS foo; 365 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_10000 GROUP BY col_b) AS foo; 366 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_10000 GROUP BY col_b) AS foo; 367 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_10000 GROUP BY col_b) AS foo; 368 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_10000 GROUP BY col_b) AS foo; 369 | 370 | \echo LARGE QUERY 8 371 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_10000 GROUP BY col_a) AS foo; 372 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_10000 GROUP BY col_a) AS foo; 373 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_10000 GROUP BY col_a) AS foo; 374 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_10000 GROUP BY col_a) AS foo; 375 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_10000 GROUP BY col_a) AS foo; 376 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_10000 GROUP BY col_a) AS foo; 377 | 378 | \echo LARGE QUERY 9 379 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_1 GROUP BY col_b) AS foo; 380 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_1 GROUP BY col_b) AS foo; 381 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_1 GROUP BY col_b) AS foo; 382 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_1 GROUP BY col_b) AS foo; 383 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_1 GROUP BY col_b) AS foo; 384 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_1 GROUP BY col_b) AS foo; 385 | 386 | \echo LARGE QUERY 10 387 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_1 GROUP BY col_a) AS foo; 388 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_1 GROUP BY col_a) AS foo; 389 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_1 GROUP BY col_a) AS foo; 390 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_1 GROUP BY col_a) AS foo; 391 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_1 GROUP BY col_a) AS foo; 392 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_1 GROUP BY col_a) AS foo; 393 | 394 | \echo LARGE QUERY 11 395 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_random GROUP BY col_b) AS foo; 396 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_random GROUP BY col_b) AS foo; 397 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_random GROUP BY col_b) AS foo; 398 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_random GROUP BY col_b) AS foo; 399 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_random GROUP BY col_b) AS foo; 400 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_random GROUP BY col_b) AS foo; 401 | 402 | \echo LARGE QUERY 12 403 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_random GROUP BY col_a) AS foo; 404 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_random GROUP BY col_a) AS foo; 405 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_random GROUP BY col_a) AS foo; 406 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_random GROUP BY col_a) AS foo; 407 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_random GROUP BY col_a) AS foo; 408 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_random GROUP BY col_a) AS foo; 409 | 410 | \echo LARGE QUERY 13 411 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM large_random GROUP BY col_b) AS foo; 412 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM large_random GROUP BY col_b) AS foo; 413 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM large_random GROUP BY col_b) AS foo; 414 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM large_random GROUP BY col_b) AS foo; 415 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM large_random GROUP BY col_b) AS foo; 416 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_c) AS b FROM large_random GROUP BY col_b) AS foo; 417 | 418 | \echo LARGE QUERY 14 419 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_random GROUP BY col_b) AS foo; 420 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_random GROUP BY col_b) AS foo; 421 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_random GROUP BY col_b) AS foo; 422 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_random GROUP BY col_b) AS foo; 423 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_random GROUP BY col_b) AS foo; 424 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_random GROUP BY col_b) AS foo; 425 | 426 | \echo LARGE QUERY 15 427 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_correlated GROUP BY col_b) AS foo; 428 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_correlated GROUP BY col_b) AS foo; 429 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_correlated GROUP BY col_b) AS foo; 430 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_correlated GROUP BY col_b) AS foo; 431 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_correlated GROUP BY col_b) AS foo; 432 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_b AS a, COUNT_DISTINCT(col_a) AS b FROM large_correlated GROUP BY col_b) AS foo; 433 | 434 | \echo LARGE QUERY 16 435 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_correlated GROUP BY col_a) AS foo; 436 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_correlated GROUP BY col_a) AS foo; 437 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_correlated GROUP BY col_a) AS foo; 438 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_correlated GROUP BY col_a) AS foo; 439 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_correlated GROUP BY col_a) AS foo; 440 | SELECT COUNT(*), COUNT(a), AVG(b), SUM(b) FROM (SELECT col_a AS a, COUNT_DISTINCT(col_b) AS b FROM large_correlated GROUP BY col_a) AS foo; 441 | --------------------------------------------------------------------------------