by subset on 12/22/22, 12:28 PM with 316 comments
by dagss on 12/22/22, 3:18 PM
It's quite another when experienced seniors ban the use of SQL features because it's not "modern" or there is an architectural principle to ban "business logic" in SQL.
In our team we use SQL quite heavily: Process millions of input events, sum them together, produce some output events, repeat -- perfect cases for pushing compute to where the data is, instead of writing a loop in a backend that fetches events and updates projections.
Almost every time we interact with other programmers or architects it's an uphill battle to explain this -- "why can't just just put your millions of events into a service bus and write some backend to react to them to update your aggregate". Yes we CAN do that but why do that it's 15 lines of SQL and 5 seconds compute -- instead of a new microservice or whatever and some minutes of compute.
People bend over backwards and basically re-implement what the databases does for you in their service mesh.
And with events and business logic in SQL we can do simulations, debugging, inspect state at every point with very low effort and without relying on getting logging right in our services (because you know -- doing JOIN in SQL is not modern, but pushing the data to your service logs and joining those to do some debugging is just fine...)
I think a lot of blame is with the database vendors. They only targeted some domains and not others, so writing SQL is something of an acquired taste. I wish there was a modern language that compiled to SQL (like PRQL, but with data mutation).
by Jupe on 12/22/22, 1:16 PM
With that said, the JOIN is a very powerful concept which, unfortunately, has been given a terrible reputation by the NoSQL community. Moving such logic out of the database and into to DB's client is just a waste of IO and computing bandwidth.
SQL has been the ONLY technology/language that has stuck with me for > 25 years. The fact that it is (apparently) not being taught by institutions of higher learning is just a shame.
by phamilton on 12/22/22, 2:25 PM
While the original example of not understanding JOIN might just be a lack of of general knowledge, the later steps are great examples of this, especially if someone else comes along and is told to fix the error.
Making something execute slow code in parallel is pretty easy to do generically. It doesn't require understanding much about the slow code. It's fairly low risk, you probably won't have to tweak tests, there won't be additional side effects. The major risks will be around error handling and it's easy to turn a blind eye to partial success/failure and leave that as a problem for a future team. You can confidently build the parallel for loop, call the task done and move on.
Striving for a deeper understanding requires a lot more effort and a lot more risk. Re-writing the slow code is a lot more risk. All side effects must be accounted for. Tests might have to be re-written. The new implementation might be slower. The new index might confuse the query planner and make unrelated queries slower somehow. It's not just a matter of investing time, it's investing energy/focus and taking on risk. But the result will have comparatively fewer failure modes, it'll be cheaper to operate and less likely to have security implications.
I've been in both spots and while I wish I could say we always went with the deeper understanding that wouldn't be an honest statement. But the framing has been really helpful, especially as I work with other execs in the company to prioritize our limited resources.
by yyyk on 12/22/22, 1:25 PM
It's the 'all signup errors warranted paging the on-call even on 4am' bureaucratic decision followed by being unable to apply any fix quickly. No surprise the author did not stay.
by rubyist5eva on 12/22/22, 2:07 PM
The NoSQL people have really done a lot of brain-damage to this industry.
It's so pervasive that I've starting using this kind of question in our technical interviews, doing a double round-trip ends the interview for anyone higher than a junior.
by acdha on 12/22/22, 5:52 PM
I knew something was off performance-wise since the entire product catalog was only on the order of tens of thousands of records. As soon as I looked at the source code, the mystery was explained: they had allegedly experienced 3 developers working on it but none of them knew about SQL WHERE constraints! Instead, they were doing nested for loops to repeatedly retrieve every row of every table and doing the equality checks in VBScript. Finishing the rest of the project backlog took me a couple of days and the customer was quite happy that the slowest pages were now measured in hundreds of milliseconds rather than tens of minutes.
I was proud of how quickly we were able to turn that project around but the PM & I were discussing how even our rush rate wasn't enough to get us anywhere close to the amount of money the previous contractors had charged.
by funstuff007 on 12/22/22, 1:54 PM
Upvoted just because of the chuckle this gave me.
by btown on 12/22/22, 1:55 PM
How does one JOIN across not just tables but opaque services, in the general case? Or does every team doing microservices silently expect that one day a data team will start querying for a massive number of records-by-ID from every service, and the veterans in each team plan for this load pattern accordingly?
by Ayesh on 12/22/22, 2:01 PM
I find SQL, Regular Expressions, DNS, Client-side caching, CORS, TLS, and a few other things to be a MUST when hiring people, because most of the over-engineered crap can be avoided with a little bit of expertise with these. I spend most of my semi-leisure time with some good Regex books and golfing too.
Modern databases are amazing. Every few months, I take pleasure and not shy away in refactoring some complex and frequent queries into SQL views, carefully replace data logic (but not business logic) into stored procedures, and replace certain batch scripts with one-off queries.
by icedchai on 12/22/22, 6:09 PM
by pier25 on 12/22/22, 3:33 PM
I'm certain Mongo only became popular because of this even though for many years it was crap.
That said I do think we need a better SQL. It's still not there but EdgeDB looks very promising.
by Thaxll on 12/22/22, 1:37 PM
by nightpool on 12/22/22, 3:29 PM
by darepublic on 12/22/22, 3:18 PM
by Nihilartikel on 12/22/22, 9:34 PM
DuckDB and Apache spark expose nice apis that almost completely remove the need to faff around with textual strings. Each projection returns a view that can be treated like another table, so composition and reuse is simple.. It would be nice if such a thing we're more standard and available on the other dbms that I have to work with.
I feel like, in the continuum of abstraction, SQL is like opengl 3.. high level and a bit inflexible. Taking the analogy further, an ORM would be like the game engine on top of opengl.. What doesn't exist, as far as I know, is the Vulkan equivalent. A low level, api that exposes the relational algebra and exactly how to execute it. There are cases where I would have saved a lot of effort if I could just write the damned physical plan for a query execution myself rather than rearranging table join orders and sending hints that the query optimizer is just going to passive aggressively ignore anyway.
by bayesian_horse on 12/22/22, 3:03 PM
by LudwigNagasena on 12/22/22, 2:16 PM
by jeffreygoesto on 12/22/22, 2:43 PM
Haha, so true. We triggered a static code analyzer error "Cyclomatic Complexity bigger than 1.000.000.000!". The vendor was very interested in that code snippet (generated classifier code) and we shared a good laugh.
by Ensorceled on 12/22/22, 3:00 PM
by johnthuss on 12/22/22, 4:08 PM
This is good advice. Share your code early and often so you can get feedback before you're fully committed to one approach.
by data-ottawa on 12/22/22, 2:29 PM
On a recent project I needed to process a couple years of data for a hard deadline of Monday, and it was Friday. Our DB had a query timeout and a resource memory limit which blocked doing the full analysis without building new data models which would take days to get shipped and to build the new data models. The deadline couldn’t be moved so hacks were needed.
The solution: write some Python code to generate one query per week of data going back two years (over 100 queries), save the results to individual scratch tables, and then use a second query to union all the results together in our BI tool.
Of course the first time I ran it serially it was too slow, so I parallelized it. That was too many queries so I added a limit. Then one query failure broke the whole thing so I added retries… by the end of the day it looked exactly like this article.
It worked though! I got all the data we needed processed for Monday, I presented it to our execs and our project was approved. We only needed to manually run that script once more before I built the real solution and deleted the script.
by im3w1l on 12/22/22, 4:53 PM
In this case, doing the join manually isn't a huge deal, chunking isn't a huge deal, parallel requests isn't a huge deal. But "concurrent limit reached" is the point in this story where Bob should have put on the thinking cap and reasoned that "this shouldn't be hard, other people do things like this with bigger datasets all the time, I wonder how". Before that point it's literally just a matter of changing a couple lines to solve the issue. So what? After that point however, it's starting to affect the overall design around it in harmful ways, and turning the issue into a bigger one.
by outsidetheparty on 12/22/22, 2:28 PM
by gsvclass on 12/22/22, 10:49 PM
Shameless plug but this was my motivation behind building GraphJin a GraphQL to SQL compiler and it's my single goto force multipler for most projects. https://github.com/dosco/graphjin
by Arwill on 12/22/22, 6:09 PM
This applies to graphics programming very well, its not a question that you wouldn't be making your own pixel rasterizer instead of using DX, OpenGL or Vulkan, for example.
The big recognition is that when doing business apps, SQL database functionality is the underlying API, and you should prefer using that.
by ivanhoe on 12/22/22, 6:39 PM
by LAC-Tech on 12/22/22, 9:30 PM
The technical capabilities are all there on the team, from description. What was probably missing is someone both technical and assertive, who could politely say to the deadline setters "This is fucking stupid and it's not going to work".
by tmp60beb0ed on 12/22/22, 7:42 PM
Why junior SWEs and not all SWEs?
by jmull on 12/22/22, 4:58 PM
The article explains how the original bad code gets checked in which seems plausible enough.
But that doesn't explain why the first fix wasn't to just start using a JOIN? Or the second fix.
I guess it's a made up story, to make a point? Anyway, I found the plot holes distracting.
by tantaman on 12/22/22, 7:19 PM
by phendrenad2 on 12/22/22, 6:01 PM
by brightball on 12/22/22, 6:51 PM
How much does this problem grow and spread the longer it goes unfixed?
by tomerbd on 12/22/22, 4:47 PM
by jmartrican on 12/22/22, 8:02 PM
by bjornsing on 12/22/22, 2:07 PM
by mgaunard on 12/22/22, 9:19 PM