Malloy – A Better SQL, from Looker
github.com
github.com
From technical documentations, I can see some potentials for significant simplifications on complex analytical queries but most people don't have such time or interest on new languages.
Here is an example of Malloy solving today's worlde in 50 lines of Malloy
https://looker-open-source.github.io/malloy/documentation/ex...
And here is the equivalent SQL.
https://gist.github.com/lloydtabb/32f46e7ecbb2da1a443d1adbe9...
query: sessionize is {
group_by: flight_date is dep_time.day
group_by: carrier
aggregate: daily_flight_count is flight_count
nest: per_plane_data is {
top: 20
group_by: tail_num
aggregate: plane_flight_count is flight_count
nest: flight_legs is {
order_by: 2
group_by: [
tail_num
dep_minute is dep_time.minute
origin_code
dest_code is destination_code
dep_delay
arr_delay
]
}
}
}
https://looker-open-source.github.io/malloy/documentation/ex...It's horrible btw. You can't even tell if and when order in this syntax is important.
It's also not clear if it's declarative or operational syntax. But since they are compiling to SQL it has to be the first. Yet the syntax strongly misleads people into assuming a particular execution strategy.
Not even naming of things is consistent (why shorten "array" into "arr" but not minute into "min").
It just looks like random syntax choices, without a cohesive rationale made by people that think the declarative syntax of SQL looks worse than for-loops, completely ignoring that the database will not execute anything the way it is structured here.
I don't believe it shortens "array" to "arr", does it? "Dep" and "arr" here seem to mean departure and arrival, which I'm reasonably sure is usual for the domain (flights).
That’s because MIN() is minimum?
> it just looks clunky and way too verbose.
Surely you need to compare this with the equivalent SQL before claiming that the SQL is cleaner? What would be the equivalent SQL.
> To me this has the verbosity of C whereas SQL is clean like Python (non-typed python).
Is this just a reaction to curly braces?
How does aggregate know what function to use? The examples on the aggregate page actually list aggregate functions, but everywhere else it's just... magically decided?
It supports TOP or LIMIT, but where's the windowing? Where's OFFSET 100 ROWS FETCH NEXT 25 ROWS ONLY for page 5?
What the heck does "order by: 2" mean? Even if it's an ordinal position, that's not a great example. Yes, SQL technically allows you to use ordinal positioning of columns in the ORDER BY, but it's horrible practice to use that because it's difficult to maintain. There's no way to tell what the original intent was, and the output columns change all the time when queries are reused.
My real question, however, is: "How is this actually easier?". Yes, sure, using symbols instead of English words is shorter, and a lot of programmers mistake a lower character count for being easier. However, it's not actually easier. It's just a bit less typing.
1) Nesting builds nested results (like GraphQL). This is particularly hard to do in SQL but is allows very large complex data sets to be returned in a single query.
https://looker-open-source.github.io/malloy/documentation/la...
For example the dashboard on the page below is a single SQL query:
https://looker-open-source.github.io/malloy/documentation/ex...
> How does aggregate know what function to use?
You can pre-define calculations with 'measure:' or decalre them explicitly in a query.
> where's the windowing
It's missing with a bunch of other things (like union for example). Its coming of course. The goal is that everything represent able in SQL is represent able in Malloy.
> heck does "order by: 2" mean
Same thing as it does in SQL. We try and have reasonable defaults.
https://looker-open-source.github.io/malloy/documentation/la...
> "How is this actually easier?"
The goal here is to be able to create data models that are re-usable and compose-able and verifiable. Yeah, there is a learning curve as there is with anything powerful. There are many things expressible in Malloy that cannot be easily expressed in SQL.
https://looker-open-source.github.io/malloy/documentation/pa...
Here is the SQL we generate.
https://gist.github.com/lloydtabb/8c144d2dac978dda9bf3ec4d6b...
[{
flight_date:
carrier:
daily_flight_count:
per_plane_data: [
{
tail_num:
plane_flight_count:
flight_legs: [
And so on.But I can’t help but feel like this is basically a different way to describe the same constructs as we have in SQL. It almost feels like a query builder’s syntax.
To me, the real improvements over SQL are when they part ways with its constructs, such as seen in for example Datalog.
Feels that it's worth giving a try.
I love database where queries and commands are not declarative but imperative. Like RethinkDB or Mongo.
Databases with this type of syntax.
But to use this syntax for an SQL database is a horrible mistake, because it is misleading.
> It compiles to SQL, so the actual execution plan is as arbitrary as the SQL this compiles to.
Yes, I'm purely talking syntax. I find the syntax of SQL to be arbitrary. Do I need a single quote or two? Do I need parentheses here? Or double parentheses? What does this bind, exactly?
I believe that there is lots to be gained by making the syntax more regular, without affecting semantics.
It begs for examples of the ugly/verbose/complex SQL and the beautiful/succinct/simple Malloy. Looking at the samples folder did no work for me.
Think of a sales orders table. Think of all the orders in there that should be considered "invalid" for some reason or another.
It would be awesome to define some logic, one time, in one place, for "invalid orders" and then have end users be able to say "from invalid orders", "stores having no invalid orders", "customers with multiple invalid orders", "top 3 reasons orders are invalid" ...
And of course "valid orders" might just be defined as "not invalid orders"
Instead this is probably multiple views, CTEs, UDFs, and still some logic in the main query to handle NULLs or joins or whatnot.
Even little things like hierarchies - I don't want to have separate sprocs for salesByCountry, salesByRegion. salesByState,and then an umbrella dynamic sproc to figure out which one to call.
It's ironic because SQL is such a human friendly declarative language that it has such poor ability to create meaningful shorthand expressions.
I've written SQL for nearly 30 years, I love it, but natural language transpilers have shown me some of its limits as an expressive tool.
It's a separate system, which has downsides. As an upside, by being a component of your system, the integrations with monitoring, alerting, quality checks, and dashboards is usually pretty easy.
It should all be in one SQL-like DSL with a natural language transpiler on top.
(Edited for clarity.)
you can use CTEs but only with one query
Don't e.g. Postgres temporary views cover this case?
"Temporary views are automatically dropped at the end of the current session."
I expect vendor specific stuff called something along the lines of temporary view would do this, yes
All these languages that compile to SQL seem to forget one fundamental problem, when this stuff fails (queries becomes slow etc). We are left to debug auto-generated SQL, which is a complete nightmare..
My first inclination when hitting slow malloy (if I ever were to use it) wouldn't be to look at the auto-generated SQL, but to analyze a query plan directly, much like I would be doing for a slow SQL query.
What query plan? The one belonging to the auto-generated SQL? Then fiddle with Malloy in hopes of it writing better SQL to avoid the bottlenecks?
Very few technologies have had the staying power that SQL still holds.
SQL is a syntax for queries, and it is just bad at some sides. Global-only scoping, issues with common expressions, excessive roundtrips, inability to fetch hierarchical data effectively. Even syntactically it is an IDETIFICATION DIVISION-style spells, whose structure is hard to feel.
This isn't a new language, its a layer on top of a language that already works, and works well.
SQL DDL, on the other hand, is broken as a standard because it assumes implementation details of the database engine that were widely true when it SQL was designed but are nonsensical or increasingly divergent in modern database engine architectures e.g. the many tacit assumptions about index properties.
The majority of it is taken up telling me what it is and how to install and configure their VS Code extension, but not a single “ah-ha that seems interesting” example to entice me to try it.
https://looker-open-source.github.io/malloy/documentation/la...
https://looker-open-source.github.io/malloy/documentation/la...
That is the one thing that I miss in SQL. I find it extremely wasteful (developer hours) that every SQL query needs to redefine the whole relational model from scratch. The RDBM knows the model, it should use that knowledge to automate the necessary joins.
In my opinion, you'll have to create a language that compiles to SQL that is better than handwritten SQL and is easier to write, just like writing in C is easier and gcc can create better asm than you.
The problem is that ASM_SQL is easy to learn and write and has a lot of features, so that this new C_SQL must be even easier to learn and write and/or a lot more powerful.
It's a high bar to overcome and reordering and renaming SQL things is not going to make it.
Most relational databases mostly don't run on SQL anymore, that is a legacy interface that is exported for compatibility. Unfortunately, that is still the only vaguely portable programming interface and everyone knows it, so that's what we use.
In SQL, "X INNER JOIN Y ON something" is a well-behaved table-type value that can directly replace "X" in a query and can be nested in further joins.
Here I must name a join, as if it is a property of a table, and it isn't clear what I'm joining and selecting exactly.
In the last 10 years of my career, many a dev & prod databases have been accidentally harmed by an overzealous query.
This could also add a warning for "left-over" non-updated rows, for example if the developer signals that only one row should be updated, but the WHERE clause has many rows, its usually a sign of a missing unique key, something I've seen before as well.
So you change:
1. What I want
2. Which tables
3. Which filter
4. What grouping
Putting what you want further down the list might be more confusing rather than less. (a + b) where
a = … * c,
b = … * sqrt(2) + d
c = …,
d = … …;
But that is not less confusing, that is more. I need eggs, flour, sugar and vanilla from the supermarket.
Vs Yoda From the supermarket eggs, flour, sugar and vanilla I need.
The original use case has long failed, but here we are with SQL stockholm syndrome. I don't hate it, but strictly speaking it is a bit odd.Edit: there was a linguist in the group that developed SQL to help with the goal of making it easier for non programmers.
[0] https://www.mcjones.org/System_R/SQL_Reunion_95/sqlr95-Syste...
Double so if they did bother to make many long claims about it being superior.
If there is anything here, the communication is really bad.
1. Start with a hello world example.
2. Add a concrete comparison (i.e. an example in both Malloy or SQL) for each claim.
For now, you are just wasting people's time releasing this like this.
All tell, no show? It's vaporware.
https://looker-open-source.github.io/malloy/documentation/la...
https://looker-open-source.github.io/malloy/documentation/la...
Specifically dataframe logic is easily mappable to dbplyr https://dbplyr.tidyverse.org/articles/sql-translation.html for those that know R and ibis https://ibis-project.org/ for Python/Pandas
For the first issue, this language has a non-standard syntax. It doesn't use JSON or XML. So either I have to write a parser on my own, or Google has to provide parsers in every language. Also, models are expressed as "explores" [1] where they define the fields available, and the query to use to get the data. But that's not what I expect from a modeling language. The purpose of modeling languages is to enable users to write new ad-hoc queries on the fly. If the queries have to be pre-written into an "explore" then this is not really a modeling language, it is just a query language.
I don't see this taking off as a modeling language.
[1] https://looker-open-source.github.io/malloy/documentation/la...
In mine, the lang IS actually composable:
for p in products ?where #price > 0.0 do
print(p)
end
let top10 = products ?limit 10
let positive = ?where #price > 0.0
for p in top10 ?positive do
print(p)
end
BTW, this is not new. This is more or less how was with FoxPro (with more verbose syntax, but same feel).Instead this, like many other attempt, make "relational language" be embarrassed to be an ACTUAL programming language. And it looks more like a clone of GraphQL than of SQL, btw...
As far as the "next SQL" goes, my hunch is that we should learn our lesson from the various ETL tools that became popular in the last two decades and base it on infinitary stream algebras, it seems like it's the correct computational model to deal with generic, potentially non-uniform data. (I'm afraid I don't have the chops to argue the idea further, though --)
Automatic generation of nested JSON results is very interesting:
https://looker-open-source.github.io/malloy/documentation/la...
"Better" is a dubious claim, and there wasn't much information to compel a passerby of the claim.
Though, some more examples with real-world use cases would be good.