This has been bugging me for a while. Most of the time, when it comes to storing data in structures such as hashtables, programmers, books and articles insist that indexing elements in said structures by String values is considered to be bad practice. Yet, so far, I have not found a single such source to also explain WHY it is considered to be bad practice. Does it depend on the programming language? On the underlying framework? On the implementation?

Take two simple examples, if it helps:

An SQL-like table where rows are indexed by a String primary key.

A .NET Dictionary where the keys are Strings.

  • 10
    Having string keys is not a bad idea in general. I suspect those statements were made in a context where a better key type is available. I have have .net dictionaries with string keys all the time. Can you give some examples of this claim? Commented Mar 2, 2013 at 21:49
  • 4
    You usually want primary keys that don't change over the lifetime of an object/row. So for example username as the primary key of a users table is probably not the best idea, and you'd prefer an auto-increment id. But that username is a string is only incidental, being a mutable property is the main issue Commented Mar 2, 2013 at 21:55
  • In a database, consider how would would index strings as opposed to integers.
    – user40980
    Commented Mar 2, 2013 at 21:58
  • 1
    That specific case is clearly about performance. A "symbol" in this context is still just a string, but one that has a single canonical instance. Which reduces memory use, and allows comparison by simply comparing the reference instead of the value. Commented Mar 2, 2013 at 22:03
  • 2
    Strings are fine. Just not 'magic' strings. So, when using a hash table, make sure you don not have naked strings in your code. You should avoid large text values as keys because they don't perform well, but in most real world situations a short text string is just as fast as an integer (they are not massive databases). You can also use alternate keys, for example, the primary key is a number but there's also a 'slug' or unique string that's also unique.
    – ipaul
    Commented Mar 3, 2013 at 16:38

8 Answers 8


It all has to do with the two things basically:

1) The speed of lookup (where integers for instance fare much better)

2) The size of indexes (where string indexes would explode)

Now it all depends on your needs and the size of the dataset. If a table or a collection has like 10-20 elements in it, the type of the key is irrelevant. It will be very fast even with a string key.

P.S. May not be related to your question, but Guids are considered bad for database keys too (16 byte Guid vs. 4 byte integer). On large data volumes Guids do slow down lookup.

  • Not always - incremental GUIDs are possible. Indexes will still be bigger, but the lookup penalty won't be nearly as bad.
    – Sam
    Commented Mar 2, 2013 at 23:55
  • 10
    Actually they're fine. You have to look at the relationship between the time disk IO time and comparing values in memory. Since disk access times overwhelm memory comparison, the only thing that really matters in analyzing database performance is IO. Whether the key is a GUID, string or an integer is not really critical. The index size affects how many index values fit in one page, but whether the key is a 4 byte int (which may not be large enough and can't be client generated) or a 16 byte value is not a significant concern. In some databases the rowId's can be 16 bytes in size.
    – ipaul
    Commented Mar 3, 2013 at 16:34

There is one more issue with using strings as keys, or more accurately, using string literals as keys, setting aside pure performance/efficiency reasons. Typos. If you use string literals as keys in a dictionary, you're setting yourself up for a nasty surprise when one "ReceiverId" becomes a "RecieverId". Set up constants to store the key values and reuse them whenever you access the dictionary.

Trivial and obvious, you can say, yet a stunning number of .NET code examples around the web uses string literals, propagating this dubious practice. ASP.NET with all the Sessions, ViewStates and QueryParams strewn across the codebase is particularly guilty here.

  • Not trivial IMHO. I've also seen cases where there are keys "1" and "1 " in the same table.
    – p.s.w.g
    Commented Mar 3, 2013 at 0:00
  • Get's even more amusing when you throw case sensitivity in the mix as well. Seen loads of people including myself stumble directly into that one. Commented Mar 3, 2013 at 16:04
  • Even better than using constants, in C# at least, is using Expressions instead. That way you can generate your strings from the names of methods/properties etc so your string lookups become type safe and refactor friendly. Commented May 4, 2017 at 12:10

