I think there is some confusion about how compilers deal with variables. From the point of view of the high level of human life, it is natural to think about defining and destroying a variable in order to have some kind of “value” associated with it.
However, this is not necessary for the optimization compiler. The variables that you create in a high-level language are more like temporary “pens” in memory. The compiler looks at these variables, and then translates it into an intermediate representation (something closer to the machine) and calculates where to store everything, mainly for the purpose of allocating registers (the most direct form of memory for CPU use). Then it converts IR to machine code, where the idea of a “variable” does not even exist, only a place to store data (registers, cache, drum, disk).
This process involves reusing the same registers for several variables, provided that they do not interfere with each other (provided that they are not needed at the same time: do not "live" at the same time).
In other words, with code like:
local a = <some expression>
The resulting assembly might look something like this:
load gp_register, <result from expression>
... or it may already have the result of some expression in the register, and the variable ends completely disappearing (just using the same register for this).
... which means there is no "cost" to the existence of the variable. It simply translates directly to the register, which is always available. There is no “cost" to "create a registry" because registers always exist.
When you start creating variables in a wider (less local) area, contrary to what you think, you can actually slow down the code. When you do this superficially, you struggle with the distribution of the compiler register and make it difficult for the compiler to figure out which registers to allocate for what. In this case, the compiler can spill more variables onto the stack, which is less efficient and actually has a cost. A smart compiler may still produce equally efficient code, but you could do something slower. Help with the compiler here often means more local variables used in small areas where you have a better chance for efficiency.
In assembly code, reusing the same registers whenever possible is effective to avoid stack leaks. In high-level languages with variables, this is similar to the opposite. Reducing the volume of variables helps the compiler figure out which registers it can reuse, because using a more local area for variables helps tell the compiler which variables do not live at the same time.
Now there are exceptions when you start to include user-defined constructor and destructor logic in languages such as C ++, where reusing an object can prevent over construction and destruction of an object that can be reused. But this does not apply in a language such as Lua, where all the variables are basically plain old data (or it processes data collected through garbage or user data).
The only time you can see the improvement using less local variables is that it somehow reduces the garbage collector. But this will not happen if you just reinstall the same variable. To do this, you will have to reuse entire tables or user data (without re-binding). In other words, reusing the same table fields without re-creating a whole new one can help in some cases, but reusing the variable used to refer to the table is unlikely to help and may actually interfere.