Based on your answer to my comment, I think you have a much simpler solution.
Including the user id shouldn't impact performance at all, because you should have an index on your AccessKey
column which allows your database to find your user in constant time. In other words you're using a query like this:
SELECT id,email,password_hash FROM users WHERE access_key=?
And you're thinking about changing to something like this so that the primary index can be used:
SELECT id,email,password_hash FROM users WHERE id=? AND access_key=?
However, there is no difference between using the primary key or adding an index to a unique column. At risk of overkill,I did a simple example using MySQL:
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(255) NOT NULL DEFAULT '',
`api_token` char(32) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
UNIQUE `users_api_token` (`api_token`)
);
You can see that whether you query on the id or the api token, the query plans are exactly the same (the only difference is the choice of index to use):
mysql> describe select id from users where id=1;
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| 1 | SIMPLE | users | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.01 sec)
mysql> describe select id from users where api_token='asdf';
+----+-------------+--------+------------+-------+-----------------+-----------------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+-------+-----------------+-----------------+---------+-------+------+----------+-------------+
| 1 | SIMPLE | users | NULL | const | users_api_token | users_api_token | 32 | const | 1 | 100.00 | Using index |
+----+-------------+--------+------------+-------+-----------------+-----------------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.01 sec)
But there is a big difference if you were to search on the first_name column which does not have an index:
mysql> describe select id from users where first_name='asdf';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | users | NULL | ALL | NULL | NULL | NULL | NULL | 1547 | 10.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
Now it is doing a full table scan, which you certainly want to avoid. So if you don't have an index on your AccessKey
column then you need to create an index there, or you need to also pass up the user id. I'd personally just put an index on the AccessKey
column, as it will be a much simpler and smaller change that reaches the same goal (better performance).