HNHacker News
TopNewBestAskShowJobs

ttfkam

1,995 karma · joined May 20, 2020

Databases and web and stuff.
submissionscomments
ttfkam··on QueryLeaf: SQL for Mongo
Would much rather have "Mongo" for SQL like this:

https://github.com/microsoft/documentdb

I am skeptical that SQL with Mongo backing it would be at all performant except in the most trivial cases. On the flip side, Postgres's jsonb indexing makes the inverse very doable.

ttfkam··on PostgreSQL 18 Beta 1 Released
> Allow generated columns to be virtual, and make them the default

Yes!!!

> Add OLD/NEW support to RETURNING in DML queries

Wow! That's a feature I'd never considered and now can't imagine living without moving forward. Kudos to the team!

ttfkam··on Matt Godbolt sold me on Rust by showing me C++
Lord, grant me the confidence of this man who claims objective understanding of what does and does not constitute "good code".
ttfkam··on Matt Godbolt sold me on Rust by showing me C++
C++ compiles quickly? News to me.
ttfkam··on Matt Godbolt sold me on Rust by showing me C++
Yes, Rust compiling is slow. Then again, I wouldn't say that C++ is exactly speedy in that area either. Nor Java. None of those are even in the same zip code to Go's compile speed.

So if you're cool with C++ or Java compile times, Rust will generally be fine. If you're coming from Go, Rust compiles will fell positively glacial.

ttfkam··on Matt Godbolt sold me on Rust by showing me C++
I liked checked exceptions. I just think they were overused. Had a CS prof that summed up the optimal case like this:

Programmer's fault: runtime exception

Not programmer's fault: checked exception

Reading from a file but the disk fails? Not programmer's fault. IOException (checked). Missed a null somewhere? Programmer's fault. NullPointerException (unchecked).

ttfkam··on Matt Godbolt sold me on Rust by showing me C++
The Result type works for an awful lot of people. Be careful with absolute statements like "does not work." When it works for many others, they might just assume it's a skill issue.
ttfkam··on Matt Godbolt sold me on Rust by showing me C++
It's also highly dependent upon the team's skill and diligence. You can easily ignore errors and skip error handling in Go with predictably hilarious results.

In Rust, you can't just skip error handling. You have to proactively do something generally unwise (and highly visible!) like call .unwrap() or you have to actually handle the error condition.

Go still relies on goodwill and a good night's sleep. The Rust compiler will guard against laziness and sleep deprivation, because ultimately programming languages are about people, not the computers.

ttfkam··on Waiting for Postgres 18: Accelerating Disk Reads with Asynchronous I/O
Apples to apples, Postgres might lose, but that'd be tying both hands behind its back first.

Remember that Postgres's feature set is far larger than those alternatives. If you can use a range with an exclusion constraint, an unnest with an array, or the like, you'll be seeing Postgres leave the alternatives in the dust.

Imagine writing a benchmark comparing programming languages, but the benchmark only includes idioms that all tested languages shared in common. Wouldn't be a fair comparison, would it?

ttfkam··on Waiting for Postgres 18: Accelerating Disk Reads with Asynchronous I/O
If the engineering demand is lower than the engineering supply, you're still winning. If your transactions per second only amounts to 60% of the Pi's capacity for a given use case, why complain?
ttfkam··on Waiting for Postgres 18: Accelerating Disk Reads with Asynchronous I/O
Which is why most folks use CloudFront like AWS recommends, which is typically free for services to route through. Prices for CloudFront egress are competitive with what you described for other vendors. I don't know anyone paying $90/TB out to internet on AWS.

https://aws.amazon.com/cloudfront/pricing/?nc=sn&loc=3

Were you trying to route S3 directly out to the internet?

ttfkam··on The case against restarting Three Mile Island's Unit-1
AI runs 24/7, not just when the Sun is shining and the wind is blowing. If folks want to put build out limits on AI, that's an option I guess (not a good one IMO). However if AI computation is going to continue to grow, it'll need constant consistent power at all hours.

So we can reuse old reactors with the knowledge gained over the last 50 years of operating nuclear plants or we can have these AI engines running on burning fossil fuels when the renewables aren't at capacity.

1. Stop AI build out in the US

2. Reuse old nuclear reactors

3. Expand fossil fuel plant usage

That's it. Those are the options. Battery storage won't get renewables over the finish line here. Solar and wind should absolutely be in the mix and doing their part in transferring supply away from fossil fuels. Personally I consider global climate change to be the largest threat of our time. Anything that worsens that threat rather than being either neutral or reducing it is a non-starter to me.

"Perfect is the enemy of good."

ttfkam··on Runtime-Extensible SQL Parsers Using Peg
I'm not sure that was their position. They're not saying tech from the 60s was inherently bad. They specifically mentioned that we today are not constrained by the same hardware restrictions that gave rise to the software in the 1960s. Those are two very different positions.

For example, I like Rust. But if Rust had been introduced as-is fifty years ago, no one would have used it, because the hardware requirements to make Rust compilation practical simply didn't exist yet. Taking a week just to compile "hello world" would have been a nonstarter. Not because Rust is bad but because hardware requirements at the time ruled something like it out.

