Множестов объектов одним запросом (insert/update)?
Цель:
Меньше обращений к БД, быстрее обрабатывается файл, меньше нагрузка на железонапротив - тебе нужно максимум передать в бд пусть сама разруливает
В постгресе есть механизм транзакции. Грубо говоря, внутри транзакции коммит проходит только после твоей четкой команды. 
Что дает: индекс не пересобирается, пока ты внутри транзакции твои данные не видны для запросов за пределами транзакции (при факапе делаешь роллбек и как ничего и не было)
Те делаешь https://docs.djangoproject.com/en/1.8/topics/db/tr...@transaction.atomic
def do_stuff():
    # This code executes inside a transaction.
и в функции делаешь get_or_create 
Делать список на 40к позиций не стоит - работай с каждой строчкой-товаром отдельно
40к селектов >>> список из 40k
Все проверки и чистку данных из цсв вынеси в отдельные функции, чтоб у тебя основная функция выглядела просто как набор вызовов
Очень-очень советую проводить добавление в модель через ModelForm с валидацией - мало ли какой цсв тебе дадут
Не используй евал и/или исполнение чего-либо из таких файлов
Чисти от js дескрипшены и тайтлы и вообще все что ты можешь в шаблоне случайно показать без фильтрации ака {{ foo|safe }}
Помести код в managed commands
используй профайлер и time ./manage.py do_stuff
Вставить много новых товаров не проблема, хоть милион.
Предварительно выбираем id уже существующих в базе товаров в set.
Затем используй bulk_create, кнечно не миллион сразу вставляй, а пачками по 1000-10000 за раз.
А вот обновить 40 тыс товаров в mysql/postgres удобных механизмов нет.
Если нам надо обновлять не всю информацию, а скажем только наличиие то можно сделать так.
Создаешь отдельную таблицу про наличие товара, туда вставляешь через bulk_create. После того как все вставил, старую таблицу грохаешь, а новую переимновываешь в старую.