Until a few (minor) versons ago, some functions built entire translation tables EACH TIME they were called on the same page load. Someone finally caught it recently and put a static in there.
The critical add_action/do_action functions had a slowdown issue up to a few versions ago if there were more than a dozen actions on a filter. It was finally optimized to be hundreds of times faster.
The first time they tried to update the cookie functions for a major release (I think it was 2.5) they misunderstood the research paper and had to change cookies again in 2.6, breaking some plugins twice in two versions.
The meta tables until very recent history were allowed to have non-unique indexes on key values. This "feature" (an alternative to serialization) was almost never used and made meta updates much more complex (and the db slower in general).
The entire tag db structure was changed in version 2.3, breaking all tag plugins, because someone thought it was theoretically better to have a "Term_taxonomy" reference - which is still unused to this date. Having it in there makes tag queries much more complex and slower. Then they took out the timestamp for when tags were added which makes it impossible to track.
The list goes on and on. Remember, a few versions ago is still 2009.
Last time I checked (2.8?) WordPress still uses SQL_CALC_FOUND_ROWS which has some nasty performance problems on many versions of mysql.
To this day, the query count for most pages on a default install with a few posts/comments without plugins is over 20. WordPress 3.1 now uses nearly 1 megabyte of php code PER INSTANCE.
Oh and last but not least, ALL plugins are loaded on EVERY page load regardless of the request/rendering requirements. Even admin-only functions. Clever plugin authors can somewhat code around this but it's still a crazy system.