#php #sql-server #apache
#php #sql-сервер #apache
Вопрос:
У меня странная проблема.
Я выполняю запрос:
SELECT IMIE, NAZWISKO, PESEL2, ADD_DATE, CONVERT(varchar, ADD_DATE, 121) AS XDATA, ID_ZLECENIA_XXX, * FROM XXX_KONWERSJE_HISTORIA AS EKH1
INNER JOIN XXX_DANE_PACJENTA EDP1 ON EKH1.ID_ZLECENIA_XXX=EDP1.ORDER_ID_XXX
WHERE EKH1.ID_KONWERSJE = (
SELECT MIN(ID_KONWERSJE)
FROM XXX_KONWERSJE_HISTORIA AS EKH2
WHERE EKH1.ID_ZLECENIA_XXX = EKH2.ID_ZLECENIA_XXX
)
AND EDP1.RECNO = (
SELECT MAX(RECNO)
FROM XXX_DANE_PACJENTA EDP2
WHERE EDP2.ORDER_ID_XXX = EDP1.ORDER_ID_XXX
)
AND EKH1.ID_ZLECENIA_XXX LIKE '0000393%'
AND ADD_DATE>'20140419' AND ADD_DATE<='20140621 23:59:59.999'
ORDER BY EKH1.ID_KONWERSJE, EKH1.ID_ZLECENIA_XXX DESC
И запрос работает нормально, если я использую ограничение по дате около 2 месяцев (63 дня — это дает мне 1015 результатов). Если я расширяю ограничение по дате, запрос просто завершается неудачей (ошибка запроса blabla).
Это происходит под Windows 64 бит php (apache, Xamp).
Когда я запускаю этот запрос непосредственно из MS SQL SERVER Management Studio, все работает нормально, независимо от того, какой срок я выбираю.
Что происходит? Существует ли какое-либо ограничение в apache / php? (Нет такой информации, как «превышение времени запроса», только «ошибка запроса»)
Комментарии:
1. добавьте set_time_limit(0); в начале вашей страницы php, на которой выполняется запрос
2. Это не помогло. Я уже использую ini_set(‘max_execution_time’, 36000); но нет ничего о превышении времени, только «ошибка запроса»
3. вы пробовали mssql_get_last_message()
4. Ошибка blabla в запросе blabla в большинстве случаев важна.
5. @Bogdan Sahlea — вот экран плана strimatex.nazwa.pl/maxium/execute_plan.jpg а вот и xml-файл strimatex.nazwa.pl/maxium/execute_plan.sqlplan
Ответ №1:
И запрос работает нормально, если я использую ограничение по дате около 2 месяцев (63 дня — это дает мне 1015 результатов). Если я расширяю ограничение по дате, запрос просто завершается неудачей (ошибка запроса blabla). … Что происходит? Существует ли какое-либо ограничение в apache / php? (Нет такой информации, как «превышение времени запроса», только «ошибка запроса»)
Это может произойти из-за того, что избирательность ADD_DATE>'20140419' AND ADD_DATE<='20140621 23:59:59.999'
средняя / низкая (слишком много строк, удовлетворяющих этому предикату), и SQL Server должен сканировать (да, сканировать) XXX_KONWERSJE_HISTORIA
много раз, чтобы проверить следующий предикат:
WHERE EKH1.ID_KONWERSJE = (
SELECT ...
FROM XXX_KONWERSJE_HISTORIA AS EKH2
WHERE EKH1.ID_ZLECENIA_XXX = EKH2.ID_ZLECENIA_XXX
)
Сколько раз нужно сканировать XXX_KONWERSJE_HISTORIA
таблицу SQL Server, чтобы проверить этот предикат? Вы можете посмотреть свойства Table Scan [XXX_KONWERSJE_HISTORIA]
оператора доступа к данным: 3917 раз
Что вы можете сделать для начала? Вы должны создать отсутствующий индекс (см. Это Предупреждение с зеленым цветом над планом выполнения):
USE [OptimedMain]
GO
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[ERLAB_KONWERSJE_HISTORIA] ([ID_ZLECENIA_ERLAB])
INCLUDE ([ID_KONWERSJE])
GO
Когда я запускаю этот запрос непосредственно из MS SQL SERVER Management Studio
, все работает нормально, независимо от того, какой срок я выбираю.
Для SQL Server Management Studio по умолчанию установлено значение тайм-аута выполнения 0 (тайм-аут выполнения отсутствует).
Примечание: если этот индекс решит проблему, вам следует попробовать (1) создать индекс ADD_DATE
со всеми требуемыми CREATE INDEX ... INCLUDE(...)
столбцами () и (2) создать уникальные кластеризованные индексы для этих таблиц.
Комментарии:
1. Это действительно надежный ответ. Спасибо. Я проверю это и создам надлежащие индексы. Есть также план Б — я создал новую таблицу в базе данных, где я буду хранить некоторые новые данные, поэтому этот сложный запрос не понадобится.
Ответ №2:
Попробуйте установить эти конфигурации php в вашем php-скрипте через ini_set
ini_set('memory_limit', '512M');
ini_set('mssql.timeout', 60 * 20);
Не уверен, что это вам поможет.
Комментарии:
1. Установка mssql.timeout изменяет предел выполнения для любой заданной команды SQL, инициированной через PHP (я думаю, что по умолчанию 30 секунд). При запуске в SMSS нет ограничений для команды sql. При запуске в размещенной среде вызывающий абонент может не иметь возможности фактически изменить этот параметр из-за административного ограничения.
2. по умолчанию через php — 60 секунд. Да, вы правы.
3. ini_set(‘memory_limit’, ‘512M’); — это хорошая идея. Я попробовал один раз, и скрипт работал, и работал, и работал… пока я не получил информацию (из браузера) об ограничении соединения (сервер не отвечает слишком долго). Я постараюсь выполнить больше тестов с меньшим лимитом памяти.
4. Дополнительное тестирование: в целом увеличение лимита памяти возвращает «сервер не отвечает слишком долго». Может быть, это моя ошибка apache? Или, может быть, проблема с сервером mssql, потому что мне удалось заблокировать его один раз с помощью этого запроса — просто невозможно было подключиться до перезапуска.