Я использую sqlsrv (php_pdo_sqlsrv_55_ts.dll и php_sqlsrv_55_ts.dll) в PHP (5.5.12) для подключения к серверу MSSQL 2012 через VPN-туннель. Но скорость передачи для больших наборов результатов очень медленная.
Тестирование SSMS на том же ПК через тот же VPN-туннель для этого запроса:
SELECT *
FROM [Data].[dbo].[Logins]
WHERE date >= '2014-01-27 00:00:00.000' AND date < '2014-01-29 00:00:00.000'
возвращает около 100 000 строк за 4 секунды. Проверка скорости передачи данных на моем брандмауэре / VPN показывает 2500 КБ / с (в сети 100 Мбит) во время выполнения запроса.
Используя PHP:
sqlsrv_configure('ClientBufferMaxKBSize', 1024*1024);
$dbconnect = "SERVER\\HERE";
$dbconinfo = array("UID" => "user", "PWD" => "pass", "Database" => "Data")
$conn = sqlsrv_connect( $dbconnect, $dbconinfo);
$sql = "SELECT *
FROM [dbo].[Logins]
WHERE date >= '2014-01-27 00:00:00.000' AND date < '2014-01-29 00:00:00.000'
";
$options = array();
$options["Scrollable"] = SQLSRV_CURSOR_CLIENT_BUFFERED;
$options["QueryTimeout"] = 30000;
$stmt = sqlsrv_query( $conn, $sql, array(), $options);
работает 40 секунд и брандмауэр / VPN показывает менее 150 КБ / с во время выполнения запроса. Диспетчер задач показывает около 5% процессорного времени для скрипта.
Я использовал SQLSRV_CURSOR_CLIENT_BUFFERED только для тестирования, потому что он считывает результат в свой собственный буфер без какого-либо дополнительного кода PHP. Выборка каждого набора данных без буферизации происходит немного медленнее (около 45 секунд).
Я также попробовал версию PDO, которая привела к тому же самому результату.
ConnectionPooling 0 или 1 также не имеет никакого значения.
Изменение имени сервера на DNS или IP-адрес также не имело значения.
LogSubsystems -1 и LogSeverity -1 не показали никаких проблем или чего-либо полезного вообще.
Я даже использовал Wireshark для наблюдения за сетевым трафиком, но не смог найти больших различий между версиями PHP и SSMS. Но я не знаю слишком много о сетевых уровнях.
Будем весьма благодарны за любые идеи, что может быть проблемой или что я мог бы попытаться ускорить PHP / sqlsrv.
Для ускорения выборки до 3 раз, пожалуйста, используйте «MultipleActiveResultSets» => ‘0’ в параметрах подключения sqlsrv_connect.
Пример:
$db = sqlsrv_connect('127.0.0.1', array('Database'=>'dbname','UID'=> 'sa','PWD'=> 'pass',"CharacterSet" =>"UTF-8","ConnectionPooling" => "1","MultipleActiveResultSets"=>'0'
));
Как насчет замены
$options["Scrollable"] = SQLSRV_CURSOR_CLIENT_BUFFERED;
с
$options["Scrollable"] = SQLSRV_CURSOR_FORWARD;
Одним из наиболее распространенных «исправлений» медленных операций sqlsrv является изменение значения прокрутки. Я попробовал это, и это не помогло … на самом деле SQLSRV_CURSOR_CLIENT_BUFFERED вызвал ошибочное поведение.
Пример:
$stmt = sqlsrv_query( $this->connection, $sql, array(), array(
"Scrollable"=>SQLSRV_CURSOR_CLIENT_BUFFERED
));
Я полагаю, что более новые версии sqlsrv (который у меня есть 4.3.0) уже несколько оптимизируют это и подозревают, что это не требуется для последних версий.
Второе по популярности предложение — изменить параметры подключения … Я пробовал много решений … и они действительно не помогли. Опять же, я думаю, что новые драйверы sqlsrv изменили настройки по умолчанию для этого.
Пример:
sqlsrv_configure('ClientBufferMaxKBSize', 0);
$serverName = Config::get('settings.MS_DB_HOST').", 1433";
$connectionInfo = array(
"Database"=>Config::get('settings.MS_DB_NAME'),
"UID"=>Config::get('settings.MS_DB_UID'),
"PWD"=>Config::get('settings.MS_DB_PWD'),
"MultipleActiveResultSets"=>'0',
"connectionpooling"=>"0",
"TraceOn"=>"0");
$this->connection = sqlsrv_connect($serverName, $connectionInfo);
Все, что сказало … что наконец помогло мне, это понять, что sqlsrv_connect был моим преступником и невероятно медленным. Для некоторых приложений вы не заметите этого … но в моем случае я имел дело с кодом, который будет постоянно переподключаться к базе данных перед выполнением последующих операций sql. Скажем, это займет полсекунды для запуска … если у вас есть 10 различных операторов sql, каждый из которых подключается к своему собственному «sqlsrv_connect ()» … это (для меня) может занять 5 секунд. Решение состояло в том, чтобы повторно использовать объект подключения из первого экземпляра. Как только я это сделал, улучшения производительности были впечатляющими.
Надеемся, что в будущем библиотека sqlsrv запрограммирует что-то вроде постоянных соединений PHP / MySQL, и в этом нет необходимости.