From adb31561dde97ee995d2c72c547be473f463a8eb Mon Sep 17 00:00:00 2001 From: Jordan Tigani Date: Sat, 23 Nov 2024 17:41:01 -0800 Subject: [PATCH 1/6] clickbench for pgduckdb-motherduck --- pgduckdb-motherduck/benchmark.sh | 55 ++++++++++++++++++++ pgduckdb-motherduck/create.sql | 4 ++ pgduckdb-motherduck/load.sh | 22 ++++++++ pgduckdb-motherduck/queries.sql | 43 ++++++++++++++++ pgduckdb-motherduck/results/motherduck.json | 57 +++++++++++++++++++++ pgduckdb-motherduck/run.sh | 20 ++++++++ 6 files changed, 201 insertions(+) create mode 100755 pgduckdb-motherduck/benchmark.sh create mode 100644 pgduckdb-motherduck/create.sql create mode 100755 pgduckdb-motherduck/load.sh create mode 100644 pgduckdb-motherduck/queries.sql create mode 100644 pgduckdb-motherduck/results/motherduck.json create mode 100755 pgduckdb-motherduck/run.sh diff --git a/pgduckdb-motherduck/benchmark.sh b/pgduckdb-motherduck/benchmark.sh new file mode 100755 index 000000000..bdfd8d1dc --- /dev/null +++ b/pgduckdb-motherduck/benchmark.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +set -ex + +#sudo apt-get update +#sudo apt-get install -y docker.io +#sudo apt-get install -y postgresql-client + +# Ubuntu: +# snap install docker +# sudo apt install posgresql-client-common +# sudo apt install postgresql-client-16 + +USE_MOTHERDUCK=1 + +CONNECTION=postgres://postgres:duckdb@172.17.0.2:5432/postgres +# CONNECTION=postgres://postgres:duckdb@172.17.0.2:5432/postgres + +if [[ $USE_MOTHERDUCK == 1 ]]; then +# Sign up for MotherDuck. Get a motherduck token. +# export MOTHERDUCK_TOKEN=... {from the MotherDuck UI} +# create a database called pgclick in the motherduck UI or duckdb cli +# you will also need to create dummy table in that database.For example, run +# create table pgclick.foo as SELECT 1 as a; +# (https://github.com/duckdb/pg_duckdb/issues/450) + +sudo docker run -d --name pgduck -e POSTGRES_PASSWORD=duckdb -e MOTHERDUCK_TOKEN=$MOTHERDUCK_TOKEN pgduckdb/pgduckdb:16-main -c duckdb.motherduck_enabled=true + +else + +wget --no-verbose --continue https://datasets.clickhouse.com/hits_compatible/athena/hits.parquet +sudo docker run -d --name pgduck -p 5432:5432 -e POSTGRES_PASSWORD=duckdb -v ./hits.parquet:/tmp/hits.parquet pgduckdb/pgduckdb:16-main + +fi + +# Give postgres time to start running +sleep 5 + +./load.sh 2>&1 | tee load_log.txt +./run.sh 2>&1 | tee log.txt + +if [[ $USE_MOTHERDUCK == 1 ]]; then +# Go to motherduck UI and execute: +# SELECT database_size FROM pragma_database_size() +# WHERE database_name = 'pgclick' +echo 'Fetch database size from the MotherDuck UI with `SELECT database_size FROM pragma_database_size() + WHERE database_name = 'pgclick'`' + +else +sudo docker exec -it pgduck du -bcs /var/lib/postgresql/data /tmp/hits.parquet +fi + +cat log.txt | grep -oP 'Time: \d+\.\d+ ms' | sed -r -e 's/Time: ([0-9]+\.[0-9]+) ms/\1/' | + awk '{ if (i % 3 == 0) { printf "[" }; printf $1 / 1000; if (i % 3 != 2) { printf "," } else { print "]," }; ++i; }' + diff --git a/pgduckdb-motherduck/create.sql b/pgduckdb-motherduck/create.sql new file mode 100644 index 000000000..5ae9eef4c --- /dev/null +++ b/pgduckdb-motherduck/create.sql @@ -0,0 +1,4 @@ +create or replace view hits_view as +select WatchID, JavaEnable, Title, GoodEvent, 'epoch'::timestamp + (EventTime || 'second')::interval EventTime, 'epoch'::timestamp + (EventDate || 'day')::interval EventDate, CounterID, ClientIP, RegionID, UserID, CounterClass, OS, UserAgent, URL, Referer, IsRefresh, RefererCategoryID, RefererRegionID, URLCategoryID, URLRegionID, ResolutionWidth, ResolutionHeight, ResolutionDepth, FlashMajor, FlashMinor, FlashMinor2, NetMajor, NetMinor, UserAgentMajor, UserAgentMinor, CookieEnable, JavascriptEnable, IsMobile, MobilePhone, MobilePhoneModel, Params, IPNetworkID, TraficSourceID, SearchEngineID, SearchPhrase, AdvEngineID, IsArtifical, WindowClientWidth, WindowClientHeight, ClientTimeZone, 'epoch'::timestamp + (ClientEventTime || 'second')::interval ClientEventTime, SilverlightVersion1, SilverlightVersion2, SilverlightVersion3, SilverlightVersion4, PageCharset, CodeVersion, IsLink, IsDownload, IsNotBounce, FUniqID, OriginalURL, HID, IsOldCounter, IsEvent, IsParameter, DontCountHits, WithHash, HitColor, 'epoch'::timestamp + (LocalEventTime || 'second')::interval LocalEventTime, Age, Sex, Income, Interests, Robotness, RemoteIP, WindowName, OpenerName, HistoryLength, BrowserLanguage, BrowserCountry, SocialNetwork, SocialAction, HTTPError, SendTiming, DNSTiming, ConnectTiming, ResponseStartTiming, ResponseEndTiming, FetchTiming, SocialSourceNetworkID, SocialSourcePage, ParamPrice, ParamOrderID, ParamCurrency, ParamCurrencyID, OpenstatServiceName, OpenstatCampaignID, OpenstatAdID, OpenstatSourceID, UTMSource, UTMMedium, UTMCampaign, UTMContent, UTMTerm, FromTag, HasGCLID, RefererHash, URLHash, CLID +from read_parquet('REPLACE_PARQUET_FILE') as (WatchID BIGINT, JavaEnable SMALLINT, Title VARCHAR, GoodEvent SMALLINT, EventTime BIGINT, EventDate int, CounterID INTEGER, ClientIP INTEGER, RegionID INTEGER, UserID BIGINT, CounterClass SMALLINT, OS SMALLINT, UserAgent SMALLINT, URL VARCHAR, Referer VARCHAR, IsRefresh SMALLINT, RefererCategoryID SMALLINT, RefererRegionID INTEGER, URLCategoryID SMALLINT, URLRegionID INTEGER, ResolutionWidth SMALLINT, ResolutionHeight SMALLINT, ResolutionDepth SMALLINT, FlashMajor SMALLINT, FlashMinor SMALLINT, FlashMinor2 VARCHAR, NetMajor SMALLINT, NetMinor SMALLINT, UserAgentMajor SMALLINT, UserAgentMinor VARCHAR, CookieEnable SMALLINT, JavascriptEnable SMALLINT, IsMobile SMALLINT, MobilePhone SMALLINT, MobilePhoneModel VARCHAR, Params VARCHAR, IPNetworkID INTEGER, TraficSourceID SMALLINT, SearchEngineID SMALLINT, SearchPhrase VARCHAR, AdvEngineID SMALLINT, IsArtifical SMALLINT, WindowClientWidth SMALLINT, WindowClientHeight SMALLINT, ClientTimeZone SMALLINT, ClientEventTime BIGINT, SilverlightVersion1 SMALLINT, SilverlightVersion2 SMALLINT, SilverlightVersion3 INTEGER, SilverlightVersion4 SMALLINT, PageCharset VARCHAR, CodeVersion INTEGER, IsLink SMALLINT, IsDownload SMALLINT, IsNotBounce SMALLINT, FUniqID BIGINT, OriginalURL VARCHAR, HID INTEGER, IsOldCounter SMALLINT, IsEvent SMALLINT, IsParameter SMALLINT, DontCountHits SMALLINT, WithHash SMALLINT, HitColor VARCHAR, LocalEventTime BIGINT, Age SMALLINT, Sex SMALLINT, Income SMALLINT, Interests SMALLINT, Robotness SMALLINT, RemoteIP INTEGER, WindowName INTEGER, OpenerName INTEGER, HistoryLength SMALLINT, BrowserLanguage VARCHAR, BrowserCountry VARCHAR, SocialNetwork VARCHAR, SocialAction VARCHAR, HTTPError SMALLINT, SendTiming INTEGER, DNSTiming INTEGER, ConnectTiming INTEGER, ResponseStartTiming INTEGER, ResponseEndTiming INTEGER, FetchTiming INTEGER, SocialSourceNetworkID SMALLINT, SocialSourcePage VARCHAR, ParamPrice BIGINT, ParamOrderID VARCHAR, ParamCurrency VARCHAR, ParamCurrencyID SMALLINT, OpenstatServiceName VARCHAR, OpenstatCampaignID VARCHAR, OpenstatAdID VARCHAR, OpenstatSourceID VARCHAR, UTMSource VARCHAR, UTMMedium VARCHAR, UTMCampaign VARCHAR, UTMContent VARCHAR, UTMTerm VARCHAR, FromTag VARCHAR, HasGCLID SMALLINT, RefererHash BIGINT, URLHash BIGINT, CLID INTEGER); +CREATE table REPLACE_DATABASE.hits USING DUCKDB AS SELECT * FROM hits_view; diff --git a/pgduckdb-motherduck/load.sh b/pgduckdb-motherduck/load.sh new file mode 100755 index 000000000..437c5d529 --- /dev/null +++ b/pgduckdb-motherduck/load.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +CONNECTION=postgres://postgres:duckdb@172.17.0.2:5432/postgres +PSQL=psql + +USE_MOTHERDUCK=1 + +if [[ $USE_MOTHERDUCK == 1 ]]; then +DATABASE='ddb$pgclick' +PARQUET_FILE='https:\/\/datasets.clickhouse.com\/hits_compatible\/hits.parquet' +else +DATABASE=temp +PARQUET_FILE='\/tmp\/hits.parquet' +fi + +echo "Loading data" +( + echo "\timing" + cat create.sql | + sed -e "s/REPLACE_DATABASE/$DATABASE/g" -e "s/REPLACE_PARQUET_FILE/$PARQUET_FILE/g" +) | $PSQL $CONNECTION | grep 'Time' + diff --git a/pgduckdb-motherduck/queries.sql b/pgduckdb-motherduck/queries.sql new file mode 100644 index 000000000..31f65fc89 --- /dev/null +++ b/pgduckdb-motherduck/queries.sql @@ -0,0 +1,43 @@ +SELECT COUNT(*) FROM hits; +SELECT COUNT(*) FROM hits WHERE AdvEngineID <> 0; +SELECT SUM(AdvEngineID), COUNT(*), AVG(ResolutionWidth) FROM hits; +SELECT AVG(UserID) FROM hits; +SELECT COUNT(DISTINCT UserID) FROM hits; +SELECT COUNT(DISTINCT SearchPhrase) FROM hits; +SELECT MIN(EventDate), MAX(EventDate) FROM hits; +SELECT AdvEngineID, COUNT(*) FROM hits WHERE AdvEngineID <> 0 GROUP BY AdvEngineID ORDER BY COUNT(*) DESC; +SELECT RegionID, COUNT(DISTINCT UserID) AS u FROM hits GROUP BY RegionID ORDER BY u DESC LIMIT 10; +SELECT RegionID, SUM(AdvEngineID), COUNT(*) AS c, AVG(ResolutionWidth), COUNT(DISTINCT UserID) FROM hits GROUP BY RegionID ORDER BY c DESC LIMIT 10; +SELECT MobilePhoneModel, COUNT(DISTINCT UserID) AS u FROM hits WHERE MobilePhoneModel <> '' GROUP BY MobilePhoneModel ORDER BY u DESC LIMIT 10; +SELECT MobilePhone, MobilePhoneModel, COUNT(DISTINCT UserID) AS u FROM hits WHERE MobilePhoneModel <> '' GROUP BY MobilePhone, MobilePhoneModel ORDER BY u DESC LIMIT 10; +SELECT SearchPhrase, COUNT(*) AS c FROM hits WHERE SearchPhrase <> '' GROUP BY SearchPhrase ORDER BY c DESC LIMIT 10; +SELECT SearchPhrase, COUNT(DISTINCT UserID) AS u FROM hits WHERE SearchPhrase <> '' GROUP BY SearchPhrase ORDER BY u DESC LIMIT 10; +SELECT SearchEngineID, SearchPhrase, COUNT(*) AS c FROM hits WHERE SearchPhrase <> '' GROUP BY SearchEngineID, SearchPhrase ORDER BY c DESC LIMIT 10; +SELECT UserID, COUNT(*) FROM hits GROUP BY UserID ORDER BY COUNT(*) DESC LIMIT 10; +SELECT UserID, SearchPhrase, COUNT(*) FROM hits GROUP BY UserID, SearchPhrase ORDER BY COUNT(*) DESC LIMIT 10; +SELECT UserID, SearchPhrase, COUNT(*) FROM hits GROUP BY UserID, SearchPhrase LIMIT 10; +SELECT UserID, extract(minute FROM EventTime) AS m, SearchPhrase, COUNT(*) FROM hits GROUP BY UserID, m, SearchPhrase ORDER BY COUNT(*) DESC LIMIT 10; +SELECT UserID FROM hits WHERE UserID = 435090932899640449; +SELECT COUNT(*) FROM hits WHERE URL LIKE '%google%'; +SELECT SearchPhrase, MIN(URL), COUNT(*) AS c FROM hits WHERE URL LIKE '%google%' AND SearchPhrase <> '' GROUP BY SearchPhrase ORDER BY c DESC LIMIT 10; +SELECT SearchPhrase, MIN(URL), MIN(Title), COUNT(*) AS c, COUNT(DISTINCT UserID) FROM hits WHERE Title LIKE '%Google%' AND URL NOT LIKE '%.google.%' AND SearchPhrase <> '' GROUP BY SearchPhrase ORDER BY c DESC LIMIT 10; +SELECT * FROM hits WHERE URL LIKE '%google%' ORDER BY EventTime LIMIT 10; +SELECT SearchPhrase FROM hits WHERE SearchPhrase <> '' ORDER BY EventTime LIMIT 10; +SELECT SearchPhrase FROM hits WHERE SearchPhrase <> '' ORDER BY SearchPhrase LIMIT 10; +SELECT SearchPhrase FROM hits WHERE SearchPhrase <> '' ORDER BY EventTime, SearchPhrase LIMIT 10; +SELECT CounterID, AVG(length(URL)) AS l, COUNT(*) AS c FROM hits WHERE URL <> '' GROUP BY CounterID HAVING COUNT(*) > 100000 ORDER BY l DESC LIMIT 25; +SELECT REGEXP_REPLACE(Referer, '^https?://(?:www\.)?([^/]+)/.*$', '\1') AS k, AVG(length(Referer)) AS l, COUNT(*) AS c, MIN(Referer) FROM hits WHERE Referer <> '' GROUP BY k HAVING COUNT(*) > 100000 ORDER BY l DESC LIMIT 25; +SELECT SUM(ResolutionWidth), SUM(ResolutionWidth + 1), SUM(ResolutionWidth + 2), SUM(ResolutionWidth + 3), SUM(ResolutionWidth + 4), SUM(ResolutionWidth + 5), SUM(ResolutionWidth + 6), SUM(ResolutionWidth + 7), SUM(ResolutionWidth + 8), SUM(ResolutionWidth + 9), SUM(ResolutionWidth + 10), SUM(ResolutionWidth + 11), SUM(ResolutionWidth + 12), SUM(ResolutionWidth + 13), SUM(ResolutionWidth + 14), SUM(ResolutionWidth + 15), SUM(ResolutionWidth + 16), SUM(ResolutionWidth + 17), SUM(ResolutionWidth + 18), SUM(ResolutionWidth + 19), SUM(ResolutionWidth + 20), SUM(ResolutionWidth + 21), SUM(ResolutionWidth + 22), SUM(ResolutionWidth + 23), SUM(ResolutionWidth + 24), SUM(ResolutionWidth + 25), SUM(ResolutionWidth + 26), SUM(ResolutionWidth + 27), SUM(ResolutionWidth + 28), SUM(ResolutionWidth + 29), SUM(ResolutionWidth + 30), SUM(ResolutionWidth + 31), SUM(ResolutionWidth + 32), SUM(ResolutionWidth + 33), SUM(ResolutionWidth + 34), SUM(ResolutionWidth + 35), SUM(ResolutionWidth + 36), SUM(ResolutionWidth + 37), SUM(ResolutionWidth + 38), SUM(ResolutionWidth + 39), SUM(ResolutionWidth + 40), SUM(ResolutionWidth + 41), SUM(ResolutionWidth + 42), SUM(ResolutionWidth + 43), SUM(ResolutionWidth + 44), SUM(ResolutionWidth + 45), SUM(ResolutionWidth + 46), SUM(ResolutionWidth + 47), SUM(ResolutionWidth + 48), SUM(ResolutionWidth + 49), SUM(ResolutionWidth + 50), SUM(ResolutionWidth + 51), SUM(ResolutionWidth + 52), SUM(ResolutionWidth + 53), SUM(ResolutionWidth + 54), SUM(ResolutionWidth + 55), SUM(ResolutionWidth + 56), SUM(ResolutionWidth + 57), SUM(ResolutionWidth + 58), SUM(ResolutionWidth + 59), SUM(ResolutionWidth + 60), SUM(ResolutionWidth + 61), SUM(ResolutionWidth + 62), SUM(ResolutionWidth + 63), SUM(ResolutionWidth + 64), SUM(ResolutionWidth + 65), SUM(ResolutionWidth + 66), SUM(ResolutionWidth + 67), SUM(ResolutionWidth + 68), SUM(ResolutionWidth + 69), SUM(ResolutionWidth + 70), SUM(ResolutionWidth + 71), SUM(ResolutionWidth + 72), SUM(ResolutionWidth + 73), SUM(ResolutionWidth + 74), SUM(ResolutionWidth + 75), SUM(ResolutionWidth + 76), SUM(ResolutionWidth + 77), SUM(ResolutionWidth + 78), SUM(ResolutionWidth + 79), SUM(ResolutionWidth + 80), SUM(ResolutionWidth + 81), SUM(ResolutionWidth + 82), SUM(ResolutionWidth + 83), SUM(ResolutionWidth + 84), SUM(ResolutionWidth + 85), SUM(ResolutionWidth + 86), SUM(ResolutionWidth + 87), SUM(ResolutionWidth + 88), SUM(ResolutionWidth + 89) FROM hits; +SELECT SearchEngineID, ClientIP, COUNT(*) AS c, SUM(IsRefresh), AVG(ResolutionWidth) FROM hits WHERE SearchPhrase <> '' GROUP BY SearchEngineID, ClientIP ORDER BY c DESC LIMIT 10; +SELECT WatchID, ClientIP, COUNT(*) AS c, SUM(IsRefresh), AVG(ResolutionWidth) FROM hits WHERE SearchPhrase <> '' GROUP BY WatchID, ClientIP ORDER BY c DESC LIMIT 10; +SELECT WatchID, ClientIP, COUNT(*) AS c, SUM(IsRefresh), AVG(ResolutionWidth) FROM hits GROUP BY WatchID, ClientIP ORDER BY c DESC LIMIT 10; +SELECT URL, COUNT(*) AS c FROM hits GROUP BY URL ORDER BY c DESC LIMIT 10; +SELECT 1, URL, COUNT(*) AS c FROM hits GROUP BY 1, URL ORDER BY c DESC LIMIT 10; +SELECT ClientIP, ClientIP - 1, ClientIP - 2, ClientIP - 3, COUNT(*) AS c FROM hits GROUP BY ClientIP, ClientIP - 1, ClientIP - 2, ClientIP - 3 ORDER BY c DESC LIMIT 10; +SELECT URL, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-01' AND EventDate <= '2013-07-31' AND DontCountHits = 0 AND IsRefresh = 0 AND URL <> '' GROUP BY URL ORDER BY PageViews DESC LIMIT 10; +SELECT Title, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-01' AND EventDate <= '2013-07-31' AND DontCountHits = 0 AND IsRefresh = 0 AND Title <> '' GROUP BY Title ORDER BY PageViews DESC LIMIT 10; +SELECT URL, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-01' AND EventDate <= '2013-07-31' AND IsRefresh = 0 AND IsLink <> 0 AND IsDownload = 0 GROUP BY URL ORDER BY PageViews DESC LIMIT 10 OFFSET 1000; +SELECT TraficSourceID, SearchEngineID, AdvEngineID, CASE WHEN (SearchEngineID = 0 AND AdvEngineID = 0) THEN Referer ELSE '' END AS Src, URL AS Dst, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-01' AND EventDate <= '2013-07-31' AND IsRefresh = 0 GROUP BY TraficSourceID, SearchEngineID, AdvEngineID, Src, Dst ORDER BY PageViews DESC LIMIT 10 OFFSET 1000; +SELECT URLHash, EventDate, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-01' AND EventDate <= '2013-07-31' AND IsRefresh = 0 AND TraficSourceID IN (-1, 6) AND RefererHash = 3594120000172545465 GROUP BY URLHash, EventDate ORDER BY PageViews DESC LIMIT 10 OFFSET 100; +SELECT WindowClientWidth, WindowClientHeight, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-01' AND EventDate <= '2013-07-31' AND IsRefresh = 0 AND DontCountHits = 0 AND URLHash = 2868770270353813622 GROUP BY WindowClientWidth, WindowClientHeight ORDER BY PageViews DESC LIMIT 10 OFFSET 10000; +SELECT DATE_TRUNC('minute', EventTime) AS M, COUNT(*) AS PageViews FROM hits WHERE CounterID = 62 AND EventDate >= '2013-07-14' AND EventDate <= '2013-07-15' AND IsRefresh = 0 AND DontCountHits = 0 GROUP BY DATE_TRUNC('minute', EventTime) ORDER BY DATE_TRUNC('minute', EventTime) LIMIT 10 OFFSET 1000; diff --git a/pgduckdb-motherduck/results/motherduck.json b/pgduckdb-motherduck/results/motherduck.json new file mode 100644 index 000000000..2bce5c863 --- /dev/null +++ b/pgduckdb-motherduck/results/motherduck.json @@ -0,0 +1,57 @@ +{ + "system": "pg_duckdb", + "date": "2024-11-23", + "machine": "cloud", + "cluster_size": "serverless", + + "tags": ["managed", "column-oriented", "PostgreSQL compatible", "serverless"], + + "load_time": 91.614, + "data_size": 0, + + "result": [ +[0.138964,0.015258,0.016077], +[0.132879,0.014631,0.016375], +[0.150402,0.020076,0.018707], +[0.136571,0.024532,0.024149], +[0.269683,0.148919,0.15068], +[0.320305,0.181124,0.178617], +[0.130833,0.014634,0.014709], +[0.130438,0.019109,0.019483], +[0.307982,0.182397,0.183229], +[0.360765,0.240961,0.24059], +[0.181567,0.06479,0.064691], +[0.208976,0.072179,0.072965], +[0.302809,0.170854,0.170643], +[0.437126,0.324878,0.318962], +[0.296762,0.180741,0.182182], +[0.322796,0.189612,0.189133], +[0.488604,0.375323,0.371993], +[0.443552,0.329381,0.357173], +[0.762512,0.658258,0.641012], +[0.140095,0.017002,0.017396], +[0.765095,0.302509,0.2995], +[0.349961,0.228921,0.224052], +[0.472621,0.360402,0.356845], +[1.39679,1.24423,1.21561], +[0.18372,0.066296,0.066534], +[0.177599,0.066766,0.06741], +[0.205539,0.083399,0.082905], +[0.470257,0.365256,0.354026], +[1.5107,1.53563,1.55076], +[0.849038,0.72794,0.728566], +[0.304129,0.153122,0.152549], +[0.321213,0.200797,0.198382], +[0.877334,0.761022,0.761743], +[0.937143,0.801845,0.806956], +[0.935478,0.832431,0.811753], +[0.382849,0.250345,0.267334], +[0.168527,0.049099,0.048662], +[0.142103,0.0414,0.025252], +[0.143525,0.032741,0.033455], +[0.234511,0.097073,0.095511], +[0.143504,0.017825,0.018593], +[0.143221,0.016469,0.016562], +[0.14678,0.018243,0.018707] + ] +} diff --git a/pgduckdb-motherduck/run.sh b/pgduckdb-motherduck/run.sh new file mode 100755 index 000000000..1dfc76acf --- /dev/null +++ b/pgduckdb-motherduck/run.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +TRIES=3 +CONNECTION=postgres://postgres:duckdb@172.17.0.2:5432/postgres +USE_MOTHERDUCK=1 + +if [[ $USE_MOTHERDUCK == 1 ]]; then +DATABASE='ddb$pgclick' +else +DATABASE=temp +fi + +cat queries.sql | while read query; do + echo "$query" + ( + echo "set search_path=$DATABASE;" + echo '\timing' + yes "$query" | head -n $TRIES + ) | psql $CONNECTION | grep 'Time' +done From bfff3fd67c4a775dda5859949f2e87d7a31c6ad4 Mon Sep 17 00:00:00 2001 From: Jordan Tigani Date: Sun, 24 Nov 2024 18:01:53 -0800 Subject: [PATCH 2/6] Updated pgduckdb motherduck scripts to not use dual with or without motherduck enabled for simplicity sake. --- pgduckdb-motherduck/benchmark.sh | 34 ++++++++------------- pgduckdb-motherduck/load.sh | 7 ----- pgduckdb-motherduck/results/motherduck.json | 4 +-- pgduckdb-motherduck/run.sh | 7 +---- 4 files changed, 15 insertions(+), 37 deletions(-) diff --git a/pgduckdb-motherduck/benchmark.sh b/pgduckdb-motherduck/benchmark.sh index bdfd8d1dc..56b36cb2e 100755 --- a/pgduckdb-motherduck/benchmark.sh +++ b/pgduckdb-motherduck/benchmark.sh @@ -11,44 +11,34 @@ set -ex # sudo apt install posgresql-client-common # sudo apt install postgresql-client-16 -USE_MOTHERDUCK=1 CONNECTION=postgres://postgres:duckdb@172.17.0.2:5432/postgres # CONNECTION=postgres://postgres:duckdb@172.17.0.2:5432/postgres -if [[ $USE_MOTHERDUCK == 1 ]]; then -# Sign up for MotherDuck. Get a motherduck token. -# export MOTHERDUCK_TOKEN=... {from the MotherDuck UI} +# Sign up for MotherDuck. +# Go to the web ui and obtain a token +# https://motherduck.com/docs/key-tasks/authenticating-and-connecting-to-motherduck/authenticating-to-motherduck/ +# Save the token as the motherduck_token environment variable: +# export motherduck_token=... # create a database called pgclick in the motherduck UI or duckdb cli -# you will also need to create dummy table in that database.For example, run -# create table pgclick.foo as SELECT 1 as a; +# `CREATE DATABASE pgclick` +# You will also need to create dummy table in that database. For example, run +# `create table pgclick.foo as SELECT 1 as a;` # (https://github.com/duckdb/pg_duckdb/issues/450) -sudo docker run -d --name pgduck -e POSTGRES_PASSWORD=duckdb -e MOTHERDUCK_TOKEN=$MOTHERDUCK_TOKEN pgduckdb/pgduckdb:16-main -c duckdb.motherduck_enabled=true - -else - -wget --no-verbose --continue https://datasets.clickhouse.com/hits_compatible/athena/hits.parquet -sudo docker run -d --name pgduck -p 5432:5432 -e POSTGRES_PASSWORD=duckdb -v ./hits.parquet:/tmp/hits.parquet pgduckdb/pgduckdb:16-main -fi +sudo docker run -d --name pgduck -e POSTGRES_PASSWORD=duckdb -e MOTHERDUCK_TOKEN=$MOTHERDUCK_TOKEN pgduckdb/pgduckdb:16-main -c duckdb.motherduck_enabled=true # Give postgres time to start running sleep 5 ./load.sh 2>&1 | tee load_log.txt + ./run.sh 2>&1 | tee log.txt -if [[ $USE_MOTHERDUCK == 1 ]]; then # Go to motherduck UI and execute: -# SELECT database_size FROM pragma_database_size() -# WHERE database_name = 'pgclick' -echo 'Fetch database size from the MotherDuck UI with `SELECT database_size FROM pragma_database_size() - WHERE database_name = 'pgclick'`' - -else -sudo docker exec -it pgduck du -bcs /var/lib/postgresql/data /tmp/hits.parquet -fi +# `SELECT database_size FROM pragma_database_size() WHERE database_name = 'pgclick'` +# 25 GB cat log.txt | grep -oP 'Time: \d+\.\d+ ms' | sed -r -e 's/Time: ([0-9]+\.[0-9]+) ms/\1/' | awk '{ if (i % 3 == 0) { printf "[" }; printf $1 / 1000; if (i % 3 != 2) { printf "," } else { print "]," }; ++i; }' diff --git a/pgduckdb-motherduck/load.sh b/pgduckdb-motherduck/load.sh index 437c5d529..7e1683d08 100755 --- a/pgduckdb-motherduck/load.sh +++ b/pgduckdb-motherduck/load.sh @@ -3,15 +3,8 @@ CONNECTION=postgres://postgres:duckdb@172.17.0.2:5432/postgres PSQL=psql -USE_MOTHERDUCK=1 - -if [[ $USE_MOTHERDUCK == 1 ]]; then DATABASE='ddb$pgclick' PARQUET_FILE='https:\/\/datasets.clickhouse.com\/hits_compatible\/hits.parquet' -else -DATABASE=temp -PARQUET_FILE='\/tmp\/hits.parquet' -fi echo "Loading data" ( diff --git a/pgduckdb-motherduck/results/motherduck.json b/pgduckdb-motherduck/results/motherduck.json index 2bce5c863..a7c82bc62 100644 --- a/pgduckdb-motherduck/results/motherduck.json +++ b/pgduckdb-motherduck/results/motherduck.json @@ -1,5 +1,5 @@ { - "system": "pg_duckdb", + "system": "pg_duckdb (MotherDuck enabled)", "date": "2024-11-23", "machine": "cloud", "cluster_size": "serverless", @@ -7,7 +7,7 @@ "tags": ["managed", "column-oriented", "PostgreSQL compatible", "serverless"], "load_time": 91.614, - "data_size": 0, + "data_size": 26843545600, "result": [ [0.138964,0.015258,0.016077], diff --git a/pgduckdb-motherduck/run.sh b/pgduckdb-motherduck/run.sh index 1dfc76acf..127693445 100755 --- a/pgduckdb-motherduck/run.sh +++ b/pgduckdb-motherduck/run.sh @@ -2,18 +2,13 @@ TRIES=3 CONNECTION=postgres://postgres:duckdb@172.17.0.2:5432/postgres -USE_MOTHERDUCK=1 -if [[ $USE_MOTHERDUCK == 1 ]]; then DATABASE='ddb$pgclick' -else -DATABASE=temp -fi cat queries.sql | while read query; do echo "$query" ( - echo "set search_path=$DATABASE;" + echo "set search_path=$DATABASE;" echo '\timing' yes "$query" | head -n $TRIES ) | psql $CONNECTION | grep 'Time' From 062966e11f178d48c1f4ce799bfead4d51a064da Mon Sep 17 00:00:00 2001 From: Jordan Tigani Date: Sun, 24 Nov 2024 18:03:06 -0800 Subject: [PATCH 3/6] use underscore in directory name to match existing directory structure --- {pgduckdb-motherduck => pg_duckdb-motherduck}/benchmark.sh | 0 {pgduckdb-motherduck => pg_duckdb-motherduck}/create.sql | 0 {pgduckdb-motherduck => pg_duckdb-motherduck}/load.sh | 0 {pgduckdb-motherduck => pg_duckdb-motherduck}/queries.sql | 0 .../results/motherduck.json | 0 {pgduckdb-motherduck => pg_duckdb-motherduck}/run.sh | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename {pgduckdb-motherduck => pg_duckdb-motherduck}/benchmark.sh (100%) rename {pgduckdb-motherduck => pg_duckdb-motherduck}/create.sql (100%) rename {pgduckdb-motherduck => pg_duckdb-motherduck}/load.sh (100%) rename {pgduckdb-motherduck => pg_duckdb-motherduck}/queries.sql (100%) rename {pgduckdb-motherduck => pg_duckdb-motherduck}/results/motherduck.json (100%) rename {pgduckdb-motherduck => pg_duckdb-motherduck}/run.sh (100%) diff --git a/pgduckdb-motherduck/benchmark.sh b/pg_duckdb-motherduck/benchmark.sh similarity index 100% rename from pgduckdb-motherduck/benchmark.sh rename to pg_duckdb-motherduck/benchmark.sh diff --git a/pgduckdb-motherduck/create.sql b/pg_duckdb-motherduck/create.sql similarity index 100% rename from pgduckdb-motherduck/create.sql rename to pg_duckdb-motherduck/create.sql diff --git a/pgduckdb-motherduck/load.sh b/pg_duckdb-motherduck/load.sh similarity index 100% rename from pgduckdb-motherduck/load.sh rename to pg_duckdb-motherduck/load.sh diff --git a/pgduckdb-motherduck/queries.sql b/pg_duckdb-motherduck/queries.sql similarity index 100% rename from pgduckdb-motherduck/queries.sql rename to pg_duckdb-motherduck/queries.sql diff --git a/pgduckdb-motherduck/results/motherduck.json b/pg_duckdb-motherduck/results/motherduck.json similarity index 100% rename from pgduckdb-motherduck/results/motherduck.json rename to pg_duckdb-motherduck/results/motherduck.json diff --git a/pgduckdb-motherduck/run.sh b/pg_duckdb-motherduck/run.sh similarity index 100% rename from pgduckdb-motherduck/run.sh rename to pg_duckdb-motherduck/run.sh From 17e3291446ab21bee843091ea7937658596c4afd Mon Sep 17 00:00:00 2001 From: Jordan Tigani Date: Sun, 24 Nov 2024 18:07:05 -0800 Subject: [PATCH 4/6] Add some helpful comments --- pg_duckdb-motherduck/benchmark.sh | 6 +++--- pg_duckdb-motherduck/load.sh | 2 ++ pg_duckdb-motherduck/run.sh | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pg_duckdb-motherduck/benchmark.sh b/pg_duckdb-motherduck/benchmark.sh index 56b36cb2e..04705c04f 100755 --- a/pg_duckdb-motherduck/benchmark.sh +++ b/pg_duckdb-motherduck/benchmark.sh @@ -11,9 +11,9 @@ set -ex # sudo apt install posgresql-client-common # sudo apt install postgresql-client-16 - -CONNECTION=postgres://postgres:duckdb@172.17.0.2:5432/postgres -# CONNECTION=postgres://postgres:duckdb@172.17.0.2:5432/postgres +# Note: To get equivalent performance you should be runnign from +# AWS US-EAST-1 region or as close to there as possible. Otherwise +# you'll see additional latency. # Sign up for MotherDuck. # Go to the web ui and obtain a token diff --git a/pg_duckdb-motherduck/load.sh b/pg_duckdb-motherduck/load.sh index 7e1683d08..a583ab326 100755 --- a/pg_duckdb-motherduck/load.sh +++ b/pg_duckdb-motherduck/load.sh @@ -1,5 +1,7 @@ #!/bin/bash +# Your docker may be set up to use localhost instead, if so +# edit the ip address below. CONNECTION=postgres://postgres:duckdb@172.17.0.2:5432/postgres PSQL=psql diff --git a/pg_duckdb-motherduck/run.sh b/pg_duckdb-motherduck/run.sh index 127693445..e5992789c 100755 --- a/pg_duckdb-motherduck/run.sh +++ b/pg_duckdb-motherduck/run.sh @@ -1,6 +1,8 @@ #!/bin/bash TRIES=3 +# Your docker may be set up to use localhost, if so edit ip address +# below. CONNECTION=postgres://postgres:duckdb@172.17.0.2:5432/postgres DATABASE='ddb$pgclick' From 9fec3a2dca84c66cd510824ce783ab34463b2bbe Mon Sep 17 00:00:00 2001 From: Jordan Tigani Date: Mon, 25 Nov 2024 16:52:12 -0800 Subject: [PATCH 5/6] Make docker use host network --- pg_duckdb-motherduck/benchmark.sh | 15 ++++++++------- pg_duckdb-motherduck/create.sql | 2 +- pg_duckdb-motherduck/load.sh | 6 ++---- pg_duckdb-motherduck/run.sh | 4 +--- 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/pg_duckdb-motherduck/benchmark.sh b/pg_duckdb-motherduck/benchmark.sh index 04705c04f..27aab8832 100755 --- a/pg_duckdb-motherduck/benchmark.sh +++ b/pg_duckdb-motherduck/benchmark.sh @@ -1,6 +1,6 @@ #!/bin/bash -set -ex +set -e #sudo apt-get update #sudo apt-get install -y docker.io @@ -22,21 +22,22 @@ set -ex # export motherduck_token=... # create a database called pgclick in the motherduck UI or duckdb cli # `CREATE DATABASE pgclick` -# You will also need to create dummy table in that database. For example, run -# `create table pgclick.foo as SELECT 1 as a;` -# (https://github.com/duckdb/pg_duckdb/issues/450) +if [ -z "${MOTHERDUCK_TOKEN}" ]; then + echo "Error: MOTHERDUCK_TOKEN is not set." + exit 1 +fi -sudo docker run -d --name pgduck -e POSTGRES_PASSWORD=duckdb -e MOTHERDUCK_TOKEN=$MOTHERDUCK_TOKEN pgduckdb/pgduckdb:16-main -c duckdb.motherduck_enabled=true +sudo docker run -d --name pgduck --network=host -e POSTGRES_PASSWORD=duckdb -e MOTHERDUCK_TOKEN=${MOTHERDUCK_TOKEN} pgduckdb/pgduckdb:16-main -c duckdb.motherduck_enabled=true # Give postgres time to start running -sleep 5 +sleep 10 ./load.sh 2>&1 | tee load_log.txt ./run.sh 2>&1 | tee log.txt -# Go to motherduck UI and execute: +# Go to https://app.motherduck.com and execute: # `SELECT database_size FROM pragma_database_size() WHERE database_name = 'pgclick'` # 25 GB diff --git a/pg_duckdb-motherduck/create.sql b/pg_duckdb-motherduck/create.sql index 5ae9eef4c..51336b6b3 100644 --- a/pg_duckdb-motherduck/create.sql +++ b/pg_duckdb-motherduck/create.sql @@ -1,4 +1,4 @@ create or replace view hits_view as select WatchID, JavaEnable, Title, GoodEvent, 'epoch'::timestamp + (EventTime || 'second')::interval EventTime, 'epoch'::timestamp + (EventDate || 'day')::interval EventDate, CounterID, ClientIP, RegionID, UserID, CounterClass, OS, UserAgent, URL, Referer, IsRefresh, RefererCategoryID, RefererRegionID, URLCategoryID, URLRegionID, ResolutionWidth, ResolutionHeight, ResolutionDepth, FlashMajor, FlashMinor, FlashMinor2, NetMajor, NetMinor, UserAgentMajor, UserAgentMinor, CookieEnable, JavascriptEnable, IsMobile, MobilePhone, MobilePhoneModel, Params, IPNetworkID, TraficSourceID, SearchEngineID, SearchPhrase, AdvEngineID, IsArtifical, WindowClientWidth, WindowClientHeight, ClientTimeZone, 'epoch'::timestamp + (ClientEventTime || 'second')::interval ClientEventTime, SilverlightVersion1, SilverlightVersion2, SilverlightVersion3, SilverlightVersion4, PageCharset, CodeVersion, IsLink, IsDownload, IsNotBounce, FUniqID, OriginalURL, HID, IsOldCounter, IsEvent, IsParameter, DontCountHits, WithHash, HitColor, 'epoch'::timestamp + (LocalEventTime || 'second')::interval LocalEventTime, Age, Sex, Income, Interests, Robotness, RemoteIP, WindowName, OpenerName, HistoryLength, BrowserLanguage, BrowserCountry, SocialNetwork, SocialAction, HTTPError, SendTiming, DNSTiming, ConnectTiming, ResponseStartTiming, ResponseEndTiming, FetchTiming, SocialSourceNetworkID, SocialSourcePage, ParamPrice, ParamOrderID, ParamCurrency, ParamCurrencyID, OpenstatServiceName, OpenstatCampaignID, OpenstatAdID, OpenstatSourceID, UTMSource, UTMMedium, UTMCampaign, UTMContent, UTMTerm, FromTag, HasGCLID, RefererHash, URLHash, CLID from read_parquet('REPLACE_PARQUET_FILE') as (WatchID BIGINT, JavaEnable SMALLINT, Title VARCHAR, GoodEvent SMALLINT, EventTime BIGINT, EventDate int, CounterID INTEGER, ClientIP INTEGER, RegionID INTEGER, UserID BIGINT, CounterClass SMALLINT, OS SMALLINT, UserAgent SMALLINT, URL VARCHAR, Referer VARCHAR, IsRefresh SMALLINT, RefererCategoryID SMALLINT, RefererRegionID INTEGER, URLCategoryID SMALLINT, URLRegionID INTEGER, ResolutionWidth SMALLINT, ResolutionHeight SMALLINT, ResolutionDepth SMALLINT, FlashMajor SMALLINT, FlashMinor SMALLINT, FlashMinor2 VARCHAR, NetMajor SMALLINT, NetMinor SMALLINT, UserAgentMajor SMALLINT, UserAgentMinor VARCHAR, CookieEnable SMALLINT, JavascriptEnable SMALLINT, IsMobile SMALLINT, MobilePhone SMALLINT, MobilePhoneModel VARCHAR, Params VARCHAR, IPNetworkID INTEGER, TraficSourceID SMALLINT, SearchEngineID SMALLINT, SearchPhrase VARCHAR, AdvEngineID SMALLINT, IsArtifical SMALLINT, WindowClientWidth SMALLINT, WindowClientHeight SMALLINT, ClientTimeZone SMALLINT, ClientEventTime BIGINT, SilverlightVersion1 SMALLINT, SilverlightVersion2 SMALLINT, SilverlightVersion3 INTEGER, SilverlightVersion4 SMALLINT, PageCharset VARCHAR, CodeVersion INTEGER, IsLink SMALLINT, IsDownload SMALLINT, IsNotBounce SMALLINT, FUniqID BIGINT, OriginalURL VARCHAR, HID INTEGER, IsOldCounter SMALLINT, IsEvent SMALLINT, IsParameter SMALLINT, DontCountHits SMALLINT, WithHash SMALLINT, HitColor VARCHAR, LocalEventTime BIGINT, Age SMALLINT, Sex SMALLINT, Income SMALLINT, Interests SMALLINT, Robotness SMALLINT, RemoteIP INTEGER, WindowName INTEGER, OpenerName INTEGER, HistoryLength SMALLINT, BrowserLanguage VARCHAR, BrowserCountry VARCHAR, SocialNetwork VARCHAR, SocialAction VARCHAR, HTTPError SMALLINT, SendTiming INTEGER, DNSTiming INTEGER, ConnectTiming INTEGER, ResponseStartTiming INTEGER, ResponseEndTiming INTEGER, FetchTiming INTEGER, SocialSourceNetworkID SMALLINT, SocialSourcePage VARCHAR, ParamPrice BIGINT, ParamOrderID VARCHAR, ParamCurrency VARCHAR, ParamCurrencyID SMALLINT, OpenstatServiceName VARCHAR, OpenstatCampaignID VARCHAR, OpenstatAdID VARCHAR, OpenstatSourceID VARCHAR, UTMSource VARCHAR, UTMMedium VARCHAR, UTMCampaign VARCHAR, UTMContent VARCHAR, UTMTerm VARCHAR, FromTag VARCHAR, HasGCLID SMALLINT, RefererHash BIGINT, URLHash BIGINT, CLID INTEGER); -CREATE table REPLACE_DATABASE.hits USING DUCKDB AS SELECT * FROM hits_view; +CREATE table REPLACE_SCHEMA.hits USING DUCKDB AS SELECT * FROM hits_view; diff --git a/pg_duckdb-motherduck/load.sh b/pg_duckdb-motherduck/load.sh index a583ab326..d0912eff2 100755 --- a/pg_duckdb-motherduck/load.sh +++ b/pg_duckdb-motherduck/load.sh @@ -1,8 +1,6 @@ #!/bin/bash -# Your docker may be set up to use localhost instead, if so -# edit the ip address below. -CONNECTION=postgres://postgres:duckdb@172.17.0.2:5432/postgres +CONNECTION=postgres://postgres:duckdb@localhost:5432/postgres PSQL=psql DATABASE='ddb$pgclick' @@ -12,6 +10,6 @@ echo "Loading data" ( echo "\timing" cat create.sql | - sed -e "s/REPLACE_DATABASE/$DATABASE/g" -e "s/REPLACE_PARQUET_FILE/$PARQUET_FILE/g" + sed -e "s/REPLACE_SCHEMA/$DATABASE/g" -e "s/REPLACE_PARQUET_FILE/$PARQUET_FILE/g" ) | $PSQL $CONNECTION | grep 'Time' diff --git a/pg_duckdb-motherduck/run.sh b/pg_duckdb-motherduck/run.sh index e5992789c..af6d05fcc 100755 --- a/pg_duckdb-motherduck/run.sh +++ b/pg_duckdb-motherduck/run.sh @@ -1,9 +1,7 @@ #!/bin/bash TRIES=3 -# Your docker may be set up to use localhost, if so edit ip address -# below. -CONNECTION=postgres://postgres:duckdb@172.17.0.2:5432/postgres +CONNECTION=postgres://postgres:duckdb@localhost:5432/postgres DATABASE='ddb$pgclick' From ad4c18785e898fa7c3c8fb3d289c9a4de8d797d0 Mon Sep 17 00:00:00 2001 From: Jordan Tigani Date: Wed, 27 Nov 2024 14:53:34 -0800 Subject: [PATCH 6/6] Remove unnecessary setup commands, fix typos --- pg_duckdb-motherduck/benchmark.sh | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/pg_duckdb-motherduck/benchmark.sh b/pg_duckdb-motherduck/benchmark.sh index 27aab8832..18cc670a2 100755 --- a/pg_duckdb-motherduck/benchmark.sh +++ b/pg_duckdb-motherduck/benchmark.sh @@ -2,24 +2,20 @@ set -e -#sudo apt-get update -#sudo apt-get install -y docker.io -#sudo apt-get install -y postgresql-client - -# Ubuntu: -# snap install docker -# sudo apt install posgresql-client-common +# Setup on Ubuntu (your package manager may vary): +# sudo snap install docker +# sudo apt install postgresql-client-common # sudo apt install postgresql-client-16 -# Note: To get equivalent performance you should be runnign from +# Note: To get equivalent performance you should be running from # AWS US-EAST-1 region or as close to there as possible. Otherwise # you'll see additional latency. # Sign up for MotherDuck. # Go to the web ui and obtain a token # https://motherduck.com/docs/key-tasks/authenticating-and-connecting-to-motherduck/authenticating-to-motherduck/ -# Save the token as the motherduck_token environment variable: -# export motherduck_token=... +# Save the token as the MOTHERDUCK_TOKEN environment variable: +# export MOTHERDUCK_TOKEN=... # create a database called pgclick in the motherduck UI or duckdb cli # `CREATE DATABASE pgclick`