Почему я получаю тайм-аут при использовании SqlCommand с параметрами даты? - PullRequest
1 голос
/ 08 декабря 2011

У меня есть код, подобный этому:

DateTime startDate = new DateTime(2010, 12, 1);
DateTime endDate = new DateTime(2011, 12, 1);
string sql = "SELECT * FROM SomeTable WHERE SomeDateColumn BETWEEN @StartDate AND @EndDate";

using (var connection = new SqlConnection(_connString))
using (var command = new SqlCommand(connection)) {
    command.Parameters.AddWithValue("@StartDate", startDate.Date);
    command.Parameters.AddWithValue("@EndDate", endDate.Date);

    using (var reader = command.ExecuteReader()) {
        // filling up some objects...
    }
}

Это время ожидания.

Просто изменив SQL-запрос, включив даты в виде открытого текста, запрос выполняется нормально.

string sql = "SELECT * FROM SomeTable WHERE SomeDateColumn BETWEEN '" + startDate.ToString("yyyy-MM-dd") + "' AND '" + endDate.ToString("yyyy-MM-dd") + "'";

При использовании Query Connection в VS2010 оба запроса выполняются быстро, но как только я опробую его в своей программе, первый из них завершится неудачно, поскольку истекло время ожидания.

Есть объяснение этому поведению, или я просто что-то пропустил?

Ответы [ 3 ]

1 голос
/ 08 декабря 2011

Причина в том, что оптимизатор запросов SQL Server не учитывает значения параметров при выборе индексов.

Таким образом, он не знает, выберет ли ваше предложение BETWEEN 1 строку, 10 строк или несколько строк, и, таким образом, выберет сканирование таблицы.

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

Что вы можете сделать, это дать подсказки к запросу . Если вы знаете, что типичный вариант использования этого запроса будет включать несколько строк, например, промежуток в неделю, вы можете встроить эти знания в SQL:

SELECT * FROM SomeTable WHERE SomeDateColumn BETWEEN @StartDate AND @EndDate
OPTION (
    OPTIMIZE FOR @StartDate = '<some date here>`,
                 @EndDate = '<some other date here>`
)

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

1 голос
/ 08 декабря 2011

Где находится параметр @enddate.Это не должно быть похоже на

DateTime startDate = new DateTime(2010, 12, 1); 
DateTime endDate = new DateTime(2011, 12, 1); 
0 голосов
/ 08 декабря 2011

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

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

...