I’m having code similar to this:
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...
}
}
This times out.
Just by changing the SQL query to include the dates in clear text, the query runs fine.
string sql = "SELECT * FROM SomeTable WHERE SomeDateColumn BETWEEN '" + startDate.ToString("yyyy-MM-dd") + "' AND '" + endDate.ToString("yyyy-MM-dd") + "'";
Using the Query Connection in VS2010, both queries runs fast, but as soon as i try it out in my program, the first one fails because it times out.
Is there an explanation to this behaviour, or have I just missed something?
The reason is that the query optimizer of SQL Server is not considering the parameter values when it picks indexes.
As such, it does not know whether your
BETWEENclause would pick 1 row, 10 rows, or a bazillion rows, and thus picks a table-scan.When you embed the dates as literals inside the SQL statement, the optimizer has all the information it needs in order to pick the right indexes.
What you can do is give query hints. If you know that the typical use-case for this query would involve a few rows, like for instance a span of a week, you can embed that knowledge into the SQL:
You should also ensure that statistics has been recalculated recently on the indexes involved on that table, to help the query optimizer pick useful indexes.