Reputation: 1
Thank you for your assistance, we have an SQL query that ran for 5 years and it was fine. With new load coming in, the query took more than 4 hours to run and it timed out, we isolated the problem to this statement:
This SQL Statement was simplified for easy reading:
select * from table1 t1, table2 t2
where (t1.ProductCode between t2.BeginNumber and t2.EndNumber)
Example with values
select * from table1 t1, table2 t2
where ('12345' between '12345' and '12345')
ProductCode, BeginNumber, EndNumber has a BTree Index, and they are varchar.
Table1 has 50000 rows Table2 has 113000 rows
BeginNumber and EndNumber are actually the same number, there is no range in them (example BeginNumber=12345 EndNumber=12345), but for compliance sake we can't change Between Clause to Equals Clause because they may change the numbers to a range in future.
This runs in MYSQL 5.6.11, configured InnoDB Memory 4GB, Intel i7-8550, 8GB RAM It was designed to be a small non critical database, but recent changes from incoming data source has grown significantly and the jobs are hanging, and it hangs at this statement for too long and time out (4 hours).
Hardware will be upgraded with 16G RAM, SSD, other than that, how can we make the statement run faster?
Upvotes: 0
Views: 5009
Reputation: 1269923
You need to check the explain plans to see what is happening.
First, are the types exactly the same. This is very important. The collation matters if these are strings . . . your individual query suggests they are strings. Your naming suggests otherwise.
Second, for this query:
select *
from table1 t1 join
table2 t2
on t1.ProductCode between t2.BeginNumber and t2.EndNumber
The only appropriate index is on t1(productcode)
. MySQL might have trouble picking up on its usage. So it might be better to phrase the query as:
select *
from table2 t2 join
table1 t1
on t2.BeginNumber <= t1.ProductCode and
t2.EndNumber >= t1.ProductCode;
This makes it clear that table2
is going to be the "driving" table in the join. That is, MySQL will scan table2
and then look for the appropriate matching rows in t1
.
As a note: Your example with values has nothing to do with your first query. That example processes the where
clause during the compilation phase and notes that it is always true. It then proceeds to do a cross join
. It will return all possible pairs from the two tables. You probably see it as running fast because you are looking at the first row being returned rather than waiting for all possible combinations.
Upvotes: 1
Reputation: 29667
Sometimes it helps to change a BETWEEN to 2 criteria.
And while changing the query, might as well go with the times and use modern JOIN syntax.
SELECT *
FROM table1 t1
JOIN table2 t2
ON (t2.BeginNumber <= t1.ProductCode AND t2.EndNumber >= t1.ProductCode)
And it probably wouldn't hurt to do an ANALYZE TABLE on both tables.
Upvotes: 0
Reputation: 133370
You shoud check for proper index
select *
from table1 t1
INNER table2 t2 ON t1.ProductCode between t2.BeginNumber and t2.EndNumber
Be sure you have proper index
table1 column ProductCode
and table
table2 composite index on columns (BeginNumber, EndNumber)
Upvotes: 0