Testen der Leistung analytischer Abfragen in PostgreSQL, ClickHouse und clickhousedb_fdw (PostgreSQL)

In dieser Studie wollte ich sehen, welche Leistungsverbesserungen durch die Verwendung einer ClickHouse-Datenquelle anstelle von PostgreSQL erzielt werden können. Ich kenne die Produktivitätsvorteile, die ich durch die Verwendung von ClickHouse erhalte. Bleiben diese Vorteile bestehen, wenn ich über PostgreSQL mit einem Foreign Data Wrapper (FDW) auf ClickHouse zugreife?

Die untersuchten Datenbankumgebungen sind PostgreSQL v11, clickhousedb_fdw und ClickHouse-Datenbank. Letztendlich werden wir ab PostgreSQL v11 verschiedene SQL-Abfragen ausführen, die über unser clickhousedb_fdw an die ClickHouse-Datenbank weitergeleitet werden. Anschließend sehen wir, wie sich die Leistung von FDW im Vergleich zu denselben Abfragen verhält, die in nativem PostgreSQL und nativem ClickHouse ausgeführt werden.

Clickhouse-Datenbank

ClickHouse ist ein spaltenbasiertes Open-Source-Datenbankverwaltungssystem, das eine 100- bis 1000-mal schnellere Leistung als herkömmliche Datenbankansätze erzielen kann und über eine Milliarde Zeilen in weniger als einer Sekunde verarbeiten kann.

Clickhousedb_fdw

clickhousedb_fdw – Der externe Daten-Wrapper für die ClickHouse-Datenbank (FDW) ist ein Open-Source-Projekt von Percona. Hier ist ein Link zum GitHub-Repository des Projekts.

Im März habe ich einen Blog geschrieben, der Ihnen mehr über unsere FDW erzählt.

Wie Sie sehen werden, stellt dies ein FDW für ClickHouse bereit, das SELECT aus der ClickHouse-Datenbank und INSERT INTO vom PostgreSQL v11-Server aus ermöglicht.

FDW unterstützt erweiterte Funktionen wie Aggregation und Join. Dadurch wird die Leistung erheblich verbessert, da die Ressourcen des Remote-Servers für diese ressourcenintensiven Vorgänge genutzt werden.

Benchmark-Umgebung

  • Supermicro-Server:
    • Intel® Xeon® CPU E5-2683 v3 bei 2.00 GHz
    • 2 Sockel / 28 Kerne / 56 Threads
    • Speicher: 256GB RAM
    • Speicher: Samsung SM863 1.9 TB Enterprise SSD
    • Dateisystem: ext4/xfs
  • Betriebssystem: Linux smblade01 4.15.0-42-generic #45~16.04.1-Ubuntu
  • PostgreSQL: Version 11

Benchmark-Tests

Anstatt für diesen Test einen maschinengenerierten Datensatz zu verwenden, haben wir die Daten „Produktivität nach gemeldeter Bedienerzeit“ von 1987 bis 2018 verwendet. Sie können auf die Daten zugreifen mit unserem hier verfügbaren Skript.

Die Datenbankgröße beträgt 85 GB und bietet eine Tabelle mit 109 Spalten.

Benchmark-Abfragen

Hier sind die Abfragen, die ich zum Vergleich von ClickHouse, clickhousedb_fdw und PostgreSQL verwendet habe.

Q#
Abfrage enthält Aggregate und Gruppierung nach

Q1
SELECT DayOfWeek, count(*) AS c FROM ontime WHERE Year >= 2000 AND Year <= 2008 GROUP BY DayOfWeek ORDER BY c DESC;

Q2
SELECT DayOfWeek, count(*) AS c FROM ontime WHERE DepDelay>10 AND Year >= 2000 AND Year <= 2008 GROUP BY DayOfWeek ORDER BY c DESC;

Q3
SELECT Origin, count(*) AS c FROM ontime WHERE DepDelay>10 AND Year >= 2000 AND Year <= 2008 GROUP BY Origin ORDER BY c DESC LIMIT 10;

Q4
SELECT Carrier, count() FROM ontime WHERE DepDelay>10 AND Year = 2007 GROUP BY Carrier ORDER BY count() DESC;

Q5
SELECT a.Carrier, c, c2, c1000/c2 als c3 FROM ( SELECT Carrier, count() AS c FROM ontime WHERE DepDelay>10 AND Year=2007 GROUP BY Carrier ) a INNER JOIN ( SELECT Carrier,count(*) AS c2 FROM ontime WHERE Year=2007 GROUP BY Carrier)b auf a.Carrier=b.Carrier ORDER BY c3 DESC;

