Я разрабатываю приложение PHP, которое обрабатывает адреса IP. Я работаю с mysql таблицами, содержащими до 4 миллиардов строк.
У меня есть сценарий, который в настоящее время должен выбирать 65 536 адресов от этой таблицы, и mysql <-> php интерфейс не удается дать ответ через PHP или даже через phpMyAdmin, когда я пытаюсь извлечь эти 65K строки. Если используется в командной строке, mysql даст 65K строки без проблемы приблизительно через 0,2 секунды.
Таблица, содержащая IP-адреса, имеет 3 индекса (1 уникальное, 2 основных), которые, как предполагается, помогают ей пойти быстрее, но я просто не могу закончить наличие mysql, отдают ассоциативный массив к PHP для продолжения моей обработки данных.
Сервер является выделенной недавней машиной Xeon приблизительно с 32 ГБ памяти (я не знаю точные спецификации).
Какие-либо подсказки о том, что могло продолжаться здесь?
Заранее спасибо.
mysqli
и PDO
по умолчанию работают в буферном режиме . Это означает, что на ваши запросы фактически действует лимит памяти PHP-процесса.
С http://php.net/manual/en/mysqlinfo.concepts.buffering.php:
.[В буферизованном режиме] результаты запросов немедленно передаются с сервера MySQL на PHP. и затем хранятся в памяти PHP-процесса. Это позволяет дополнительные операции, такие как подсчет количества строк и перемещение (ищет) текущий указатель на результат. Это также позволяет выдать дальнейший запросы по одному и тому же соединению при работе с результирующим набором. Обратной стороной буферизованного режима является то, что большие наборы результатов могут потребовать достаточно много памяти.
Вы должны либо увеличить лимит памяти PHP-процессов в вашем php.ini
, увеличив значение параметра memory_limit
, либо сказать запросам использовать unbuffered mode:
Unbuffered MySQL-запросы исполняют запрос и затем возвращают ресурс пока данные еще ждут на сервере MySQL. Это использует меньше памяти на стороне PHP, но может увеличить нагрузку на server.
Mysqli пример:
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
$uresult = $mysqli->query("SELECT Name FROM City", MYSQLI_USE_RESULT);
PDO пример:
$pdo = new PDO("mysql:host=localhost;dbname=world", 'my_user', 'my_pass');
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);