i have 10 tables with same structure except table name.
i have a sp (stored procedure) defined as following:
select * from table1 where (@param1 IS
I had seen this behavior, but it wasn't related to the character set.
I had a table that held self-referencing hierarchical data (a parent with children, and some children had children of their own, etc.). Since the parent_id had to reference the primary id's (and the column specified a constraint to that effect), I couldn't set the parent id to NULL or 0 (zero) to disassociate a child from a parent, so I simply referenced it to itself.
When I went to run a stored procedure to perform the recursive query to find all children (at all levels) of a particular parent, the query took between 30 & 40 times as long to run. I found that altering the query used by the stored procedure to make sure it excluded the top-level parent record (by specifying WHERE parent_id != id) restored the performance of the query.
The stored procedure I'm using is based on the one shown in: https://stackoverflow.com/questions/27013093/recursive-query-emulation-in-mysql.
Interesting question, because I am fond of using stored procedures. Reason is maintenance and the encapsulation principle.
This is information I found: http://dev.mysql.com/doc/refman/5.1/en/query-cache-operation.html
It states that the query cache is not used for queries that 1. are a subquery that belong to an outer query, and 2. are executed within the body of a stored procedure, trigger or event.
This implies that it works as designed.
Just a guess:
When you run the query by hand, the expression WHERE ('test' IS NULL or COL1 = 'test')
can be optimized when the query is being parsed. The parser can see that the string 'test'
is not null, so it converts the test to WHERE COL1 = 'test'
. And if there's an index on COL1
this will be used.
However, when you create a stored procedure, parsing occurs when the procedure is created. At that time, it doesn't know what @param
will be, and has to implement the query as a sequential scan of the table.
Try changing your procedure to:
IF @param IS NULL
THEN BEGIN
SELECT * FROM table1
UNION ALL
SELECT * FROM table2
...
END;
ELSE BEGIN
SELECT * FROM table1 WHERE col1 = @param
UNION ALL
SELECT * FROM table2 WHERE col1 = @param
...
END;
END IF;
I don't have much experience with MySQL stored procedures, so I'm not sure that's all the right syntax.
Possible character set issue? If your table character set is different from your database character set, this may be causing a problem.
See this bug report: http://bugs.mysql.com/bug.php?id=26224
[12 Nov 2007 21:32] Mark Kubacki Still no luck with 5.1.22_rc - keys are ingored, query takes within a procedure 36 seconds and outside 0.12s.
[12 Nov 2007 22:30] Mark Kubacki After having changed charsets to UTF-8 (especially for the two used), which is used for the connection anyways, keys are taken into account within the stored procedure!
The question I cannot answer is: Why does the optimizer treat charset conversions an other way within and outside stored procedures? (Indeed, I might be wrong asking this.)