Q6
SELECT a.Carrier, c, c2, c1000/c2 als c3 FROM ( SELECT Carrier, count() AS c FROM ontime WHERE DepDelay>10 AND Year >= 2000 AND Year <= 2008 GROUP BY Carrier) a INNER JOIN ( SELECT Carrier, count(*) AS c2 FROM ontime WHERE Year >= 2000 AND Year <= 2008 GROUP BY Carrier ) b on a.Carrier=b.Carrier ORDER BY c3 DESC;

Q7
SELECT Carrier, avg(DepDelay) * 1000 AS c3 FROM ontime WHERE Year >= 2000 AND Year <= 2008 GROUP BY Carrier;

Q8
SELECT Year, avg(DepDelay) FROM ontime GROUP BY Year;

Q9
Wählen Sie Jahr aus, zählen Sie(*) als c1 aus der Pünktlichkeitsgruppe nach Jahr;

Q10
SELECT avg(cnt) FROM (SELECT Year,Month,count(*) AS cnt FROM ontime WHERE DepDel15=1 GROUP BY Year,Month) a;

Q11
select avg(c1) from (select Year, Month, count(*) as c1 from ontime group by Year, Month) a;

Q12
SELECT OriginCityName, DestCityName, count(*) AS c FROM ontime GROUP BY OriginCityName, DestCityName ORDER BY c DESC LIMIT 10;

Q13
SELECT OriginCityName, count(*) AS c FROM ontime GROUP BY OriginCityName ORDER BY c DESC LIMIT 10;

Abfrage enthält Joins

Q14
SELECT a.Year, c1/c2 FROM ( select Year, count()1000 als c1 von ontime WHERE DepDelay>10 GROUP BY Year) a INNER JOIN (wählen Sie Year, count(*) als c2 von ontime GROUP BY Year) b on a.Year=b.Year ORDER BY a.Year;

Q15
SELECT a.“Year“, c1/c2 FROM ( select „Year“, count()1000 als c1 FROM Fontime WHERE „DepDelay“>10 GROUP BY „Year“) a INNER JOIN (wählen Sie „Year“, count(*) als c2 FROM Fontime GROUP BY „Year“) b auf a.“Year“=b. "Jahr";

Tabelle 1: Im Benchmark verwendete Abfragen

Abfrageausführungen

Hier sind die Ergebnisse jeder Abfrage, wenn sie in verschiedenen Datenbankeinstellungen ausgeführt wird: PostgreSQL mit und ohne Indizes, natives ClickHouse und clickhousedb_fdw. Die Zeit wird in Millisekunden angezeigt.

Q#
PostgreSQL
PostgreSQL (indiziert)
Clickhouse
clickhousedb_fdw

Q1
27920
19634
23
57

Q2
35124
17301
50
80

Q3
34046
15618
67
115

Q4
31632
7667
25
37

Q5
47220
8976
27
60

Q6
58233
24368
55
153

Q7
30566
13256
52
91

Q8
38309
60511
112
179

Q9
20674
37979
31
81

Q10
34990
20102
56
148

Q11
30489
51658
37
155

Q12
39357
33742
186
1333

Q13
29912
30709
101
384

Q14
54126
39913
124
1364212

Q15
97258
30211
245
259

Tabelle 1: Zeitaufwand für die Ausführung der im Benchmark verwendeten Abfragen

Ergebnisse anzeigen

Das Diagramm zeigt die Ausführungszeit der Abfrage in Millisekunden, die X-Achse zeigt die Abfragenummer aus den obigen Tabellen und die Y-Achse zeigt die Ausführungszeit in Millisekunden. ClickHouse-Ergebnisse und Daten, die mit clickhousedb_fdw aus Postgres abgerufen wurden, werden angezeigt. Aus der Tabelle können Sie ersehen, dass es einen großen Unterschied zwischen PostgreSQL und ClickHouse gibt, aber nur einen minimalen Unterschied zwischen ClickHouse und clickhousedb_fdw.

Testen der Leistung analytischer Abfragen in PostgreSQL, ClickHouse und clickhousedb_fdw (PostgreSQL)

Diese Grafik zeigt den Unterschied zwischen ClickhouseDB und clickhousedb_fdw. Bei den meisten Abfragen ist der FDW-Overhead nicht so hoch und fällt bis auf Q12 kaum ins Gewicht. Diese Abfrage umfasst Joins und eine ORDER BY-Klausel. Aufgrund der ORDER BY GROUP/BY-Klausel wird ORDER BY nicht an ClickHouse weitergeleitet.

