Ошибка запроса при выполнении большего периода времени (mssql server 2005 только под php)

#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, потому что мне удалось заблокировать его один раз с помощью этого запроса — просто невозможно было подключиться до перезапуска.