2024 is not 1964 however, and it's always good to re-examine old assumptions.

ttfkam··on jQuery UI
Party over, oops, out of time!

Tonight we're gonna party like it's the year 2009!

ttfkam··on Frosted glass from games to the web
I have the same perspective regarding bandwidth, but I also consider any client to be running on a computer at least ten years old and at least three OS revisions behind.

I like to consider myself a guest on a client CPU, GPU, and RAM. I should not eat all their food, leave an unflushed turd in their toilet, and hog the remote control. Be a thoughtful guest that encourages feelings of inviting me back in the future.

Load fast, even when cell coverage is marginal. Low memory so a system doesn't grind to a halt from swapping. Animate judiciously because it's polite. Good algorithms, because everyone notices when their cursor becomes jerky.

ttfkam··on Why does everyone run ancient Postgres versions?
Contrary to intuition, bigint ends up only 25% smaller on disk than UUIDv7 and no improvement in speed. Honestly in 2024, 32-bit ints are generally a poor fit. Either the table is small enough to be considered a lookup table (16-bit int) or could grow to unknown bounds given enough time (64-bit int). Sequential ids are guessable (which could be a security issue), cannot be generated on the client, and can hinder sharding now that Postgres supports bidirectional replication (multiple writers).

https://ardentperf.com/2024/02/03/uuid-benchmark-war/

My PK preference in descending order: natural key if it makes sense and would speed up queries, 16-bit for unambiguous lookup tables with a hard finite limit of values, UUIDv7, 64-bit sequence, UUIDv4, and then finally 32-bit sequence.

UUIDv7 for performance, reasonable non-guessability, client-generation, and potential for sharding. 64-bit for cases that really need a sequence. UUIDv4 when randomness is required for security. 32-bit when there's a hard finite limit that can guaranteed to be below 2 billion even given the most optimistic of projections.

If the database is small, it doesn't matter. If it's large, it is 99.999% unlikely the primary key will be anything more than a rounding error in storage, access time, or cost. No one ever said, "We would have made payroll if only we had used 32-bit primary keys."

To really save space, extract the timestamp in the UUIDv7 and use an expression index to use as the creation date. Then you're not "wasting" any storage space. Personally I don't think the storage optimization is necessary. Premature optimization being evil and all that.

ttfkam··on Why does everyone run ancient Postgres versions?
> Easy enough: almost no one writes SQL queries by hand these days, not for querying the database nor for doing schema upgrades. It's all done by tools

Your experience does not match mine. Tools like ORMs make horrible schemas in my opinion that cater to the lowest common denominator of SQL engine functionality. This means leaving a lot of performance and scalability on the floor. In order to make the ORMs generate decent schema definitions, you need to know the underlying engine and therefore SQL. At that point, you might as well use SQL.

Ever try changing a column's data type from a table with hundreds of millions of rows with an ORM definition file? Hope you like downtime.

ttfkam··on Why does everyone run ancient Postgres versions?
> For a UUIDv4 PK

To be fair, this blows out any db that supports clustered indexes as well. Non-k-sortable primary keys are just a bad idea all around.

With UUIDv7, the WAL write amplification problem goes away just as the clustered index issues do.

ttfkam··on Why does everyone run ancient Postgres versions?
> the old central gate keeping DBA team model

I have mixed feelings about this. On the one hand I agree that ownership should be shared. On the other, app developers really don't consider their data structures as carefully in SQL as they do in-memory. It's odd. The right data structure matters more than a good algorithm since algorithms are easier to change. Once you settle on a list vs a set vs a queue, you're stuck once code is built around it.

The same is doubly true for the database schema. Lack of planning and knowledge of expected access patterns can turn an otherwise fast database to mud in no time flat. Once your data is in there, changing the schema is exponentially harder.

"I’m a huge proponent of designing your code around the data, rather than the other way around, and I think it’s one of the reasons git has been fairly successful… I will, in fact, claim that the difference between a bad programmer and a good one is whether he considers his code or his data structures more important. Bad programmers worry about the code. Good programmers worry about data structures and their relationships." – Linus Torvalds (2006)

What is your database but a bunch of data structures and relationships? I get why the gatekeeping occurred. I don't agree with it, but I understand it. Far too many folks consider expertise in data stores to be optional as developers.

ttfkam··on Why does everyone run ancient Postgres versions?
> the multi-table pipeline write pattern

        WITH new_order AS (
            INSERT INTO order (po_number, bill_to, ship_to)
                 VALUES ('ABCD1234', 42, 64)
              RETURNING order_id
        )
        INSERT INTO order_item (order_id, product_id, quantity)
             SELECT new_order.order_id, vals.product_id, vals.quantity
               FROM (VALUES (10, 1), (11, 5), (12, 3)) AS vals(product_id, quantity)
              CROSS JOIN new_order
        ;