In Tabelle 2 sehen wir den Zeitsprung in den Abfragen Q12 und Q13. Auch dies wird durch die ORDER BY-Klausel verursacht. Um dies zu bestätigen, habe ich die Abfragen Q-14 und Q-15 mit und ohne die ORDER BY-Klausel ausgeführt. Ohne die ORDER BY-Klausel beträgt die Abschlusszeit 259 ms und mit der ORDER BY-Klausel 1364212. Um diese Abfrage zu debuggen, erkläre ich beide Abfragen und hier sind die Ergebnisse der Erklärung.

F15: Ohne ORDER BY-Klausel

bm=# EXPLAIN VERBOSE SELECT a."Year", c1/c2 
     FROM (SELECT "Year", count(*)*1000 AS c1 FROM fontime WHERE "DepDelay" > 10 GROUP BY "Year") a
     INNER JOIN(SELECT "Year", count(*) AS c2 FROM fontime GROUP BY "Year") b ON a."Year"=b."Year";

F15: Abfrage ohne ORDER BY-Klausel

QUERY PLAN                                                      
Hash Join  (cost=2250.00..128516.06 rows=50000000 width=12)  
Output: fontime."Year", (((count(*) * 1000)) / b.c2)  
Inner Unique: true   Hash Cond: (fontime."Year" = b."Year")  
->  Foreign Scan  (cost=1.00..-1.00 rows=100000 width=12)        
Output: fontime."Year", ((count(*) * 1000))        
Relations: Aggregate on (fontime)        
Remote SQL: SELECT "Year", (count(*) * 1000) FROM "default".ontime WHERE (("DepDelay" > 10)) GROUP BY "Year"  
->  Hash  (cost=999.00..999.00 rows=100000 width=12)        
Output: b.c2, b."Year"        
->  Subquery Scan on b  (cost=1.00..999.00 rows=100000 width=12)              
Output: b.c2, b."Year"              
->  Foreign Scan  (cost=1.00..-1.00 rows=100000 width=12)                    
Output: fontime_1."Year", (count(*))                    
Relations: Aggregate on (fontime)                    
Remote SQL: SELECT "Year", count(*) FROM "default".ontime GROUP BY "Year"(16 rows)

F14: Abfrage mit ORDER BY-Klausel

bm=# EXPLAIN VERBOSE SELECT a."Year", c1/c2 FROM(SELECT "Year", count(*)*1000 AS c1 FROM fontime WHERE "DepDelay" > 10 GROUP BY "Year") a 
     INNER JOIN(SELECT "Year", count(*) as c2 FROM fontime GROUP BY "Year") b  ON a."Year"= b."Year" 
     ORDER BY a."Year";

F14: Abfrageplan mit ORDER BY-Klausel

QUERY PLAN 
Merge Join  (cost=2.00..628498.02 rows=50000000 width=12)   
Output: fontime."Year", (((count(*) * 1000)) / (count(*)))   
Inner Unique: true   Merge Cond: (fontime."Year" = fontime_1."Year")   
->  GroupAggregate  (cost=1.00..499.01 rows=1 width=12)        
Output: fontime."Year", (count(*) * 1000)         
Group Key: fontime."Year"         
->  Foreign Scan on public.fontime  (cost=1.00..-1.00 rows=100000 width=4)               
Remote SQL: SELECT "Year" FROM "default".ontime WHERE (("DepDelay" > 10)) 
            ORDER BY "Year" ASC   
->  GroupAggregate  (cost=1.00..499.01 rows=1 width=12)         
Output: fontime_1."Year", count(*)         Group Key: fontime_1."Year"         
->  Foreign Scan on public.fontime fontime_1  (cost=1.00..-1.00 rows=100000 width=4) 
              
Remote SQL: SELECT "Year" FROM "default".ontime ORDER BY "Year" ASC(16 rows)

Abschluss

Die Ergebnisse dieser Experimente zeigen, dass ClickHouse eine wirklich gute Leistung bietet und clickhousedb_fdw die Leistungsvorteile von ClickHouse von PostgreSQL bietet. Bei der Verwendung von clickhousedb_fdw entsteht zwar ein gewisser Mehraufwand, dieser ist jedoch vernachlässigbar und vergleichbar mit der Leistung, die durch die native Ausführung in der ClickHouse-Datenbank erzielt wird. Dies bestätigt auch, dass fdw in PostgreSQL hervorragende Ergebnisse liefert.

Telegram-Chat über Clickhouse https://t.me/clickhouse_ru
Telegram-Chat mit PostgreSQL https://t.me/pgsql

Source: habr.com

Kommentar hinzufügen