|
| 1 | +# -----------------------------------Goal-------------------------------------- |
| 2 | +# Compare the implementation of parsing Ecto.Query objects into SQL queries by |
| 3 | +# the different database adapters |
| 4 | + |
| 5 | +# -------------------------------Description----------------------------------- |
| 6 | +# Repo.to_sql/2 is an important step of a database query. |
| 7 | +# This benchmark tracks performance of parsing Ecto.Query structures into |
| 8 | +# "raw" SQL query strings. |
| 9 | +# Different Ecto.Query objects has multiple combinations and some different attributes |
| 10 | +# depending on the query type. In this tests we benchmark against different |
| 11 | +# query types and complexity. |
| 12 | + |
| 13 | +# ----------------------------Factors(don't change)--------------------------- |
| 14 | +# Different adapters supported by Ecto, each one has its own implementation that |
| 15 | +# is tested against different query inputs |
| 16 | + |
| 17 | +# ----------------------------Parameters(change)------------------------------- |
| 18 | +# Different query objects (select, delete, update) to be translated into pure SQL |
| 19 | +# strings. |
| 20 | + |
| 21 | +Code.require_file("../../support/setup.exs", __DIR__) |
| 22 | + |
| 23 | +import Ecto.Query |
| 24 | + |
| 25 | +alias Ecto.Bench.{User, Game} |
| 26 | + |
| 27 | +inputs = %{ |
| 28 | + "Ordinary Select All" => {:all, from(User)}, |
| 29 | + "Ordinary Delete All" => {:delete_all, from(User)}, |
| 30 | + "Ordinary Update All" => {:update_all, from(User, update: [set: [name: "Thor"]])}, |
| 31 | + "Ordinary Where" => {:all, from(User, where: [name: "Thanos", email: "blah@blah"])}, |
| 32 | + "Fetch First Registry" => {:all, first(User)}, |
| 33 | + "Fetch Last Registry" => {:all, last(User)}, |
| 34 | + "Ordinary Order By" => {:all, order_by(User, desc: :name)}, |
| 35 | + "Complex Query 2 Joins" => |
| 36 | + {:all, |
| 37 | + from(User, where: [name: "Thanos"]) |
| 38 | + |> join(:left, [u], ux in User, on: u.id == ux.id) |
| 39 | + |> join(:right, [j], uj in User, on: j.id == 1 and j.email == "email@email") |
| 40 | + |> select([u, ux], {u.name, ux.email})}, |
| 41 | + "Complex Query 4 Joins" => |
| 42 | + {:all, |
| 43 | + from(User) |
| 44 | + |> join(:left, [u], g in Game, on: g.name == u.name) |
| 45 | + |> join(:right, [g], u in User, on: g.id == 1 and u.email == "email@email") |
| 46 | + |> join(:inner, [u], g in fragment("SELECT * from games where game.id = ?", u.id)) |
| 47 | + |> join(:left, [g], u in fragment("SELECT * from users = ?", g.id)) |
| 48 | + |> select([u, g], {u.name, g.price})} |
| 49 | +} |
| 50 | + |
| 51 | +jobs = %{ |
| 52 | + "Pg Query Builder" => fn {type, query} -> Ecto.Bench.PgRepo.to_sql(type, query) end, |
| 53 | + "MyXQL Query Builder" => fn {type, query} -> Ecto.Bench.MyXQLRepo.to_sql(type, query) end |
| 54 | +} |
| 55 | + |
| 56 | +path = System.get_env("BENCHMARKS_OUTPUT_PATH") || "bench/results" |
| 57 | +file = Path.join(path, "to_sql.json") |
| 58 | + |
| 59 | +Benchee.run( |
| 60 | + jobs, |
| 61 | + inputs: inputs, |
| 62 | + formatters: [Benchee.Formatters.JSON, Benchee.Formatters.Console], |
| 63 | + formatter_options: [json: [file: file]] |
| 64 | +) |
0 commit comments