Множествоенное обновление и выгрузка

Темы, не касающиеся фреймворка, но относящиеся к программированию в целом.
Ответить
Аватара пользователя
Cacatuidae
Сообщения: 65
Зарегистрирован: 2017.01.08, 17:39

Множествоенное обновление и выгрузка

Сообщение Cacatuidae »

Народ, поделитесь успешными реализациями такой вещи как:
Выгрузка данных из базы по множественным условиям (не знаю как правильно назвать).
Наприер, нужно выгрузить из базы 500.000 книг. У нас есть только ID (AI или MongoDB\BSON\ObjectID) этих книг.
Я думал 1 вариант, это разбиение 500.000 на итерации выгрузки по 1000, и писать стандартный .. in ($ids). Но все равно очень много запросов будет..
Кто как делает? :? Куда копать?)
Аватара пользователя
Cacatuidae
Сообщения: 65
Зарегистрирован: 2017.01.08, 17:39

Re: Множествоенное обновление и выгрузка

Сообщение Cacatuidae »

Аналогично и потребуется еще обновлять. Мол выгрузить, и обновить потом.
Обновляться будет у всех одно и тоже поле с оним и тем же значением.
Выгрузили 500.000 книг, изменили поле и нужно обновить их же. :shock:
Аватара пользователя
Cacatuidae
Сообщения: 65
Зарегистрирован: 2017.01.08, 17:39

Re: Множествоенное обновление и выгрузка

Сообщение Cacatuidae »

Мини иследование по селекту по первому вопросу.
$ids = Массив 50,000 ID
Если делать напрямую

Код: Выделить всё

...
$query->where(['id' => $ids]);
...
Такие результаты:
Память: 27,64 МБ
MAX память: 818,794 МБ
17 секунд
Если делать через временную таблицу в такой последовательности:
1. Создать таблицу

Код: Выделить всё

CREATE TEMPORARY TABLE IF NOT EXISTS `{$tableName}` (id int(11) NOT NULL, INDEX (id))
2. Заполнить ее массив $ids

Код: Выделить всё

$db->createCommand()->batchInsert($table, ['id'], $ids)->execute();
3. Добавить в основную выборку

Код: Выделить всё

...
$query->where(['id' => $db->createCommand("select `id` from `{$table}`")->queryColumn()]);
...
То получаю такие результаты:
Память: 28,401 МБ
MAX память: 71,836 МБ
16 секунд
По времени получается почти одинаково, но вот в потребление памяти второй вариант выгоднее первого
Иследование продолжается 8-)

Update1:
Вся непосредственная выборка упирается в процессор. А именно в одно ядро в случае с INNODB.
Никакие nnodb_thread_concurrency не помогут, т.к. если я правильно понял, то innoDB на 1 запрос использует 1 ядро процессора
anton_z
Сообщения: 483
Зарегистрирован: 2017.01.15, 15:01

Re: Множествоенное обновление и выгрузка

Сообщение anton_z »

Используйте курсоры для выгрузки. Прочитали одну строку - звписали в файл или сделали update и т.д. Расход памяти будет минимальным. Запрос будет один. Если используете PDO и MySQL, в PDO нужно задать специальную опцию: http://php.net/manual/ru/mysqlinfo.conc ... fering.php

Если про yii, то делаете по ссылке выше. Однако там не сказано, что построчное получение результата надо сначала как правило включить в драйвере. Более того, он должен это поддерживать. Если просто сделать как в примере в книге, все равно PDO сначала загрузит все в память.
Ответить