1#include "benchmark_runner.hpp"
2#include "duckdb_benchmark_macro.hpp"
3#include "duckdb/main/appender.hpp"
4
5using namespace duckdb;
6using namespace std;
7
8//////////////
9// INSERT //
10//////////////
11#define APPEND_BENCHMARK_INSERT(CREATE_STATEMENT, AUTO_COMMIT) \
12 void Load(DuckDBBenchmarkState *state) override { \
13 state->conn.Query(CREATE_STATEMENT); \
14 } \
15 void RunBenchmark(DuckDBBenchmarkState *state) override { \
16 if (!AUTO_COMMIT) \
17 state->conn.Query("BEGIN TRANSACTION"); \
18 for (int32_t i = 0; i < 100000; i++) { \
19 state->conn.Query("INSERT INTO integers VALUES (" + to_string(i) + ")"); \
20 } \
21 if (!AUTO_COMMIT) \
22 state->conn.Query("COMMIT"); \
23 } \
24 void Cleanup(DuckDBBenchmarkState *state) override { \
25 state->conn.Query("DROP TABLE integers"); \
26 Load(state); \
27 } \
28 string VerifyResult(QueryResult *result) override { \
29 return string(); \
30 } \
31 string BenchmarkInfo() override { \
32 return "Append 100K 4-byte integers to a table using a series of INSERT INTO statements"; \
33 }
34
35DUCKDB_BENCHMARK(Append100KIntegersINSERT, "[append]")
36APPEND_BENCHMARK_INSERT("CREATE TABLE integers(i INTEGER)", false)
37FINISH_BENCHMARK(Append100KIntegersINSERT)
38
39DUCKDB_BENCHMARK(Append100KIntegersINSERTDisk, "[append]")
40APPEND_BENCHMARK_INSERT("CREATE TABLE integers(i INTEGER)", false)
41bool InMemory() override {
42 return false;
43}
44FINISH_BENCHMARK(Append100KIntegersINSERTDisk)
45
46DUCKDB_BENCHMARK(Append100KIntegersINSERTPrimary, "[append]")
47APPEND_BENCHMARK_INSERT("CREATE TABLE integers(i INTEGER PRIMARY KEY)", false)
48FINISH_BENCHMARK(Append100KIntegersINSERTPrimary)
49
50DUCKDB_BENCHMARK(Append100KIntegersINSERTAutoCommit, "[append]")
51APPEND_BENCHMARK_INSERT("CREATE TABLE integers(i INTEGER)", true)
52FINISH_BENCHMARK(Append100KIntegersINSERTAutoCommit)
53
54//////////////
55// PREPARED //
56//////////////
57struct DuckDBPreparedState : public DuckDBBenchmarkState {
58 unique_ptr<PreparedStatement> prepared;
59
60 DuckDBPreparedState(string path) : DuckDBBenchmarkState(path) {
61 }
62 virtual ~DuckDBPreparedState() {
63 }
64};
65
66#define APPEND_BENCHMARK_PREPARED(CREATE_STATEMENT) \
67 unique_ptr<DuckDBBenchmarkState> CreateBenchmarkState() override { \
68 auto result = make_unique<DuckDBPreparedState>(GetDatabasePath()); \
69 return move(result); \
70 } \
71 void Load(DuckDBBenchmarkState *state_) override { \
72 auto state = (DuckDBPreparedState *)state_; \
73 state->conn.Query(CREATE_STATEMENT); \
74 state->prepared = state->conn.Prepare("INSERT INTO integers VALUES ($1)"); \
75 } \
76 void RunBenchmark(DuckDBBenchmarkState *state_) override { \
77 auto state = (DuckDBPreparedState *)state_; \
78 state->conn.Query("BEGIN TRANSACTION"); \
79 for (int32_t i = 0; i < 100000; i++) { \
80 state->prepared->Execute(i); \
81 } \
82 state->conn.Query("COMMIT"); \
83 } \
84 void Cleanup(DuckDBBenchmarkState *state) override { \
85 state->conn.Query("DROP TABLE integers"); \
86 Load(state); \
87 } \
88 string VerifyResult(QueryResult *result) override { \
89 return string(); \
90 } \
91 string BenchmarkInfo() override { \
92 return "Append 100K 4-byte integers to a table using a series of prepared INSERT INTO statements"; \
93 }
94
95DUCKDB_BENCHMARK(Append100KIntegersPREPARED, "[append]")
96APPEND_BENCHMARK_PREPARED("CREATE TABLE integers(i INTEGER)")
97FINISH_BENCHMARK(Append100KIntegersPREPARED)
98
99DUCKDB_BENCHMARK(Append100KIntegersPREPAREDDisk, "[append]")
100APPEND_BENCHMARK_PREPARED("CREATE TABLE integers(i INTEGER)")
101bool InMemory() override {
102 return false;
103}
104FINISH_BENCHMARK(Append100KIntegersPREPAREDDisk)
105
106DUCKDB_BENCHMARK(Append100KIntegersPREPAREDPrimary, "[append]")
107APPEND_BENCHMARK_PREPARED("CREATE TABLE integers(i INTEGER PRIMARY KEY)")
108FINISH_BENCHMARK(Append100KIntegersPREPAREDPrimary)
109
110//////////////
111// APPENDER //
112//////////////
113#define APPEND_BENCHMARK_APPENDER(CREATE_STATEMENT) \
114 void Load(DuckDBBenchmarkState *state) override { \
115 state->conn.Query(CREATE_STATEMENT); \
116 } \
117 void RunBenchmark(DuckDBBenchmarkState *state) override { \
118 state->conn.Query("BEGIN QUERY"); \
119 Appender appender(state->conn, "integers"); \
120 for (int32_t i = 0; i < 100000; i++) { \
121 appender.BeginRow(); \
122 appender.Append<int32_t>(i); \
123 appender.EndRow(); \
124 } \
125 appender.Close(); \
126 state->conn.Query("COMMIT"); \
127 } \
128 void Cleanup(DuckDBBenchmarkState *state) override { \
129 state->conn.Query("DROP TABLE integers"); \
130 Load(state); \
131 } \
132 string VerifyResult(QueryResult *result) override { \
133 return string(); \
134 } \
135 string BenchmarkInfo() override { \
136 return "Append 100K 4-byte integers to a table using an Appender"; \
137 }
138
139DUCKDB_BENCHMARK(Append100KIntegersAPPENDER, "[append]")
140APPEND_BENCHMARK_APPENDER("CREATE TABLE integers(i INTEGER)")
141FINISH_BENCHMARK(Append100KIntegersAPPENDER)
142
143DUCKDB_BENCHMARK(Append100KIntegersAPPENDERDisk, "[append]")
144APPEND_BENCHMARK_APPENDER("CREATE TABLE integers(i INTEGER)")
145bool InMemory() override {
146 return false;
147}
148FINISH_BENCHMARK(Append100KIntegersAPPENDERDisk)
149
150DUCKDB_BENCHMARK(Append100KIntegersAPPENDERPrimary, "[append]")
151APPEND_BENCHMARK_APPENDER("CREATE TABLE integers(i INTEGER PRIMARY KEY)")
152FINISH_BENCHMARK(Append100KIntegersAPPENDERPrimary)
153
154///////////////
155// COPY INTO //
156///////////////
157#define APPEND_BENCHMARK_COPY(CREATE_STATEMENT) \
158 void Load(DuckDBBenchmarkState *state) override { \
159 state->conn.Query("CREATE TABLE integers(i INTEGER)"); \
160 Appender appender(state->conn, "integers"); \
161 for (int32_t i = 0; i < 100000; i++) { \
162 appender.BeginRow(); \
163 appender.Append<int32_t>(i); \
164 appender.EndRow(); \
165 } \
166 appender.Close(); \
167 state->conn.Query("COPY integers TO 'integers.csv' DELIMITER '|'"); \
168 state->conn.Query("DROP TABLE integers"); \
169 state->conn.Query(CREATE_STATEMENT); \
170 } \
171 string GetQuery() override { \
172 return "COPY integers FROM 'integers.csv' DELIMITER '|'"; \
173 } \
174 void Cleanup(DuckDBBenchmarkState *state) override { \
175 state->conn.Query("DROP TABLE integers"); \
176 state->conn.Query(CREATE_STATEMENT); \
177 } \
178 string VerifyResult(QueryResult *result) override { \
179 return string(); \
180 } \
181 string BenchmarkInfo() override { \
182 return "Append 100K 4-byte integers to a table using the COPY INTO statement"; \
183 }
184
185DUCKDB_BENCHMARK(Append100KIntegersCOPY, "[append]")
186APPEND_BENCHMARK_COPY("CREATE TABLE integers(i INTEGER)")
187FINISH_BENCHMARK(Append100KIntegersCOPY)
188
189DUCKDB_BENCHMARK(Append100KIntegersCOPYDisk, "[append]")
190APPEND_BENCHMARK_COPY("CREATE TABLE integers(i INTEGER)")
191bool InMemory() override {
192 return false;
193}
194FINISH_BENCHMARK(Append100KIntegersCOPYDisk)
195
196DUCKDB_BENCHMARK(Append100KIntegersCOPYPrimary, "[append]")
197APPEND_BENCHMARK_COPY("CREATE TABLE integers(i INTEGER PRIMARY KEY)")
198FINISH_BENCHMARK(Append100KIntegersCOPYPrimary)
199
200DUCKDB_BENCHMARK(Write100KIntegers, "[append]")
201void Load(DuckDBBenchmarkState *state) override {
202 state->conn.Query("CREATE TABLE integers(i INTEGER)");
203 Appender appender(state->conn, "integers");
204 for (int32_t i = 0; i < 100000; i++) {
205 appender.BeginRow();
206 appender.Append<int32_t>(i);
207 appender.EndRow();
208 }
209}
210string GetQuery() override {
211 return "COPY integers TO 'integers.csv' DELIMITER '|' HEADER";
212}
213string VerifyResult(QueryResult *result) override {
214 if (!result->success) {
215 return result->error;
216 }
217 return string();
218}
219string BenchmarkInfo() override {
220 return "Write 100K 4-byte integers to CSV";
221}
222FINISH_BENCHMARK(Write100KIntegers)
223