There are many tradeoffs here. Actually I use string keys frequently, but often I include surrogate secondary keys for joins (obviously it would be the other way around if I was using MySQL). There are cases where I don't however.

First I am a fan of declaring natural keys as the primary key where the db can handle this well (PostgreSQL for example). This helps with normalization and makes for clearer database design. Surrogate keys make joining easier.

There are two reasons I usually add surrogate keys:

  1. It isn't always clear what a natural key is. Sometimes these have to be changed. Changing a natural, composite key when it is used for joins and referential integrity is complicated and error prone.

  2. Join performance on composite keys is problematic and once you go down the natural key route, you get stuck there.

In cases where a natural key is definitional, single column, and text, however, I usually join on the string key. My reason for doing so is that this often avoids joins on lookup. The most common use is providing proper db design around the use case of enum types. In most cases, these do not require the extra join for routine queries. So where this is the case, string keys as join keys makes perfect sense.

For example in LedgerSMB, we store account categorizations. These are identifed by string reference.and some other data is stored with the string reference which is used to enforce rules regarding the combinations of categorizations that can affect an account. The only time that logic is needed is when saving a set of categorizations, so we join on the string key.

As to why the default would be integer keys, I don't think it's just a question of index size. A big issue is management of keys. Since the key is arbitrary and you may be dealing with millions of records, you have to have a way of generating unique strings. There are cases where people use UUIDs for this, but there is a non-zero chance of UUID collision, and where billions of records are stored, this chance becomes high enough one might actually see while the chance of collision with incremented integer types is zero by definition.

  • It's not non-zero if you manage to make the integer type wrap around back to zero. For an unsigned 32-bit type, that is only 4G away, which is disturbingly close with “billions of records”… Commented Mar 3, 2013 at 7:46
  • If you have a db that you can tell "error rather than wrap around" it is zero. At any rate it is easier to manage the possibility of collision with incrementing integers than with pseudorandom values. Commented Mar 3, 2013 at 9:00

There are a number of potential issues with using strings as keys, especially when it comes to sql-like tables. As mentioned by @bunny, the indexes for your tables are going to be bigger, but I think more significantly, any foreign key relationships to the table will involve BOTH tables to have contain the string as opposed to a lighter-weight (integer) identifier. If you find that there are even more tables with references to the first, the string keys will be proliferated throughout your database.


It' not a bad idea in and of itself, it's usually with 20/20 hindsight a poor design compromise. The flexibility and range of string versus the additional cost and complexity.

If integer does the job range wise and the bulk of the expensive processing doesn't need to know what the integer represents, use one.


You somehow retrieved the wrong data from a Hashtable.

Did you mean "DaytimeTelephone" or "EveningTelephone"?


Did you mean 1234567 or 1234576?

Whilst numbers are arguably more efficient for the machine, whenever things go awry (and they do), it falls to the likes of you and I to make sense of what's happened and, at that point, that saving of a few bytes of storage and a few micro (nano?)-seconds of processing loses out to clarity every single time.

  • 1
    And thus you end up with a list of constants, using the name of the constant in your code to represent the magic number... Java enums to the rescue to abstract it away even further and leaving you with just the name and having the ordinal mapping invisible.
    – jwenting
    Commented May 4, 2017 at 11:19

Lots of trade offs and no one right answer. Many programmers would never consider using string keys in the database because they aren't aware of hashing and how a database works. String keys as long as they are either extremely stable, or meaningless (surrogates), are a good design choice in many circumstances.

  • 3
    This answer doesn't add anything that hasn't already been said in the other answers, which say it better. Commented Apr 19, 2014 at 15:21

string key will make sense, when it comes to lookup table with about 10-100 short string records; related data is more readable + e.g. change tracking (numeric/guid id vs. string e.g "Administrator"); btw, ASP.NET Membership database uses string keys for AspNetRoles.