There’s two different ways of identifying a nix package: its attribute path in the package set, and the name it self-identifies as. Here’s an example where those differ, firefox-esr. Its attribute path is firefox-esr while the package name it reports is firefox.
It’s very fast to find a package by its attribute path since that’s essentially one or more map lookups. In contrary, the package name isn’t unique (for example, firefox and firefox-esr both have a package name of “firefox” because they are built from the same package file just with different sources) and also doesn’t have an index, so to find a package with a matching name you have to search through the entire package set and evaluate every package to get its name and check if it matches.
nix-env -i searches packages by their package name, which as a consequence makes it slow and also unreliable since you might not get the package you were looking for, but instead another with the same name. nix-env -iA somewhat fixes this by installing packages by their attribute path, but even if you use that you get the same issues with nix-env --upgrade since that always searches for packages to update by the installed packages’ names (it might even replace one package with a completely unrelated one which coincidentally has the same name!).
The new nix profile however stores the attribute paths a package was installed from so doesn’t have any of these problems.