It depends on the implementation.
For example, a C compiler might maintain a symbol table during compilation. This is a rich data structure that allows pushing and popping of scopes, since each compound-statement opening brace {
potentially introduces a new scope for new local variables. In addition to handling scopes coming and going, it records the variables declared, and for each includes the names and their types.
This symbol table data structure also supports looking up a variable's information by name, e.g. by its identifier, and the compiler does this when it binds the declared variable information to raw identifiers it sees in the parse, so this is pretty early on during compilation.
At some point, the compiler assigns locations to the variables. Perhaps location assignments are recorded in the same symbol table data structure. The compiler could do location assignment directly during parsing, but it is likely to be able to do a better job if it waits not just until after parsing, but after general optimization.
At some point, for local variables, the compiler assigns either a stack location or a CPU register (it can be more complex in that the variable can actually have multiple locations, such as a stack location for some parts of the generated code and a CPU register for other sections).
Finally, the compiler generates actual code: machine instructions that references variables' values directly by their CPU registers or assigned stack location, as needed to execute the code being compiled. Each line of source code compiles to its own series of machine code instructions, so the generated instructions encode not only the operations (add, subtract) but also the locations of the variables being referenced.
The final object code that comes out of the compiler no longer has variable names and types; there are only locations, stack locations or CPU registers. Further there is no table of locations, but rather these locations are used by each machine instruction knowing the location where the value of the variable is stored. No looking up of identifiers in the runtime code, each bit of generated code simply knows the operation to perform and the location(s) to use.
When debugging is enabled during compilation, the compiler will output a form of the symbol table so that, for example, debuggers will know the names of the variables at the various stack locations.
Some other languages have the need to lookup identifiers dynamically at runtime, so may also provide some form of symbol table in support of such needs.
Interpreters have a wide range of options. They might maintain a symbol table-like data structure for use during execution (in addition to use during parsing), though instead of assigning/tracking a stack location, simply store the value for the variable, associated with the variable's entry in the symbol table data structure.
A symbol table is perhaps stored in the heap rather than on the stack (though using the stack for scopes and variables is certainly possible, and further it may mimic a stack in the heap to get the cache friendly advantage of packing the variable's values near each other), so an interpreter is probably using heap memory for storing the variable's values whereas a compiler uses stack locations. Generally speaking, the interpreter also does not have the freedom to use CPU registers as storage for variable's values since the CPU registers are otherwise busy running the lines of code of the interpreter itself...