2015-02-10 3 views
2

У меня есть запрос Oracle bind, который очень медленный (около 2 минут), когда он выполняется в моей программе на C#, но очень быстро работает в SQL Developer. Она имеет два параметра, которые поражают индекс таблицы:Oracle Bind Query очень медленный

select t.Field1, t.Field2 
from theTable t 
where t.key1=:key1 
    and t.key2=:key2 

Кроме того, если удалить переменные связывания и создания динамических SQL, он работает так же, как это делает в SQL Developer.

Любое предложение?

BTW, я использую ODP.

+1

Интересно, связано ли это с различными настройками оптимизатора (например, first_rows vs all_rows) в C# vs sql-разработчике. Более подробную информацию см. В [этой статье Тома Ките] (http://www.oracle.com/technetwork/issue-archive/2008/08-may/o38asktom-085659.html). Возможно, вы можете проверить v $ sql и v $ sql_shared_cursor, чтобы узнать, есть ли у вас несколько строк для одного и того же оператора sql, и если да, то в этом проблема? – Boneist

ответ

1

Являются ли параметры привязаны к правильному типу данных в C#? Являются ли столбцы key1 и key2 номерами, но параметры :key1 и :key2 являются строками? Если это так, запрос может возвращать правильные результаты, но потребует неявного преобразования. Это неявное преобразование похоже на использование функции to_char(key1), которая предотвращает использование индекса.

+0

Поля key1 и key2 обозначают соответственно CHAR (8) и CHAR (2). Параметрами являются также CHAR (8) и CHAR (2). – wcm

1

Просьба также проверить, каково количество строк, возвращаемых запросом. Если число больше, возможно, C# извлекает все строки, а другой - только первый карман. Извлечение всех строк может потребовать в этом случае гораздо больше чтения дисков, что происходит медленнее. Чтобы проверить это, попробуйте выполнить в SQL Developer:

SELECT COUNT(*) FROM (
    select t.Field1, t.Field2 
     from theTable t 
    where t.key1=:key1 
     and t.key2=:key2 
) 

В приведенном выше запросе должно быть указано максимальное количество блоков базы данных.

Приятным инструментом в таких случаях является утилита tkprof, которая показывает план выполнения SQL, который может быть другим в случаях выше (однако это не должно быть).

Возможно также, что вы случайно подключились к различным базам данных. В таких случаях приятно сравнивать результаты запросов.

Поскольку вы поднимаете «Bind is slow», я предполагаю, что вы проверили SQL без привязок, и это было быстро. В 99% с помощью binds улучшается. Проверьте, будет ли запрос с константами работать быстро. Если да, то проблема может быть неявным преобразованием столбца key1 или key2 (например, t.key1 - это число и: key1 - строка).

+0

Количество записей невелико. Между 10 и 100. – wcm

1

Если вы заменяете переменные связывания статическими varibles в sql-разработчике, то вы на самом деле не используете тот же тест. Убедитесь, что вы используете переменные привязки, и если это так же медленно, вы просто получаете бит из плотного кэшированного плана выполнения. Обновление статистики в этой таблице должно решить проблему.

Однако, если вы действительно используете переменные связывания в sql-разработчиках, продолжайте читать. Версия TLDR заключается в том, что параметры, которыми управляет ODP.net, иногда вызывают несколько более пессимистический подход. Начните с обновления статистики, но пусть ваш dba захватит план выполнения в обоих сценариях и сравните его с подтверждением.

Я перепроведении мой ответ здесь: https://stackoverflow.com/a/14712992/852208 я считал слабеющей ваши, как дубликат, но ваше название немного более кратким, так как он идентифицирует запрос мчит быстро в SQL Developer. Я буду приветствовать советы по обращению по-другому.

Добавление следующего в вашу конфигурацию отправит odp.Чистая трассировку информация в лог-файл:

Это, вероятно, только будет полезно, если вы можете найти большой разрыв во времени. Скорее всего, строки на самом деле идут, но медленнее.

Попробуйте добавить строку "enlist = false" в строку соединения. Я не считаю это решением, поскольку он эффективно отключает распределенные транзакции, но он должен помочь вам изолировать проблему. Вы можете получить немного больше информации от оракул forumns поста:

С точки зрения ODP, все мы действительно можем указать на то, что поведение происходит, когда OCI_ATR_EXTERNAL_NAME и OCI_ATR_INTERNAL_NAME устанавливаются на основной связи OCI (что происходит, когда включена поддержка поддержки tx ).

Я бы предположил, что вы не видите, что план выполнения фактически отличается (что означает фактическое поражение производительности на сервере) между вызовом odp.net и вызовом разработчика sql. Попросите dba отслеживать соединение и получать планы выполнения как с вызова odp.net, так и с вызова прямо из SQL Developer (или с параметром enlist = false).

Если вы подтвердите различные планы выполнения или хотите сделать упреждающий снимок в темноте, обновите статистику по связанным таблицам. В моем случае это исправило проблему, указав, что генерация плана выполнения на самом деле не соответствует различным правилам для разных типов подключений, но анализ затрат просто более пессимистичен, когда может быть задействована распределенная транзакция. Запросы подсказки для принудительного исполнения плана также являются опцией, но только в качестве последнего средства.

И, наконец, это может быть проблема с сетью. Если ваша установка odp.net использует новый дом оракула (чего я ожидал бы, если бы вы не выполнили какую-либо настройку после установки), tnsnames.ora может отличаться. Имена хостов в tnsnams могут быть неполными, что создает дополнительные задержки при разрешении сервера. Я бы только ожидал, что первая попытка (а не последующие попытки) будет медленной в этом случае, поэтому я не думаю, что это проблема, но я подумал, что это нужно упомянуть.

+0

Я копирую sql из приложения и сохраняя переменные связывания в такте. – wcm

Смежные вопросы