If you need to use the whole combination of key1 to keyn to get value, you can flip the dict like I suggested below for O(nk*nv) (number of keys * number of values) or use the tuple method above.
Assuming you need to build the tuple on insertion and again when you need to get a value, both will be O(nk) where nk is the number of keys.
The nested dict version might be more space efficient if you're nested fairly deeply (there are lots of values that share a partial ordered list of keys), and getting a value will still be O(nk), but probably slower than the tuple version.
However, insertion will be slower, though I can't quantify it's speed. You will have to construct at least one layer of dict for each insertion, and test for the existence of
dicts at the previous levels.
There are many recipes for recursive defaultdicts that would simplify insertion from a coding perspective, but it wouldn't actually speed things up.
The tuple method is both simpler and faster for insertion, but may take more memory depending on your nesting.
Original answer from before I knew the requirements
Why not
{'key1' : 'value', 'key2' : 'value', .... 'keyn' : 'value' }
It's just storing a reference to value at each location, not value itself, so the memory usage would be less than the nested dict version, and not much larger than the tuple version, unless you have an extremely large number of values.
For time complexity of Python standard type operations, see the Python wiki.
Basically, insertion or getting one item on average is O(1).
Getting all the keys for a value would on average be O(n):
[key for key in mydict if mydict[key] == value]
However, if adding keys, or searching for all keys, is the usual operation, your dict is flipped. You want:
{'value': [key1, key2, ... keyn]}
This way you can add keys with just mydict[value].append(newkey) and get all the keys with just mydict[value] and both will be on average O(1).