PostgreSQL is the worlds’ best database
2ndquadrant.com
2ndquadrant.com
Out of my tries, my clients tries, and my friends tries, only one DB was up to this task. Not Maria, not Access, not Oracle, not NoSQL, not MSSQL, not MySQL - all of them failed. The only one was PostgreSQL.
And before starting to bash me, please do this. Make a small application that will show a map, put 100 million points of interest on that map, that are contained in the table we talk about, and now as you scroll the map, select the middle of view as your circle and select on a small radius only those points of interest inside that radius. No more then a thousand points of interest, lets say. When you do that within a second, you got yourself a good database. For me PGSQL was the only one capable to do this reliable.
An experienced database developer with help from "SET STATISTICS IO ON"[1] and query plans[2] can achieve incredible MSSQL query optimization results.
PostgreSQL has good query plan output via the EXPLAIN[2] statement - but I haven't (yet?) seen PostgreSQL produce per-query IO statistics.
[1] - https://docs.microsoft.com/en-us/sql/t-sql/statements/set-st...
[2] - https://docs.microsoft.com/en-us/sql/relational-databases/pe...
[3] - https://www.postgresql.org/docs/current/sql-explain.html
shared_preload_libraries = 'auto_explain'
auto_explain.log_min_duration = '5s'
auto_explain.log_analyze = true
auto_explain.log_buffers = true
auto_explain.log_timing = falseTable F.21. pg_stat_statements Columns
https://www.postgresql.org/docs/11/pgstatstatements.html
blk_read_time
double precision
Total time the statement spent reading blocks, in milliseconds (if track_io_timing is enabled, otherwise zero)
blk_write_time
double precision
Total time the statement spent writing blocks, in milliseconds (if track_io_timing is enabled, otherwise zero)
It took some brief configuration but I've been able to try it out locally and will refer to it when doing PostgreSQL query performance tuning in future.
\set track_io_timing=on;
explain (analyze, verbose, buffers) your-query;
Additionally, it will also include things like times for triggers executed from the query.
But MSSQL also has a fairy good optimizer (from the ones on the GP relation, those are the only two good options) so you can set things to get better than an unset Postgres. It is also possible (but unlikely) that you get a problem where it fits better.
About Oracle, it is pretty great on doing `select stuff from table join table using (column)`. (I dunno what it does, but it does spend a lot of memory doing it.) So if you only does that, it's the best option. But if you do anything else, that anything else will completely dominate the execution time.
On databases that have good scanning behavior you can use a geohash approach instead. Insert all points with a geohash as key, determine a geohash bounding box that roughly fits your circle, query the rows matching that geohash in their key, run a “within distance” filter on the results client-side. I used that approach in hbase and it could query really fast. I suspect it would perform well on pretty much any mainstream sql db, but admittedly I haven’t tried it.
Geohashing has a lot of weaknesses and limitations, not really recommended unless your use case is very simple and not primarily geospatial in nature. The modern version was created in the 1990s and implemented by big database companies like Oracle and IBM (based on work in the 1960s and '70s). They deprecated that indexing feature in their database engines a long time ago for good technical reasons that apply to current open source implementations.
Geospatial index performance is very sensitive to temporal and geometry distribution, and the performance variance can be extremely high. For non-trivial applications, the real world will eventually produce data that inadvertently executes a denial of service attack on naive geospatial databases.
MSSQL has a GIS package included in the basic database. I'm not sure how featurefull it is now, but last time I looked (years ago) it was missing a lot.
MySQL also has a GIS package included at the database. It's missing a lot of things.
The top of the line is, as usual, Postgres. But honestly, you probably won't need the difference.
For a reddit-like social site, we have a Maria database with around 3 billion rows in total, with the largest table (votes) spanning about 1,5 billion rows.
We can select data within ~3ms for about 20k-40k concurrent visitors on the site. Our setup is a simple Master-Slave config, with the slave only as backup (not used for selects in production). Our 2 DB servers have 128gb of RAM and cost around 200 EUR/month each - so, nothing special.
Of course you have to design your schema with great care to get to this point, but I imagine PG to be as lost as any other database if a crucial index is missing.
It's not realistic that Postgres would outclass everything else like this.
Even if they didn't, there are plenty of algorithms based on lat/lon which uses numeric/float data types with simple indexes.
Not that trivial if you're not just dealing with points.
This is a bad example. An SQL database is a wrong tool for the job if you care about performance.
You want a data structure like a range tree[1] or a k-d tree[2]. The results would be near-instantaneous.
100 million lat/lng pairs is something you can fit in RAM without any problem. And you can even do the geometry query on the client side for performance in milliseconds.
Other examples might need SQL, but here, this would be doing things the wrong way.
If you mean that nearby places have geotags with large common prefixes, then the "edge" cases there this won't work include such little-known, unpopular cities as London, UK (thorough which the Greenwich meridian passes).
That's to say, East and West London geohashes have no common prefix. The Uber driver picking you up in Greenwich will drop you off in a geohash which starts with a different letter.
To point out the obvious, the surface of Earth is two-dimensional, and a database index is one-dimensional. A solution to the 2D query problem using a 1D index is mathematically impossible (if existed, you would be able to construct a homeomorphism between a line and a plane, which does not exist).
Sure, geohashes can be used to compute the answer. But you need to know more information than just the letters in the geohash to find out which geohash partitions are adjacent to a given one. That extra information would be equivalent to building a space partitioning tree, though, and you still won't be able to use a range query to get it.
If there's an SQL range query-based approach with geohashes which compromises on correctness but is still practical, I'm all ears.
---
PS: this is a good overview of this problem:
https://dev.to/untilawesome/the-problem-of-nearness-part-1-g...
The solution there involves first producing a geohash cell covering. Of course, this means you have a BSP-like structure backed by a database.
---
PPS: the quick-and-dirty way using SQL would be keeping a table with lat / lng in different columns. It is not hard to define a lat/lng box around a point that has roughly equal sides, using basic trig.
You can filter locations outside the box with SQL, and then just loop over the results to check distances and fine-tune the answer (if needed). However, it will not be performant.
We investigated the options for LDAP and Kerberos integration, commercial and free. Turns out there is no decent way to do it and grant permissions based on LDAP groups. There wasn't even a a half decent way. The only options were way to hackish to consider. MS SQL still own the house.
One of the bigger issues with places that have made themselves dependent on MS solutions is that MS software completely permeates the place. Then when the pain of going full MS is too big, they are only looking for drop in replacements of existing parts. This will never go well. MS software never plays well with alternatives.
If you have let yourself slide too far down the slippery slope of MS Office integrations and MS Sharepoints and the like, you will have to pay the MS price. Or you have to be willing to chuck out the entire lot.
This is a common, standard requirement in enterprise systems, and it seem quite sensible. If you have a better, more robust solution, there are billions in this market, in the most literal way.
One more thing, although Active Directory is a standard in the enterprise, LDAP is an open protocol that existed before Microsoft were dreaming on being a player in the enterprise field and have at least half a dozen open source implementations.
That is precisely what I meant with messed up requirements. Why would any of your SSO be relevant on the database level? A database user should be coupled to an application, not to a single user in AD. If you are letting constantly changing users do their own SQL requests on DB level, there is something rotten in the first place.
> This is a common, standard requirement in enterprise systems, and it seem quite sensible. If you have a better, more robust solution, there are billions in this market, in the most literal way.
I have never come across this kind of setup in a normal enterprise environment. There, you have everything behind some kind of enterprise software. Data entry, auditing, etc.
However, you could have need for this if we are talking developers sharing a single database and you don't want to manage accounts and passwords separately.
You said the solutions you found for Postgres were too "hacky". I think if you have a setup where enterprise users who are not developers or DBAs need personal access on DB level, your setup is quite "hacky" to begin with.
> One more thing, although Active Directory is a standard in the enterprise, LDAP is an open protocol that existed before Microsoft were dreaming on being a player in the enterprise field and have at least half a dozen open source implementations.
Microsoft has bent LDAP and Kerberos in its own way. Trying to use AD like an LDAP server is full of unpleasant surprises dealt to you by badly documented or outright undocumented "features", and useless error messages and logging. Believe me, it's a major nightmare to get anything integrated with AD.
The hackish implementations are syncing users from LDAP to PostgreSQL, on schedule. There are more than 3 different implementations of this madness.
What was my task? Add XML export into a poorly done XML schema, and do it all in PL/SQL; the data that went into the XML was a mixture of normal queries and computed PL/SQL results.
That schema + stored procedure monstrosity sticks out in my mind as the most unholy disasters I’ve ever worked on.
If you have LAT/LON in the table as normal columns indexed you just query the bounding box of your radius so it can use the standard b-tree indexes then post filter to a circle cutting off the corners. Of curse you have to do some work to account for the curvature of the earth but this is pretty standard geospatial stuff.
If you have a DB with geospatial types and indexes like MSSQL 2008+, Oracle, PG etc then this becomes trivial as they can do this directly.
If you want to do spatial things in the database, then PostGIS for PostgreSQL or Spatialite for SQLite are definitely your best options.
For general performance, PostgreSQL is consistently excellent, but it's not the best in all cases.
A lot of users case mostly about accessibility, simplicity, integration with existing experience/tools (e.g. JSON), managability, ecosystem, etc. Those users might be happy from the start; or if they aren't happy, they complain for a while until their problem is solved, and then go silent.
Honestly, if it's taking your database more than a second to pull 1000 of 100M rows on a simple query, that means you need to figure out what's wrong with your indexes, not that your choice of database vendor is bad. It is true that postgres is a very nice database, but for basic tasks, honestly any database will be fine if you know how to use it effectively.
Demo in mysql:
-- create a helper table for inserting our 100M points
create table nums (
id bigint(20) unsigned not null
);
insert into nums (id)
values (0), (1), (2), (3), (4), (5), (6), (7), (8), (9);
-- the table in which we will store our 100M points
create table points (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
latitude float NOT NULL,
longitude float NOT NULL,
latlng POINT NOT NULL,
primary key (id),
spatial key points_latlng_index (latlng)
);
-- insert the 100M points with latitude between 32 and 49
-- and longitude between -120 and -75, which is roughly a
-- rectangle covering the continental US, placing them
-- randomly. Be patient, as it takes a while to create
-- 100M rows.
insert into points (latitude, longitude, latlng)
select
ll.latitude,
ll.longitude,
ST_GeomFromText(concat('POINT(',
ll.latitude, ' ', ll.longitude,
')')) as latlng
from (
select
32 + 17 * conv(left(sha1(concat('latitude', ns.n)), 8), 16, 10) / pow(2, 32) as latitude,
-120 + 45 * conv(left(sha1(concat('longitude', ns.n)), 8), 16, 10) / pow(2, 32) as longitude
from (
select
a.id * pow(10, 0) + b.id * pow(10, 1)
+ c.id * pow(10, 3) + d.id * pow(10, 4)
+ e.id * pow(10, 5) + f.id * pow(10, 6)
+ g.id * pow(10, 7) + h.id * pow(10, 8)
as n
from nums a join nums b join nums c join nums d
join nums e join nums f
join nums g join nums h
) as ns
) as ll;
-- Generate a roughly circular boundary polygon 7km around
-- the center of Las Vegas
set @earth_radius_meters := 6371000,
@lv_lat := 33.17,
@lv_lng := -115.14,
@search_radius_meters := 7000;
set @boundary_polygon := (select
ST_GeomFromText(concat('POLYGON((', group_concat(
concat(boundary_lat, ' ', boundary_lng)
order by id
separator ', '), '))')
) as boundary_geom
from (
select
nums.id,
@lv_lat + @search_radius_meters * cos(nums.id * 2 * pi() / 9)
/ (@earth_radius_meters * 2 * pi() / 360) as boundary_lat,
@lv_lng + @search_radius_meters * cos(@lv_lat * 2 * pi() / 360) * sin(nums.id * 2 * pi() / 9)
/ (@earth_radius_meters * 2 * pi() / 360) as boundary_lng
from nums
) t);
explain select count(*) from points where ST_Contains(@boundary_polygon, latlng)\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: points
partitions: NULL
type: range
possible_keys: points_latlng_index
key: points_latlng_index
key_len: 34
ref: NULL
rows: 987
filtered: 100.00
Extra: Using where
1 row in set, 1 warning (0.01 sec)
mysql> select count(*) from points where ST_Contains(@boundary_polygon, latlng)\G
*************************** 1. row ***************************
count(*): 1228
1 row in set (0.01 sec)Now I don’t have experience with MySQL, SQLServer, etc., but between Oracle and Postgres, Postgres is definitely the best database.
Everything that used to be a 'that is an enterprise edition feature' is now baked in.
concurrent index creation is amazing.
The simplicity and speed of pgBarman vs RMAN is mind boggling. RMAN in Oracle Standard Edition can only do full backups.
Full read-only access to a standby? That is huge! (enterprise only for the big O)
Realtime replication (not log shipping), also enterprise only for the big O.
I'm a sysadmin, so that is what I notice right away, but our developers love it too, for many other reasons.
Postgres backups work.
You can simply backup your database. And you simply restores your backup. And the result is a working database, without errors.
* Protocol: (a) no wire level named parameters support; everything must be by index. (b) Binary vs text is is not great, and binary protocol details is mostly "see source" (c) no support for inline cancellation: to cancel a query client can't signal on current TCP connection, the client must open or use a different connection to kill an existing query, this is sometimes okay, but if you are behind a load balancer or pooler this can end up being a huge pain.
* Multiple Result Sets from a single query without hacks. While you can union together results with similar columns or use cursors, these are hacks and work only in specific cases. If I have two selects, return two result sets. Please.
* Protocol level choosing of language. Yes, you can program in any language, but submitting an arbitrary query in any language is a pain and requires creating an anonymous function, which is a further pain if your ad-hoc query has parameters. I would love a protocol level flag that allows you to specify: "SQL", "PG/plSQL", "cool-lang-1" and have it execute the start of the text as that.
I do love Postgres recently added Procs! Yay!
Also true indexed organized table aka real clustered indexes.
Oh and real cross connection query plan caching, prepared statements are only for the connection and must be explicitly used. No need to use prepared statements in MSSQL since the 90's
Using UUIDs for PKs is fine and dandy but clustered indexes and type 4 UUIDs do not play well. Many MS SQL users discover this the hard way when their toy database suddenly has order of magnitudes more rows.
I wish MSSQL had this.
I'm sure if postgres had it, it wouldn't have had most of those problems.
As a database Driver/Client developer:
* Having two protocols/data types that two the same thing (text / binary) isn't the end of the world, but it just adds confusion. Also it adds complexity for a different server/proxy/pool implementation. Recommendation: better document binary and add an intent to remove text data types.
* Not having an inline cancellation (in same TCP/IP connection) means cancellation isn't supported by many drivers, and even when it is, there are many edge cases were it stops working. Each client implementation has to work around this.
As an application developer, I typically see three patterns emerge:
1. Put SQL on SQL platform: stored functions / procs. Application only calls stored functions / procs. 2. Put SQL on Application platform: simple stored SQL text, query builders. 3. Make Application dump and use simple CRUD queries and put logic fully in application.
I typically find myself in category (2), though I have no beef with (1). Benefits of (2) include: (a) easier to create dynamic search criteria and (b) use a single source of schema truth for application and database.
* Multiple Result Sets:
- (A) The screens I make often have a dynamic column set. To accomplish this I may return three result sets: row list, column list, and field list. This works for my screens and print XLSX sheets that can auto-pivot the data in, while all the data transfer columns can be statically known. and pre-declared. This allows me to edit a pivoted table because each cell knows the origin row.
- (B) Any reasonable amount of work in SQL may be long-ish (300-1000+) lines of SQL. There are often many intermediate steps and temp tables. Without Multiple Result Sets, it is difficult to efficiently return the data when there are often multiple arities and columns sets that are all relevant for analysis or work. So if I take a fully application centric view (more like application mindset (3)), you just call the database alot. But if you are more database server centric (1) or (2), this can pose a real problem as complexity of the business problem increases. (I'm aware of escape hatches, but I'm talking about strait forward development without resorting to alternative coding.)
- (C) Named parameters are extremely useful for building up query parameters in the application (development model (2)). You can specify a query where-clause snippet, the parameter name and the have the system compose it for you that is impossible with ordinal queries. A driver or shim can indeed use text replacement, but that (a) adds implementation cost and (b) server computation / allocation cost, (c) mental overhead when you see trace the query on the server. Further more it composes poorly with stored functions and procs on the server (in my opinion). It is again not insurmountable, but it is another thing that adds friction. Lastly, when you have a query that takes over 30 or 50 parameters, you must use named parameters; ordinal positioning is too error prone at scale.
- (D) Protocol level language selection. PostgreSQL always starts execution in plain SQL context. If you always execute functions as PL/pgSQL it is just extra overhead. In addition, running ad-hoc PL/pgSQL with named parameters isn't the most easy thing. It is possible, just not easy. This feature plus named parameters so by the time I'm writing my query, I know (a) that I have all my sent parameters available to me bound to names and (b) the first character I type is in the language I want.
The combination of these features would make applications developed in model (2) go from rather hard to extremely easy. It would also make other development modes easier I would contend as well.
I would note that it's required in Postgres for custom types to implement in/out (text encoding), but not required to implement send/recv (binary encoding.) In case send/recv isn't implemented, the datum falls back to using in/out even over the binary protocol.
Given the number of third-party extensions, and the ease of creating your own custom types even outside an extension, I'd expect that deprecating the text protocol will never happen. It's, ultimately, the canonical wire-format for "data portability" in Postgres; during major-version pg_upgrades, even values in system-internal types like pg_lsn get text-encoded to be passed across.
Meanwhile, binary wire-encoding (as opposed to internal binary encoding within a datum) is just a performance feature. That's why it's not entirely specified. They want to be able to change the binary wire-encoding of types between major versions to get more performance, if they can. (Imagine e.g. numeric changing from a radix-10000 to a radix-255 binary wire-encoding in PG13. No reason it couldn't.)
I don't see us removing the textual transport, unfortunately. The cost of forcing all clients to deal with marshalling into the binary format seems prohibitive to me.
What's the server/proxy/pool concern? I don't see a problem there.
> Not having an inline cancellation (in same TCP/IP connection) means cancellation isn't supported by many drivers, and even when it is, there are many edge cases were it stops working. Each client implementation has to work around this.
Yea, it really isn't great. But it's far from clear how to do it inline in a robust manner. The client just sending the cancellation inline in the normal connection would basically mean the server-side would always have to eagerly read all the pending data from the client (and presumably spill to disk).
TCP urgent or such can address that to some degree - but not all that well.
> - (C) Named parameters
I'm a bit hesitant on that one, depending on what the precise proposal is.
Having to textually match query parameters for a prepared statement for each execution isn't great. Overhead should be add per-prepare, not per-execute.
If the proposal is that the client specifies, at prepare time, to send named parameters in a certain order at execution time, I'd not have a problem with it (whether useful enough to justify a change in protocol is a different question).
> A driver or shim can indeed use text replacement ... b) server computation / allocation cost
How come?
> - (D) Protocol level language selection. PostgreSQL always starts execution in plain SQL context. If you always execute functions as PL/pgSQL it is just extra overhead. In addition, running ad-hoc PL/pgSQL with named parameters isn't the most easy thing. It is possible, just not easy. This feature plus named parameters so by the time I'm writing my query, I know (a) that I have all my sent parameters available to me bound to names and (b) the first character I type is in the language I want.
I can't see this happening. For one, I have a hard time believing that the language dispatch is any sort of meaningful overhead (unless you mean for the human, while interactively typing?). But also, making connections have state where incoming data will be completely differently interpreted is a no-go imo. Makes error handling a lot more complicated, for not a whole lot of benefit.
How would you feel about Postgres listening over QUIC instead of/in addition to TCP?
It seems to me that having multiple independently-advancing "flows" per socket, would fix both this problem, and enable clients to hold open fewer sockets generally (as they could keep their entire connection pool as connected flows on one QUIC socket.)
You'd need to do something fancy to route messages to backends in such a case, but not too fancy—it'd look like a one-deeper hierarchy of fork(2)s, where the forked socket acceptor becomes a mini-postmaster with backens for each of that socket's flows, not just spawning but also proxying messages to them.
As a bonus benefit, a QUIC connection could also async-push errors/notices spawned "during" a long-running command (e.g. a COPY) as their own new child-flows, tagged with the parent flow ID they originated from. Same for messages from LISTEN.
For all-binary, the client would have to know about all data types and how to represent them in the host language. But that seems clunky. Consider NUMERIC vs. float vs. int4 vs int8: should the client really know how to parse all of those from binary? It makes more sense to optimize a few common data types to be transferred as binary, and the rest would go through text. That also works better with the extensible type system, where the client driver will never know about all data types the user might want to use. And it works better for things like psql, which need a textual representation.
The main problem with binary is that the "optimize a few columns as binary" can't be done entirely in the driver. The driver knows which types it can parse, but it doesn't know what types a given query will return. The application programmer may know what types the query will return, in which case they can specify to return them in binary if they know which ones are supported by the client driver, but that's ugly (and in libpq, it only supports all-binary or all-text). Postgres could know the data types, but that means that the driver would need to first prepare the query (which is sometimes a good idea anyway, but other times the round trip isn't worth it).
"Not having an inline cancellation (in same TCP/IP connection)"
This is related to another problem, which is that while a query is executing it does not bother to touch the socket at all. That means that the client can disconnect and the query can keep running for a while, which is obviously useless. I tried fixing this at one point but there were a couple problems and I didn't follow through. Detecting client disconnect probably should be done though.
Supporting cancellation would be trickier than just looking for a client disconnect, because there's potentially a lot of data on the socket (pipelined queries), so it would need to read all the messages coming in looking for a cancellation, and would need to save it all somewhere in case there is no cancellation. I think this would screw up query pipelining, because new queries could be coming in faster than they are being executed, and that would lead to continuous memory growth (from all the saved socket data).
So it looks like out-of-band is the only way cancellation will really work, unless I'm missing something.
"Multiple Result Sets... you just call the database alot"
Do pipelined queries help at all here?
"Named parameters are extremely useful for building up query parameters"
+1. No argument there.
"Protocol level language selection"
I'm still trying to wrap my head around this idea. I think I understand what you are saying and it sounds cool. There are some weird implications I'm sure, but it sounds like it's worth exploring.
We return the types of the result set separately even when not preparing. The harder part is doing it without adding roundtrips.
I've argued before that we should allow the client to specify which types it wants as binary, unless explicitly specified. IMO that's the only way to solve this incrementally from where we currently are.
> Do pipelined queries help at all here?
We really need to get the libpq support for pipelining merged :(
I lucked up and ended up with a real hacker for a boss. As early as 2001-2002 he had saved entire businesses by migrating them from mysql to postgres.
He was a BSD guy and a postgres guy. He made me into a fanboy of both those technologies.
So out of sheer luck I've preferred Postgres for over 15 years, and it has never disappointed me.
Unlike BSD, which often disappointed me once I learned how much easier and mature Linux was to use.
MySql was pretty bad in the first versions. I'm in the enterprise/erp development world, and when I look at mysql when it start to show in the radar, I can't believe the joke.
MySql get good around 5? Now I can say all major DBs are good enough not matter what you chosee, (still think PG is the best around) but MySql was always the more risky proposition, the PHP of the db engines...
So far I've only setup one master/slave cluster with pgpool-II in postgres and it's definitely an OK setup. But I much prefer the usability and stability of Galera/MariaDB for clustering.
I was with you right until that last sentence. I'm not going to offer a counterargument because your statement is extremely genralised and ripe for flamewars but I will say it's not as clear cut as you stated.
With the exception of package management (at least with debian) I've found the opposite to be true. It's configuration has always been a bit of a mess, especially with regards to networking. Lately systemd has made things only more confusing. And that's before dealing with the myriad of ways different distributions do things (which thankfully now is really only 2 different bases, debian or red hat).
While linux "won" in the end and I use it professionally now, I'm glad I rarely have to interact with it directly anymore thanks to ansible or other orchestration tools.
I'm extremely curious how this worked out.
But all I know is that they had been throwing hardware on a MySQL install to make it work better.
He migrated them to postgres and they got much better performance and could get away with less hardware than they had with mysql.
That was as much detail that I remember. Keep in mind I said by sheer luck I became a fanboy. Not by experience and competence. That came later.
A database for competent users can be amazingly simple and fast. But the Market Has Spoken, loud and clear: databases must absorb an indefinitely large amount of complexity to make the job of app writers a tiny bit easier.
Can anyone recommend a good client for PostgreSQL?
[1] - I see that there have been some new releases in 2020 so I ought to check on them. The version I tried earlier was 4.11.
Native cross-platform and works across dozens of databases with lots of features.
Another option is Jetbrains DataGrip: https://www.jetbrains.com/datagrip/
I prefer to use HeidiSQL running on Wine.
I've inadvertently become the pgadmin 3 "LTS" maintainer. A release of pgadmin 3 that was altered to support 10.x was previously provided by BigSQL. I forked it on GitHub to add TCP keepalive on client connections. At some point after that BigSQL removed the original repo. Apparently I was the only one that had forked it prior to removal, so now the few vestigial users in the world still using it are forking my fork. One has even patched it to work with 11.x, although they've offered no pull requests.
Otherwise, TablePlus is cross-platform (and supports multiple DBs) https://tableplus.com/
Agreed that PgAdmin is awful.
If I didn't already have a Postico license I'd definitely be looking at TablePlus.
I use TablePlus for quickly looking stuff up when I'm working on my MacBook, but I use DataGrip when I'm working on Linux.
It's not specific to PostgreSQL, it's universal.
https://github.com/microsoft/azuredatastudio#azure-data-stud...
Bonus — it also works for MySQL/MariaDB, MS SQL, and sqlite.
It crashes constantly. Went back to HeidiSQL.
Supports many databases
Since then I'm sticking with psql for administration and with DataGrip for more involved DB development, and that works very well.
Perhaps I don't know enough about databases and their differences.
Anyone have some pros and cons of others?
Like why would I pick MySQL, Microsoft, Oracle, Maria etc over Postgres?
Apart from support that you gotta pay for.
In the same way that Golang claims it's the 90% language ( https://talks.golang.org/2014/gocon-tokyo.slide#1 ), I'd say Postgres is the perfect 90% database.
However, we're still using at least four other databases in production, and the reason why is that because it's doing something of everything, there are lots of niches that it doesn't fill well. It's all about tradeoffs.
If you've got a Full Text Search problem, PG is "good enough", that is until you need to index more challenging languages like Korean or need more exotic scoring functions. For that, Elastic is better.
You can do small scale analytics on PG, but at larger sizes, the transactional setup gets in the way and you're better off with BigQuery/Redshift/Snowflake.
You can scale vertical pretty big these days, but if you need linear scalability while still guaranteeing single digit ms access, you're better off with ScyllaDB.
However, there isn't a single project I wouldn't not start on a Postgres these days, that's how much I love it.
PG was driven by engineering correctness, by considering what DBAs 'Are Going to Need'. Sometimes that strictness worked against popular growth but in the end it has worked out well, as many programmers figured out they also needed it. I'd say the programming language analogue would likely be Rust, lets see in 10 years where the 90% case lies.
I'b be interested to know about the limits of the full text feature.
... and wins, which surprised me when I found out.
At the very least, CockroachDB is much simpler to set up and manage. Cannot vouch for its stability and complexity of abnormal emergency recoveries, though - haven't used it long enough, only had simplest outages (that it had handled flawlessly).
Just haven't had the reason to dive in yet, but seems good. Their PR department just isn't as good as CockroachDBs one.
I wonder why Postgre hasn't improved in these areas and instead leaving it to third party solution. I mean every year these few points are still listed as something that flavours MySQL.
Oracle is the choice of organisations with money to burn who don't believe that free products can be good. An Oracle installation nearly always comes with some consultants to write your application for you, and define your application for you, and write your invoices for you ...
It's not that you can't create a master-master setup using Postgresql, I believe 2ndquadrant have and add-on that allows this. It just feels like it's messing with the fundamentals of the database on such a low level that I really only trust it, if it's part of Postgresql it self.
There are naturally caveats: sequences don't get replicated, so you need to configure each replica with a non-overlapping range for each sequence. And DDL statements are also not replicated, so you have to migrate database schemas by hand on each replica.
[1] https://wiki.postgresql.org/wiki/Replication,_Clustering,_an...
- the code is not reusable outside of a database setting. So not cacheable.
- the code is not reusable accross different storage layers. So not portable.
- the code may needs updating if the schema change, you can't abstract that
- changing the logic means a db migration
- testing the code requires a DB
- tooling support to check that code si limited to SQL tooling, which is very weak, especially for code completion, refactor and debugging.
That's a lot of constraints for just making the application logic a lot simpler.
In my 23-and-a-bit years of web development I've literally never changed the database engine on a project. Maybe that happens on other people's projects, but it's not something I consider important or even useful really. The notion that you can swap out your database for a different one without changing the application code to take advantage of the db you're moving to is ludicrous. Of course your database code isn't portable.
Websites that used MySQL and Myisam tables with raw SQL statements written as strings in PHP for the first decade of the web is one of the reasons why so many web developers still don't use things like transactions, stored procedures, views, etc. That's a bit of a tragedy. The web would be much better today if everyone had been using Postgres's features from the beginning.
- it is cached, in the database’s memory, where the cache can be invalidated automatically. It is better to cache views than data anyway.
- it is portable to every platform postgres runs, which in practice means it will run everywhere. Portability between databases is overrated because it rarely happens in practice.
- the access control logic evolves together with the schema, guaranteeing they have an exact correspondence. This is a good thing.
- integration tests should involve a live database
- have you looked at jetbrains datagrip?
Historically Postgres has thought that the job of the file system, which is basically a bad choice for dbs. MyRocks wipes the floor with it.
TimescaleDB is an interesting new Postgres storage choice. I'm evaluating it. But the free version doesn't do compression on-demand nor transparently. Anyway, it can only get better.
https://www.timescale.com/products/features https://docs.timescale.com/latest/using-timescaledb/compress...
(The "community" edition is available under our Timescale License. It's all source available and free-to-use, the license just places some restrictions if you are a cloud vendor offering DBaaS.)
In my use cases I have got recent partitions that are upsert heavy, so row-based works best. But as the partitions age, column-based would be better. What every DB seems to force me to do is use the same underlying format for all partitions. What I’d like is a storage engine that automates everything; instead of me picking partition size, it picks on the fly and makes adjustments. Instead of me picking olap vs oltp, it picks and migrates partitions over time etc.
I think that if timescaledb can support time-based or mru-based compression and even row-store partitions then it would take things to the next level.
https://stackoverflow.com/questions/1369864/does-postgresql-...
MySQL's innodb, for example, supports per-row-compression. Its completely ineffective. Block compression in tokdub and myrocks etc is a completely different class.
MySQL's innodb also supporta kind of 'page compression' using the file-system's sparse pages. Its also naff.
The closest postgres can get is using zfs with compression. Its a lot better than nothing.
PG sure seems to have better foundations and generally a more engineered approach to everything. This leads to some noteworthy outcomes in the tooling or the developer UX, for example: PG won't allow a union type (like String or Integer) in query arguments. PGs query argument handling is rather simple (at least the stuff provided with libpq), it only allows positional arguments.
Sometimes, MySQL by extending or bending SQL here and there allows for some queries to be written terser, like an update+join over multiple tables. Also I did actually enjoy that MySQL had less advanced features, so it seemed to be easier to reason about performance and overall behaviour.
And in plenty of situations, sqlite is perfectly adequate, and saves you from the extra work of managing yet another service.
But yes, I agree if I'd start from a blank sheet and need a network-accessible SQL DB, pgSQL would be my first choice. Now if I had some very high end requirements, maybe one of those big commercial DB's would have an advantage.
Large companies use some of everything, but I never saw PG in use there.
Yahoo’s use of Postgres was legendary.
We also have other DB tech in the company: Teradata, Oracle, Redis, Cassandra.
I self-admittedly love esoteric databases and storage engines to a fault. I'll try to shoehorn things like RocksDB into whatever personal project I'm working on.
At work however, the motto I spread to the teams I work on is "use Postgres until it hurts". And for many, many teams - Postgres will never hurt. I'm very happy for its continued existence because its been a solid workhorse on various projects I've worked on over the years.
BTW, here's an interesting observation: if you normalize a schema to the max, applying CRDT techniques for eventually-consistent multi-master concurrency is relatively simple, and you can do it using SQL. With PG you could have each instance publish a replication publication of an event log, and each instance could subscribe to a merged log published by any of N instances whose job is to merge those logs, and then each instance could use the merged log to apply local updates in a CRDT manner. If you normalize to the max, this works.
For example, instead of having an integer field to hold a count (e.g., of items in a warehouse of some item type) you can have that many rows in a related table to represent the things being counted. Now computing the count gets a bit expensive (you have to GROUP BY and count() aggregate), but on the other hand you get to do CRDT with a boring, off-the-shelf, well-understood technology, with the same trade-offs as you'd have using a new CRDT DB technology, but with all the benefits of the old, boring technology.
Any interesting notes and observations after using those esoteric tools?
It can also be challenging to accurately assess a database's performance and correctness. I've been using C/Rust bindings when possible for the former, and Aphyr's Jepsen test results for the latter. Unfortunately there's no silver bullet on these topics - you pretty much have to test all your use cases.
This is a side-effect of the old-school one-process-per-connection architecture that Postgres uses. MySQL (ick) easily handles thousands of connections on small servers; with Postgres you will need a LOT of RAM to sustain the same, RAM that would be better served as cache.
I've found (at least, for my current app) that the number of connections defines my scaling limit. I can't add more appserver instances or their combined connection pools will overflow the limit. And that limit is disappointingly small. It's not so painful that I want to reach for another RDBMS, but I'm bumping into this problem way too early in my scale curve.
How I understood the problem is thousands of connections, of which most do a query from time to time only.
Judging by the other comments, it seems solutions like that are already available.
There honestly doesn't seem to be a good solution to this problem. I have reorganized my app a bit to try to keep the transactions shorter (mostly checkpointing) but it's using architecture to solve a fundamentally technical problem. I wouldn't have this problem with MySQL.
Switching from processes to threads (or some other abstraction) per connection isn't likely to show up in Postgres anytime soon, so I guess I'm willing to live with this... but I'm not going to pretend that Postgres is without some serious downsides.
The per-connection memory overhead is not actually that high. If you configure huge_pages, it's on the order of ~1.5MB-2MB, even with a large shared_buffers setting.
Unfortunately many process monitoring tools (including top & ps) don't represent shared memory usage well. Most of the time each process is attributed not just the process local memory, but all the shared memory it touched. Even though it's obviously only used once across all processes.
In case of top/ps it's a bit easier to see when using huge pages, because they don't include huge pages in RSS (which is not necessarily great, but ...).
Edit: expand below
On halfway recent versions of linux /proc/$pid/smaps_rollup makes this a bit easier. It shows shared memory separately, both when not using huge pages, and when doing so. The helpful bit is that it has a number of 'Pss*' fields, which is basically the 'proportional' version of RSS. It divides repeatedly mapped memory by the number of processes attached to it.
Here's an example of smaps_rollup without using huge pages:
cat /proc/1684346/smaps_rollup
56444bf26000-7fff2d936000 ---p 00000000 00:00 0 [rollup]
Rss: 1854392 kB
Pss: 235614 kB
Pss_Anon: 1420 kB
Pss_File: 274 kB
Pss_Shmem: 233919 kB
Shared_Clean: 10700 kB
Shared_Dirty: 1837560 kB
Private_Clean: 0 kB
Private_Dirty: 6132 kB
Referenced: 1853428 kB
Anonymous: 2664 kB
LazyFree: 0 kB
AnonHugePages: 0 kB
ShmemPmdMapped: 0 kB
FilePmdMapped: 0 kB
Shared_Hugetlb: 0 kB
Private_Hugetlb: 0 kB
Swap: 0 kB
SwapPss: 0 kB
Locked: 0 kB
You can see that RSS claims 1.8GB of memory. But the proportional amount of anonymous memory is only 1.4MB - even though "Anonymous" shows 2.6MB. That's largely due to that memory not being modified between postmaster and backends (and thus shared). Nearly all of the rest is shared memory that was touched by the process, Shared_Clean + Shared_Dirty.With huge pages it's a bit easier:
cat /proc/1684560/smaps_rollup
55e67544d000-7ffecebc9000 ---p 00000000 00:00 0 [rollup]
Rss: 13312 kB
Pss: 1671 kB
Pss_Anon: 1397 kB
Pss_File: 274 kB
Pss_Shmem: 0 kB
Shared_Clean: 10656 kB
Shared_Dirty: 1292 kB
Private_Clean: 0 kB
Private_Dirty: 1364 kB
Referenced: 12312 kB
Anonymous: 2656 kB
LazyFree: 0 kB
AnonHugePages: 0 kB
ShmemPmdMapped: 0 kB
FilePmdMapped: 0 kB
Shared_Hugetlb: 1310720 kB
Private_Hugetlb: 2379776 kB
Swap: 0 kB
SwapPss: 0 kB
Locked: 0 kBPostgres is still laid out for for 9 to 5 workloads, accumulating garbage during the day and running vacuum at night. Autovacuum just doesn't cut it in a 24/7 operation and it is by far what has caused the most problems in production.
No query hints and no plan to ever implement it. Making the planner better only takes you so far when everything depends on table statistics which can be easily skewed. pg_hint_plan or using CTEs is not extensive enough.
Partial indexes are not well supported in the query planner, thanks to no query hints I can't even force the planner to use them.
Memory usage was extremely inefficient. ARC had to be set to half of what it should've been because it varied so dramatically, so half the system memory was wasted. ZFS would occasionally exhaust system memory causing a block on allocations for 10+ minutes almost daily, no ssh or postgresql connections could be opened in the meantime. Sometimes a zfs kernel process would get stuck in a bad state and require restarting the server. Many days were wasted testing different raid schemes to work around dramatic space inefficiencies (2-8x IIRC) with the wrong combinations of using disk block sizes, zfs record sizes, postgresql block sizes, and zfs record compression. Because zfs records are atomic and larger than disk pages, writes have to be prefaced with reads for the other disk pages, adding lots of latency and random IOPS load. Bunch of other issues, I could go on.
I've since switched back to ext4 and hardware RAID. Median and average latency dropped an order of magnitude. 99th percentile latency dropped 2 orders of magnitude.
These databases are at high load. If they had low load, and I wasn't expecting to grow into high load, I'd consider ZFS since it does have a bunch of nice features.
Otherwise, it is much simpler to manage than Oracle (which really is a system turned inside out). The documentation is really good and straight to the point (Oracle can't help but turn everything into an ad - nvl uses the best null handling technology on the market and such).
I do kinda miss how easy it was to do partitioning but I’m on Redshift now so it doesn’t matter.
I've used Oracle for 20+ years, SQLServer for > 10 years, and Postgres from time to time and would say they are all good tools for a general use case.
I used to be MySQL but it felt like over time it was becoming hack on top of hack for each subsequent version while PG lacked a number of features in the early 2010's it has clearly caught up with great care to its codebase.
There are scenarios that PG does not win and should not be used, but if we're talking about the most applications that it covers well, PG is it.
For features I used on both, the average quality of the SQL Server implementation is between middling and pathetic (mostly the latter). I cannot recall a single instance where I thought "that's nice" or anything positive about how SQL Server does something. At best, it has been "this is not awful".
Things that sucked especially hard:
- Datetime API: In postgresql it is a joy to use and most features one would like to have to analyze data are directly there and work as they should. The analysis for my master's thesis was completely done in postgresql [1] (including outputting CSV files that could then be used by the LaTeX document) - without ever feeling constrained by the language or its features. Meanwhile, the way to store a Timespan from C# via EF is to convert it to a string and back or convert it to ticks and store it as long.
- The documentation: The pgsql documentation is the best of any project I have ever seen, the one for SQL Server is horrible and doesn't seem to have any redeeming qualities. - Management: SMSS is a usability nightmare and still the recommended choice for doing anything. I assume there are better ways but I haven't found them and if I have, they usually didn't work.
- The query language: In psql you can do things like
select a < b as ab, b < c as bc , count(*) from t group by 1,2; \crosstabview
To get even half of that in SQL Server one would do select case when a < b then 1 else 0 end as ab, case when b < c then 1 else 0 end as bc, count(*) as count group by case when a < b then 1 else 0 end, case when b < c then 1 else 0 end
I think crosstab queries are unsupported (there are PIVOTs but I haven't yet looked into them a lot).Maybe my use cases are a bit weird and I haven't encountered the better features of SQL Server yet. Would appreciate if someone could point out what I am doing wrong.
[1]: https://github.com/oerpli/MONitERO/blob/master/sql/queries/r...
select iif(a < b, 1, 0) as ab, iif(b < c, 1, 0) bc...
Unsure what crosstabview is as I've never used it.I hate sql server tho. Basic things like indexable arrays in postgresql make it amazing.
Crosstabview converts a table from:
|a x 0
|a y 1
|a z 2
|b x 1
|b z 5
to | x y z
|a 0 1 2
|b 1 5a) are OK with using SQL (this is not obvious)
b) do not need a distributed database
I've spent a lot of time on looking at database solutions recently, reading through Jepsen reports and thinking about software architectures. The problem with PostgreSQL is that it is essentially a single-point-of-failure solution (yes, I do know about various replication scenarios and solutions, in fact I learned much more about them than I ever wanted to know). This is perfectly fine for many applications, but not nearly enough to call it "the world's best database".
The hard truth is that postgres is more annoying to operate than a lot of the modern alternatives when you need HA.
Do you really care that much about the language? Shouldn't you care more about your data? If you are not OK with SQL there are abstractions available.
I do care about SQL being a text-based protocol with in-band commands, bringing lots of functionality that I never need (I do not use the fancy query features for exploratory analysis, I have applications with very specific data access patterns).
For my needs, I do not need a "query language" at all, just index lookups. And I would much rather not have to worry about escaping my data, because I have to squeeze everything into a simple text pipe.
Postgres is not only for Sql, as I see multiple people referencing only the SQL functionality.
For those that work with events/projections, Postgress supports js migrations on events so you can update events in you store to the latest version.
It is hard to explain, at this remove, what horrible perversions were performed in order to be able to say "yes" to such questions, or to avoid need to answer them.
One example was a router that, at opposite ends of a long-haul network, managed data flow that was utterly insensitive to the magnitudes of latency or drop rate. They sold hardly any. It turned out the algorithm could be run in user space over UDP, and that became a roaring business, for a different company, because you could deploy without getting network IT involved. Mostly IT didn't even want bribes. They just didn't want anything around that was unfamiliar.
Database products had to pretend to be an add-on to Oracle, and invisibly back up to, and restore from, an Oracle instance, because Oracle DBAs only ever wanted to back up or restore an Oracle instance. The Oracle part typically did absolutely nothing else, but Oracle collected their $500k (yes, really) regardless.
Folks in the PostgreSQL community are aware of temporal tables:
https://www.pgcon.org/2019/schedule/events/1336.en.html
https://www.2qpgconf.com/wp-content/uploads/2016/05/Chad-Sla...
For ease of use for a new comer, mysql seems to have nicer tooling and out of box use. I’ve worked with mysql on sites with millions of daily active users and it hasn’t been a problem. Snappy 10ms queries for most things. I guess one really needs to learn ANALYZE and do the necessary index tuning.
I’m just saying, use the tool you’re most comfortable with, has good ecosystem and gets the job done. For some it’s PGSQL, for some it’s MySQL, for others it could be the paid ones. MySQl8 is pretty solid nowadays.
There is no universal “best”, just as there is no “best” car. All about trade offs.
What was your problem? All you need to call is:
docker run --rm --name pg-docker -e POSTGRES_PASSWORD=docker -d -p 5432:5432 -v $HOME/docker/volumes/postgres:/var/lib/postgresql/data postgres:latest
...and you are good to go. In depth guide: https://hackernoon.com/dont-install-postgres-docker-pull-pos...
Isn't this a fairly big issue? I would think the convenience of automated scaling is a primary reason to use these other tools.
What database or database design strategies to be used for an analytics dashboard that can be queries real-time similar to Google Analytics?
The first real scaling issue I've come across (as a junior dev working on a side project) is a table with 38 million rows and rapidly growing.
Short of just adding indexes and more RAM to the problem, is there another way to design such a table to be effectively queried for Counts and Group Bys over a date range?
Iimagine things can't really be pre-comuted too easily due to the different filters?
I'm certainly not a DB expert, but this is where a similar need led me a few months ago.
My only complaints are:
1) No built-in or easy failover mechanism (and will never have one because of their estated philosophy). I'll settle for a standard one and yes I know there are different requirements and things to optimize for and there are 3rd party solutions (just not one to integrate easily).
2) Horizontal Scalability. And yes I know of some solutions and other dbs being more apt for this and asking the wrong thing.
Security, concurrency control - those are important for transactional work facing numerous users. Not for analytic processing speed.
You can get away with having a scheduled pg_dump early on, some reports on that, while you figure out an ETL/Messaging process — but picking something that handles concurrent large-scale queries will matter fast.
How do you define an "analytic" database? Time series data, or something else?
Some of those can be done with back-end tools — say, if your software also contact to your customer service, and the managers of that center monitor their activity on a solution developed in-house, that solution isn’t “analytical” but should rather be part of the main architecture.
The main distinction that I’d make is: would it be a problem for your service if that data wasn’t available for a second, a minute, an hour? Anything visible on your app or website? A second is probably stretching it. Monitoring logistic operations, say drivers at Ubers? Up to a minute is probably fine. You want to retrain a ML model because you have a new idea, but database is down for maintenance? For an hour? You can go and grab coffee, or lunch — you are fine. Serving that same model for recommendations on a e-commerce website, that’s obviously not something that can take the same delay.
Most of those are great and work: they have connectors to whatever language or tool you want to use. The most promising tool you’ll need to handle most of the transformation is either AirFlow or preferably dbt. Those are is independent from the database, so don’t worry too much about the features that vendors tout. One key thing: monitor all the queries going to that database, find the expensive ones, those with suspicious patterns, etc.
Spin-up, response time can matter, but they are rarely a problem for most “slow” analytic use cases; for instance, Google BigQuery takes 10 seconds no matter what you query and it’s fine. On the other hand, concurrency has been an issue for me more than anything: all the analysts and managers trying to update their dashboards on Monday at 10 am.
You rapidly get to a point where prices are high and negotiated, so you want to think about your likely usage in the next years before you step into that meeting. Key decision: by default, prefer the tech that is closest to the rest of your stack because ingress is the easiest factor to predict.
Looker will be mentioned: it’s on top of all that, downstream from AirFlow/dbt.
- For OLTP workload and some ad-hoc queries, you can use TiDB + TiKV. One of our adopters has a production cluster with 300+ TB data and can easily cope with the spike caused by the brought by COVID-19.
- For more complex queries, TiSpark+ TiKV might work well; for heavier queries, we added a columnar store, TiFlash, see https://pingcap.com/blog/delivering-real-time-analytics-and-...
[2] https://www.citusdata.com/ (edit: I said TimescaleDB, I was thinking of Citus)
[3] https://github.com/pipelinedb/pipelinedb
Disclosure: I work for VMware, which sponsors Greenplum development and sells commercial offerings.
AWS RDS makes it impossible to export snapshots to s3 (because the native snapshot storage is super expensive).
EC2 m5.xlarge w/ 5000 GB storage costs 700$ RDS db.m5.xlarge w/ 5000 GB costs 1000$
Why is there no SAAS that lets me BYO my own EC2 and just runs and gives me a dashboardy experience ESPECIALLY for snapshots and restores ?
They claim this is because (unlike AWS), they don't provision iops as "credits".
There is an opportunity to play in this price arbitrage space where you can take the cloud instances and manage a database on top of it.
What I would like is if I have an item ID of 1 and a reservation duration of today 10AM to 11AM and I try to add another record of item ID 1 and duration 10:39AM to 11:39AM the insert should fail.
Apparently it is straightforward in db2 but not in postgresql?
I never used them but the manual page shows an example on avoiding overlaps that looks a lot like your case:
https://www.postgresql.org/docs/12/rangetypes.html#RANGETYPE...
CREATE TABLE reservations (
item_id uuid,
duration tsrange,
EXCLUDE USING GIST (item_id WITH =, duration WITH &&)
);And while SSMS certainly has some pain points, I have yet to find a DB client tool that even comes close in terms of usability. For this reason alone I prefer MS SQL.
I've used jsonb for performing ETL in-database from REST APIs.
I know Concourse from 6.0 uses it for storing resource versions. They had an inputs selection algorithm that became stupidly faster because they can perform joins over JSON objects provided by 3rd-party extensions. Previously it was a nested loop in memory.
https://github.com/concourse/concourse/releases/tag/v6.0.0#3...
Yea, we definitely need to do better there. But it's harder than one might think initially :(. My suspicion is that we (the PG developers) will have to write our own parser generator at some point... We don't really want to go to a manually written recursive descent parser, to a large part because the parser generator ensuring that the grammar doesn't have ambiguities is very helpful.
> At the very least, if I know which position in the text is the beginning of an error, I can fix it.
For many syntax errors and the like we actually do output positions. E.g.
postgres[1429782][1]=# SELECT * FROM FROM blarg;
ERROR: 42601: syntax error at or near "FROM"
LINE 1: SELECT * FROM FROM blarg;
^
(with a mono font the ^ should line up with the second FROM)If you have a more concrete example of unhelpful errors that particularly bug you, it'd be helpful. In some cases it could be an easy change.
Edit: also, best for what? SQLite is, in a way, the perfect DB is you don't have concurrent writes, and I've worked with vector databases (think bitmap indices on steroids) that totally outclass eg. Oracle and PostgreSQL for analytics-heavy workloads
[0] https://www.postgresql.org/docs/12/logical-replication.html
https://redmondmag.com/articles/2019/07/03/microsoft-buildin...
There's BDR, but it's closed source for recent version Pg AFAICT.
Postgres has very poor security compared to MySQL, and in fact, I tell companies implementing compliance policies to shift to MySQL.
https://www.cvedetails.com/metasploit-modules/vendor-336/Pos...
The reasons are:
- Postgres' grant model is overly complex. I haven't seen anybody maintain the grants correctly in production for non-admin read-only users. By contrast, MySQL's are grants are simple to use and simple to understand.
- Postgres' COPY FROM and COPY TO have been used to compromise the database by copying ssh keys to the server, amongst other things.
- Postgres' version of upsert allowed any command to be run without checking the permissions. So the vaunted "software engineering" behind Postgres is not that solid.
- Currently Postgres is subject to around a dozen metasploit vulnerabilities that any script-kiddy can execute.
The simple fact is, if you use Postgres, you almost certainly have a security compliance problem.
I could make the same arguments about replication, or online schema changes, multi-master writes, or any enterprise database feature.
Some constructive advice to the Postgres developers is to take a week and add grant commands to limit COPY FROM and COPY TO, and look at the metasploit options and see what can be done ASAP.
I'd appreciate if you're itching to write a hasty response that you actually check your facts first.
If you're thinking, "How is it possible that everybody else is wrong about Postgres being the best?", just remember the decade of Mongo fanboism on HN. I cringed during that era, too.
Source: MySQL and Postgres DBA.
If you care this much about security, you should have taken a look at CVE reports of each db. You'll find that historically MySql has almost double the number of vulnerabilities.
That never was the case (see evidence in initial commit [1]). Are you talking about CVE-2017-15099? Obviously annoying that we had that bug, but thats very far from what you claim.
Since you write "I'd appreciate if you're itching to write a hasty response that you actually check your facts first." you actually follow up your own advice?
> - Postgres' COPY FROM and COPY TO have been used to compromise the database by copying ssh keys to the server, amongst other things.
If, and only if, the user is a superuser. It's possible to do the same in just about any other client/server rdbms.
> Some constructive advice to the Postgres developers is to take a week and add grant commands to limit COPY FROM and COPY TO
You mean, like it has been the case for ~19 years? https://www.postgresql.org/docs/7.1/sql-copy.html "COPY naming a file is only allowed to database superusers, since it allows writing on any file that the backend has privileges to write on.".
> - Currently Postgres is subject to around a dozen metasploit vulnerabilities that any script-kiddy can execute.
That does not actually seem to be the case (what a surprise). And the modules that do exist are one for a (serious!) vulnerability from 2013, and others that aren't vulnerabilities because they require superuser rights.
[1] https://github.com/postgres/postgres/commit/168d5805e4c08bed...
And I'd love to see your sources for all your "exploits".
Your opinion against mine, but in my last project I successfully did this. I didn't even have to think about it; the client asked me if I could introduce a role for pure-read-only access and it was done in a few minutes. It helped that I'd already set up all objects, roles, and grants for non-admin access.
OTOH, the privileges system in postgres has always worked when and how I've wanted it to work, unlike my experience with MySQL.
----
> Postgres' COPY FROM and COPY TO have been used to compromise the database by copying ssh keys to the server, amongst other things.
> Some constructive advice to the Postgres developers is to take a week and add grant commands to limit COPY FROM and COPY TO
From the docs:
7.1 to 9.2: "COPY naming a file is only allowed to database superusers, since it allows writing on any file that the backend has privileges to write on." (Note that there was no support for PROGRAM in these versions, which was introduced in 9.3, and thus the docs changed to ...)
9.3 to 10: "COPY naming a file or command is only allowed to database superusers, since it allows reading or writing any file that the server has privileges to access." (and after this your request for grantable control was, well, granted ...)
11, 12: "COPY naming a file or command is only allowed to database superusers or users who are granted one of the default roles pg_read_server_files, pg_write_server_files, or pg_execute_server_program, since it allows reading or writing any file or running a program that the server has privileges to access."
And, of course, there's the classic combo of functions with SECURITY DEFINER and EXECUTE grants. For which, again, the doc has always advised: "For security reasons, it is best to use a fixed command string, or at least avoid passing any user input in it."
----
> Postgres' version of upsert allowed any command to be run without checking the permissions. So the vaunted "software engineering" behind Postgres is not that solid.
I'm afraid I couldn't find any info about this thing you mention; and frankly, it's a pretty bold claim. Could you elaborate?
Again, your opinion against mine (and many others'), but the "vaunted" engineering (and _design_) behind Postgres is solid on many fronts, from our experience of running it and using it in many contexts, including security.
I can little imagine case when you have access to the system and install dumps from untrusted sources. Probably it is world of untrusted PHP scripts from russian forums with stollen software. It is the world full of whole specter of pains. But I’m not agree that it should be considered as weakness. You never should restore dumps from untrusted sources ever. Such dumps can contains stored procedures that can contain code in pl/python that can do a lot of shady things. Is it a weakness or advantage of having freedom of using of python? In the world of script kiddies it is, but it is not problem of the Postgres.
MySQL LOAD_FILE() and SELECT ... INTO OUTFILE have been used to compromise the database by copying SSH keys to the server, amongst other things.
> Currently Postgres is subject to around a dozen metasploit vulnerabilities that any script-kiddy can execute
Such as?
Why? Postgres has a "Redis cache" (in-memory query cache) built in already[1]. Your application layer doesn't have to worry about query caching at all.
1. https://www.postgresql.org/docs/current/runtime-config-resou...
On the other hand, MySQL, who's not as bright as the smarter kid, is easy to talk to and feels friendlier and is generally the more popular kid.
I do appreciate the strictness of PostgreSQL but if I see small weird stuff, I tend to pick the one that is easier to get along with (meaning, more resource found on the net.)
Also to mention that MySQL is also getting 'brighter" since version 8.
Sure, you can list the fields in the order you want in a SELECT statement, but that's tedious - it's handy to have something reasonable in the table definition.
There's a wiki page on the Postgres site:
https://wiki.postgresql.org/wiki/Alter_column_position
talking about workarounds and a plan from 2006 on how they might implement that feature.
The problem with all SQL databases is that they are too easy to query and use. You add all kinds of select queries, joins and foreign keys and when traffic hits scramble to make it scale. NoSQL is hard to design but you can atleast be sure that once traffic hits, you don't have to redesign the schema to make it scale.
Surely this depends on how you set up your SQL database to begin with? I'm not familiar with NoSQL, so can you explain why "schemas" aren't necessary and scaling happens automatically?
Oh, profound, profound!
It occurs to me the author's a n00b.
Anyway, I do MSSQL. Until recently CTEs in PG were an optimisation fence. That would have slaughtered performance for my work. Not that I'm knocking PG, 'best' depends upon the problem.
I wonder if that really disqualifies Postgres from the same task. Are MSSQL CTEs just the hammer for your proverbial nail? Can you use a different approach in Postgres to solve the problem by leveraging its strengths?
My day job is a lot of Redshift. We use CTEs and temp tables depending on what we need. It’s based on Postgres but not really comparable when talking about performance optimization.