tags:

views:

88

answers:

2

Hi,

i have a problem with this mysql query. It take vmore as 1 day to execute ...

The query is :

INSERT INTO traduction  
(traduction.`id`,traduction.`traduction`,traduction.`language`,traduction.`type`) 
(
 SELECT cities.id,cities.name, '', 'city' FROM cities 
  WHERE cities.id NOT IN 
   (
    SELECT traduction.`id` FROM traduction WHERE traduction.type='city' GROUP BY id
   )
);

I made a explain extended on the 2 select and it says DEPENDENT SUBQUERY so the second select is played for every select on cities but I think it's useless.

There is a way in mysql or another sql server which can allow that ?

Or maybe a complet other query.

The idea is, if a city doesn't have a traduction, the city name should be writen in the traduction table. Then I just have to look in traduction table and not city table.

A: 

You are modifying traduction table, that's why the results of inner subquery cannot be reused

limpalex
there is not a way to force the cache ? Like(Select * FROM tracution) as traduction_query and then use traduction_query as a list or something like that ...Maybe I should create a function or procedure ?
charles
+2  A: 

You can try something like this

INSERT INTO traduction   
(traduction.`id`,traduction.`traduction`,traduction.`language`,traduction.`type`)  
( 
SELECT  cities.id,
        cities.name, 
        '', 
        'city' 
FROM    cities  LEFT JOIN
        (
            SELECT  traduction.`id` 
            FROM    traduction 
            WHERE   traduction.type='city' 
            GROUP BY id 
        ) s ON cities.id = s.id
WHERE   s.ID IS NULL
);

Also ensure that you have the correct indexes on your tables, for lets say traduction.type or traduction.id and cities.id

INSERT INTO traduction   
(traduction.`id`,traduction.`traduction`,traduction.`language`,traduction.`type`)  
( 
SELECT  cities.id,
        cities.name, 
        '', 
        'city' 
FROM    cities  LEFT JOIN
        (
            SELECT  DISTINCT
                    traduction.`id` 
            FROM    traduction 
            WHERE   traduction.type='city'
        ) s ON cities.id = s.id
WHERE   s.ID IS NULL
);

EDIT: NOT EXISTS

INSERT INTO traduction    
(traduction.`id`,traduction.`traduction`,traduction.`language`,traduction.`type`)   
(  
SELECT  cities.id, 
        cities.name,  
        '',  
        'city'  
FROM    cities 
WHERE   NOT EXISTS (
                        SELECT  DISTINCT 
                                traduction.`id`  
                        FROM    traduction  
                        WHERE   traduction.type='city'
                        AND     cities.id = traduction.id 
                    )
);
astander
there is no dependency more but I don't think that it's made that i want.how can be cities.id = s.id and s.ID IS NULL ?I can't join because cities.id doen't not exists in the traduction table. I want to create it with this query.
charles
This query would bring back all items from cities that does not exist in traduction. That is why I mention the **LEFT JOIN and IS NULL** check
astander
Oh ok i understand thanks. I try it
charles
i just run the 2 select and it runs like 1hour ago. Is it normal ? There is 1,200,000 rows in cities and 750,000 in traduction.
charles
No, this is not normal, do you have indexes on the tables and if so, what indexes do you have?
astander
cities.id as primarytraduction.traduction,language,type,id as index
charles
Have you tried changing the group by to a distinct, see edit answer?
astander
disctinct is a bit faster but the idea is to make the subquery just one time. The select on traduction give 313000 result, I search a way to execute it just one time.Maybe should i use function/procedure ?From which edit are u speaking ?
charles
I edited my answer. Running the query using a sub select, not in the where clause, should be a lot faster.
astander
yes i try it. but it's slow :(
charles
Also, have you tried *NOT EXISTS*, see edited answer.
astander
I think it's good now.881711 rows in set (32.31 sec)The insert should be ok too.
charles
Thank you a lot for your help, it's now really faster.881711 rows affected (4min 14.82 sec)!But "NOT EXISTS" is almost the same as "cities.id NOT IN" ? Or the problem was just the group by ?
charles
You wil notice that from the not exists section, there is a link to cities.id in the sub select. this should limit the returned rows for each pass
astander
Ok that's clever i understand now. Thanks you again. Sorry i don't know very well stackoverflow, should i do something for your reputation ?
charles
Its fine, you already did by accepting the answer, also have a look at http://stackoverflow.com/faq at the **What is reputation?**
astander