Я делаю так, если нужно очень много обновлять:
* сначала создаём временную таблицу с двумя полями: Id, balance:
create table users_update_tmp(
id,
balance,
primary key (`id`)
)
, тип таблицы и тип полей такие же как в "users";
* данные сливаем в временный csv-файл;
* затем делаем "load data local infile" из csv-файла во временную таблицу;
* затем обновляем целевую таблицу: "update users inner join users_update_tmp on users.id = users_update_tmp.id set users.balance = users_update_tmp.balance";
* затем удаляем временную таблицу;
* удаляем временный файл.
Не забудьте только повесить ключь на поле id во временной таблице, чтобы джойн в команде update работал эффективно.
Несколько миллионов кортежей такая схема переваривает легко. Самое тяжелое - слить данные в csv-файл.