Not super pretty, but it illustrates the point. A single statement that creates an order, gets its autogenerated id (bigint, uuid, whatever), and applies that id to the order items that follow. No network round trip necessary to get the order id before you add the items, which translates into a shorter duration for the transaction to remain open.
ttfkam··on Why does everyone run ancient Postgres versions?
I use transactional DDL all the time, even during development. It's nice to not have to fully reset your schema every time you test a migration file locally. With transactional DDL, you run the whole list, and if any fails, it rolls back to where you started. You look at the error, edit your migration, and try again. It really is a time saver. There is a peace of mind always knowing your schema is in a consistent state not unlike the peace that comes from a good set of unit tests.

1. Yep, I definitely miss clustering indexes in Postgres sometimes. I can sometimes fake it with covering indexes when all I want are an extra column or two along with the primary key or similar without seeking to the main table, but you're right about that MySQL/MariaDB win here.

2. The dynamic computed column is an easy workaround with immutable functions that take the record as a param.

        CREATE TABLE foo ( a int, b int, c int );
        CREATE FUNCTION d(entry foo) RETURNS int LANGUAGE sql IMMUTABLE AS $$
          SELECT foo.a + foo.b + foo.c;
        $$;

        SELECT a, b, c, d(foo) FROM foo;
It's not part of the table schema when doing a SELECT *, but it is just as efficient as a computed column in MySQL/MariaDB and only slightly more verbose.

3. ON UPDATE CURRENT_TIMESTAMP works in Postgres with a trigger function, which you can reuse if all your tables use the same name for your "last_modified" column (probably a good idea anyway). Not as convenient as the declarative syntax, but it's a fairly trivial workaround.

        CREATE OR REPLACE FUNCTION update_last_modified() RETURNS TRIGGER AS $$
          BEGIN
            NEW.last_modified = now();
            RETURN NEW;   
          END;
        $$ language 'plpgsql';

        CREATE TRIGGER foo_last_modified BEFORE UPDATE ON foo
        FOR EACH ROW EXECUTE PROCEDURE update_last_modified();

        CREATE TRIGGER bar_last_modified BEFORE UPDATE ON bar
        FOR EACH ROW EXECUTE PROCEDURE update_last_modified();
One function, many triggers. You also get to choose between "when transaction started" (now() or CURRENT_TIMESTAMP), "when statement started" (statement_timestamp()), or "right now" (clock_timestamp()).

I don't mind workarounds so much as functionality that simply cannot be replicated. For example I miss real temporal table support in Postgres like what you can find in MariaDB or MS SQL Server. The painful kludges for missing PIVOT support like in MS SQL Server is another one.

You never know how much you need deferred foreign key constraints until you don't have them anymore. Or a materialized view.

ttfkam··on Why does everyone run ancient Postgres versions?
I hear you.

When all you know is an ORM, you tend to treat SQL databases like dumb bit bucket add-ons to your app server. It's amazing how much potential performance and scalability are left on the floor because app developers can't shift their mindset when needed. Objects/structs cannot be assumed to map 1:1 with relations. What a world we'd live in if devs spent even 1/10 the effort examining their relational schema design that they spend arguing over whether a set, a list, or a queue is better for a given situation. It's like thoughts on Big-O stop cold at the database driver interface.

ttfkam··on Why does everyone run ancient Postgres versions?
Yep, that was our strategy as well: just keep iterating until the script run cleanly from start to finish without errors.
ttfkam··on Why does everyone run ancient Postgres versions?
> JSON can often be used in place of arrays

This is like storing UUIDs as text. You lose type information and validation. It's like storing your array as a comma-delimited string. It can work in a pinch, but it takes up more storage space and is far more error prone.

> convenience types for ipv4, ipv6, and uuid.

That's nice to see. A shame you have to decide ahead of time whether you're storing v6 or v4, and I don't see support for network ranges, but a definite improvement.

> MariaDB supports RETURNING.

That's honestly wonderful to see. Can these be used inside of CTEs as well for correlated INSERTs?

ttfkam··on Why does everyone run ancient Postgres versions?
You think people choose Postgres because it's the incumbent? That's an… interesting take.
ttfkam··on Why does everyone run ancient Postgres versions?
Upgrading from v11 to v16 is not materially different in Postgres from v14 to v16. Same tools. Same strategies.
ttfkam··on Why does everyone run ancient Postgres versions?
If you want performance to steadily increase rather than steadily decrease, the answer to your question is yes. That doesn't mean tools couldn't be better, but there are clear technical advantages to their on-disk format updates.
ttfkam··on Why does everyone run ancient Postgres versions?
Unless you want support for the MERGE command (v15), bidirectional replication (v16), and some behind the scenes optimizations, you're not really missing anything.

Whether you go from v14 to v17 or v14 to v20, I doubt it'll make a difference in migration strategy. You've still got a fair amount of time before EOL. No need to stress or FOMO.

ttfkam··on Why does everyone run ancient Postgres versions?
You're thinking only in terms of application. Types in the db save storage space, allow for better validation than plain strings, can be correlated cleanly with other columns with the same type, etc.

Yes, more drivers and libraries should support the more expansive data type list, but even just within the database itself there are multiple advantages.

ttfkam··on Why does everyone run ancient Postgres versions?
Uhh… not wanting to see emojis is a matter of taste, not engineering.
← PreviousPage 2 of 34Next →