I'm building a complex query to show some statistics results in a web view. The view can have several different filters depending on the user's choice. Also, there is the possibility to use wildcards.
I'm building this query programatically in c# using SqlParameters. So the query looks like this:
sc.CommandText = "SELECT * FROM table
WHERE field1 = @filter1
AND field2 LIKE @filter2"; //...and more parameters
sc.SqlParameters.Add(
new SqlParameter("@filter1", SqlDbType.Int, 32) { Value = 1});
sc.SqlParameters.Add(
new SqlParameter("@filter2", SqlDbType.VarChar, 446) { Value = "whatever%"});
This is a very simplified version, but the query itself is not the point. Just keep in mind that it can have different optional parameters (which I think it is a pretty common situation).
When I ran this query in Sql Manager I realized that there is a huge slow down when using parameters.So, the following two queries, that should be the same, they use a different execution plan that makes the parameterized one run a lot slower:
DECLARE @filter1 INT
DECLARE @filter2 VARCHAR 446
SET @filter1 = 1
SET @filter2 = "whatever%"
SELECT * FROM table WHERE field1 = @filter1 AND field2 LIKE @filter2
The fast version:
SELECT * FROM table WHERE field1 = 1 AND field2 LIKE 'whatever%'
Here is another example of someone with the same issue:
Why does a parameterized query produces vastly slower query plan vs non-parameterized query
Seems that there is something called parameter sniffing, that might make a parameterized query run slower, but it does not apply in my case because this is not a stored procedure.
One of the solutions proposed is to use OPTION(RECOMPILE) or OPTION(OPTIMIZE FOR). I can't do that because I have about 10 optional parameters, that may be in the filter or not, and this option is not working when using a LIKE
.
So, I feel I'm in a dead end and I'm thinking on get rid of the parameters and build dynamic literal queries on the code. But then Sql Injection comes in the game.
So, do you have any other suggestions on how to solve this issue? Or do you know a safe way to escape the parameters?
EDIT: Here you can see the execution plans for a query with one parameter using LIKE
:
EDIT: A more simplified representative query execution plan: