2017-09-01 3 views

Répondre

1

Une requête comme

select * from table where id in (select id from othertable) 

sera essentiellement interprété comme

select * from table where exists 
    (select id from othertable where table.id = othertable.id) 

C'est ce que vous attendez pour cette requête. Vous vous attendez en particulier à la requête IN pour utiliser l'index sur othertable.id. Dans le manual, il est décrit comme

Quelques optimisations MySQL lui-même sont par exemple: [...]

  • MySQL récrit EN, TOUT, TOUT, et quelques sous-requêtes pour tenter de tirer profit de la possibilité que les colonnes select-list de la sous-requête soient indexées.

Ce sont, non pas par pure coïncidence, exactement les quatre opérateurs mentionnés dans le message d'erreur si vous ajoutez un limit:

select * from table where id in 
    (select id from othertable order by id limit 10) 

erreur 1235 (42000): Cette version de MySQL ne supporte pas encore 'LIMIT & IN/ALL/ANY/QUEL sous-requête'.

Réécriture cette requête de manière similaire est pas directement plus possible, car il est quelque chose de différent que

select * from table where exists 
    (select id from othertable where table.id = othertable.id 
    order by id limit 10) 

Pour exécuter le IN avec une limite, MySQL pourrait récupérer les 10 premières lignes de othertable, stocker ce resultset comme sous-table dérivée et vérifiez si l'id est là. Et vous pouvez bien sûr faire exactement cela:

select * from table where id in 
    (select id from 
     (select id from othertable order by id limit 10) subtable) 

Cette volonté, par analogie avec le premier exemple, être interprété comme

select * from table where exists 
    (select * from 
     (select id from othertable order by id limit 10) subtable 
    where table.id = subtable.id) 

Il est donc un mélange de la façon dont les travaux d'optimisation (il réécrira la requête), comment fonctionne limit (il arrête l'exécution après trouver lignes, ne pas les ignorer), ce qui est attendu (l'utilisation d'index) et finalement si les développeurs ont décidé d'autoriser une syntaxe spécifique ou non.

Vous pourriez argumenter que MySQL pourrait toujours se replier pour exécuter la requête en tant que table dérivée s'il rencontre IN avec une sous-requête limit - mais vous pourriez aussi en utilisant explicitement une sous-table dérivée. Vous pourriez également soutenir que vous pouvez penser à des façons de mettre en œuvre ou de mettre en œuvre cela différemment - et vous avez raison, il y en a. C'est pourquoi il y a un "encore" dans le message d'erreur. Alors n'hésitez pas à les mettre en œuvre ou au moins les décrire par exemple. dans une demande de fonctionnalité aussi complètement que possible et en considération de la façon dont toutes les autres parties de MySQL fonctionnent. Mais assurez-vous qu'ils sont en fait plus rapides que l'utilisation d'une sous-table.