tags:

views:

366

answers:

3

UPDATE:

Just to mention it on a more visible place. When I changed IN for =, the query execution time went from 180 down to 0.00008 seconds. Ridiculous speed difference.


This SQL query takes 180 seconds to finish! How is that possible? is there a way to optimize it to be faster?

SELECT IdLawVersionValidFrom 
FROM question_law_version 
WHERE IdQuestionLawVersion IN 
  (
  SELECT MAX(IdQuestionLawVersion) 
  FROM question_law_version 
  WHERE IdQuestionLaw IN 
    (
    SELECT MIN(IdQuestionLaw) 
    FROM question_law 
    WHERE IdQuestion=236 AND IdQuestionLaw>63
    )
  )

There are only about 5000 rows in each table so it shouldn't be so slow.

+10  A: 

Here is a good explanation why = is better than IN

Mysql has problems with inner queries - not well using indexes (if at all).

  1. Make sure you have indexes on all the fields in the join/where/order etc.
  2. get those Max and MIN values in a separate query (use stored procedure for this entire thing if you want to skip the multiple requests overhead Or just do a request with multiple queries.

Anyway:

SELECT
         IdLawVersionValidFrom 
FROM 
         question_law_version 
    JOIN 
         question_law
      ON 
         question_law_version.IdQuestionLaw = question_law.IdQuestionLaw
WHERE 
         question_law.IdQuestion=236 
     AND 
         question_law.IdQuestionLaw>63

ORDER BY 
         IdQuestionLawVersion DESC, 
         question_law.IdQuestionLaw ASC
LIMIT 1
Itay Moav
+1 I meant to mention indexes, but... somehow... didn't :)
Unreason
Actually Martin Smith's comment is the right answer.
Richard Knop
@Richard Knop - Did my query worked for you or not?
Itay Moav
I will be able to test it tomorrow. I have the application in my work computer and I am home already.
Richard Knop
+4  A: 

You can use EXPLAIN to find out how is it possible for a query to execute so slow.

MySQL does not really like nested subselects so probably what happens is that it goes and does sorts on disk to get min and max and fail to reuse results.

Rewriting as joins would probably help it.

If just looking for a quick fix try:

SET @temp1 =     
  (
  SELECT MIN(IdQuestionLaw) 
  FROM question_law 
  WHERE IdQuestion = 236 AND IdQuestionLaw > 63
  )

SET @temp2 = 
  (
  SELECT MAX(IdQuestionLawVersion) 
  FROM question_law_version 
  WHERE IdQuestionLaw = @temp1
  )

SELECT IdLawVersionValidFrom 
FROM question_law_version 
WHERE IdQuestionLawVersion = @temp2
Unreason
Actually Martin Smith's comment is the right answer.
Richard Knop
Completely agree and gave +1 to that. Do notice his use of `EXPLAIN` :)
Unreason
+13  A: 

(Posting my comment as an answer as apparently it did make a difference!)

Any difference if you change the IN to =?

If anyone wants to investigate this further I've just done a test and found it very easy to reproduce.

Create Table

CREATE TABLE `filler` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
) 

Create Procedure

CREATE PROCEDURE `prc_filler`(cnt INT)
BEGIN
        DECLARE _cnt INT;
        SET _cnt = 1;
        WHILE _cnt <= cnt DO
                INSERT
                INTO    filler
                SELECT  _cnt;
                SET _cnt = _cnt + 1;
        END WHILE;
END

Populate Table

  call prc_filler(5000)

Query 1

SELECT id 
FROM filler 
WHERE id =  (SELECT MAX(id) FROM filler  WHERE id =   
 ( SELECT MIN(id) 
    FROM filler
    WHERE id between 2000 and 3000
    )
  )

Equals Explain Output

Query 2 (same problem)

SELECT id 
FROM filler 
WHERE id in  (SELECT MAX(id) FROM filler  WHERE id in   
 ( SELECT MIN(id) 
    FROM filler
    WHERE id between 2000 and 3000
    )
  )

In Explain Output

Martin Smith
I'd be curious for some MySQL experts to comment on the difference in performance. Clearly the subqueries are going to return 1 row only so equals is the right operator, but why would using IN make such a big performance difference when it's only checking if the value is found in a 1-row resultset?
Wade Williams
@Wade - Mark's answer here has that covered I think http://stackoverflow.com/questions/3417074/why-would-an-in-condition-be-slower-than-in-sql/3417190#3417190
Martin Smith