Вы знаете, что фильтрацию геолокации разумнее выполнять до, чем после, потому что вы знаете что-то о своих данных и своем запросе, чего нет в MySQL.
В частности, MySQL предполагает, что ему нужно просмотреть 502897*1
строк в первом запросе, и 52785*13=686205
строк для второго запроса, и решает использовать первый. Есть и другие факторы, которые влияют на решение о том, какой план выполнения использовать, но он дает вам приблизительное представление о том, как MySQL считает ваши данные. Это далеко от реальности (188 строк), и не удивительно, что принятие решения на основе таких неправильных предположений привело к плохой стратегии.
На самом деле, даже я знаю, что только потому, что вы сказали мне, и теперь можете предположить, основываясь на именах столбцов, что gauche
всегда меньше, чем droite
, поэтому ваше условие для g
, вероятно, описывает очень узкое окно. Но MySQL этого не знает, поскольку вы не сказали об этом MySQL, поэтому он не может принять это во внимание. И, конечно же, он не способен принимать решения на основании значения имен столбцов.
Поскольку у вас есть индекс на gauge
, для высокого значения (например, g.gauge >= your_max_value_in_that_column
) MySQL должен действительно быть в состоянии обнаружить, что имеется только несколько строк, и должен использовать лучший план выполнения. В противном случае MySQL в основном не имеет понятия. Попробуйте изменить размер окна в очень широком диапазоне (например, g.gauche >= 100000 AND g.droite <= 200000
); MySQL не покажет существенно другое число в rows
, если вы не приблизитесь к пределам своих столбцов (и не будете иметь индекс для них). Для некоторых диапазонов первый запрос на самом деле должен быть быстрее, поскольку он приближается к распределению данных, которое предполагает MySQL.
Так как вы можете рассказать MySQL о вашем распределении данных?
Возможно, можно закодировать вашу информацию как пространственные данные (точка) и указатель на них. Затем вы можете искать точки, которые лежат в двухмерном прямоугольнике, и MySQL теперь может понять, что это на самом деле очень маленький прямоугольник, содержащий ограниченное количество данных. Не обязательно, чтобы ваши данные были фактически геометрическими данными, просто вы можете кодировать их в двух измерениях.
Предполагая, что мои предположения верны, вы также можете использовать (g.gauche = 151579 or g.gauche = 151580)
, и MySQL также должен понимать, что это только ограниченный объем данных.
И вы, конечно, можете просто принудительно индексировать (или использовать FROM geolocalisation g STRAIGHT_JOIN annonce a
). Вы знаете, что MySQL не знает, и часто вы не можете сказать MySQL иначе. Недостатком является то, что это не может быть адаптировано к другим ситуациям, например если вы (иногда) используете большие окна в своем запросе, или gauche <= droite
больше не соответствует действительности.