In addition to the nice answers here, here is some perspective when thinking about how to build a database.
First, robust hash tables are typically done using a bucketing system, such as in Quadratic Probing which is used to implement JavaScript "objects" (i.e. hash tables), for example. You can see a bucketed hash table implementation in JavaScript here.
You'll notice in this implementation, that there is a lot more processing that goes on than meets the eye with O(1)
notation. First, you run it through the hashing function, which iterates the length of the input string, and has 5+ computational steps each iteration. Note though, these are fast computational steps because they are all done in registers and not in RAM. Next, you use that hash value to fetch a bucket. I'm not sure how many buckets there are, or how long a bucket is, but the bucket is an array or linked list. So then you iterate through the bucket items, and compare every item with the input key you are fetching the value for. This is again a string comparison. So in all likelihood I would estimate that there are at least 100 computational steps for even a simple string to fetch it from a hash table. All of these string comparisons add up.
In addition, the buckets might be half empty, which takes up a lot of useless space. Finally, when the hash table reaches a certain size in occupancy, it has to then double in size! It has to re-process and recompute everything. This can cause a noticeable glitch in a UI application.
B+trees, on the other hand, are a more compact data structure. You are still doing string comparison, but you are only jumping MAX I would say 20 links in the tree (in terms of depth), then scanning the children in the last tree node to find the exact match.
In this sense, I think in reality that B+trees or B-trees will perform on par with hash tables, especially naive implementations. Both systems can be optimized and fine-tuned, and I still think they will be close to equal. Only testing will tell. But trees come with the advantage of being more compact memory-wise. So after thinking about this for long periods of time and weighing every aspect of the equation, I am going to choose B+trees as the ideal solution to finding items by key quickly.