Вопрос

У меня есть запрос, который выглядит так:

select
id
, int1
, int2
, (select count(*) from big_table_with_millions_of_rows 
    where id between t.int1 and t.int2)
from myTable t
where
....

Этот выбор возвращает ровно одну строку. Идентификатор, используемый в встроенном выборе, является индексированным столбцом (первичный ключ). Если я заменю t.int1 а также t.int2 С значениями Int1/Int2, возвращенными этой единственной строкой, запрос завершается в миллисекундах. Если я выполняю запрос, как указано выше - т.е. с ссылками на Int1/Int2, это занимает около 10 минут. Когда я запускаю Profiler и смотрю, что на самом деле происходит, я вижу, что 99% случаев, когда двигатель занят возвратом данных из встроенного запроса. Похоже, что MySQL на самом деле работает

select ... from big_table_with_millions_of_rows 

немного встроенного запроса один раз перед нанесением

where id between t.int1 and t.int2

бит до результата. Может ли это быть правдой? Если нет, то что происходит? Я всегда думал, что встроенный SELECTS были потенциально опасными, потому что они выполняются в строке как последний элемент запроса, но для подобных ситуаций, где начальные SELECT действительно очень избирательный, это может быть очень эффективным. Кто -нибудь может пролить свет на это?

РЕДАКТИРОВАТЬ: Спасибо за отзыв до сих пор. Я обеспокоен не столько в рядовом характере встроенного запроса, а о том, что он, кажется, не может использовать первичный индекс ключей при столкновении с переменными, а не (одинаковыми) жесткими значениями. Я предполагаю, что если анализ не был запущен в последнее время, то оптимизатор предполагает, что он должен сделать сканирование таблицы, поскольку не знает о распределении данных. Но не должен ли тот факт, что поиск диапазона не выполняется на первичном ключе, не компенсирует это?

Это было полезно?

Решение

Если коррелированная подзадность не оптимизирована хорошо, попробуйте этот запрос:

select
  t.id
, t.int1
, t.int2
, count(*)
from myTable t
left outer join big_table_with_millions_of_rows b
  on (b.id between t.int1 and t.int2)
where
....
group by t.id

Это должно оптимизировать намного лучше.


По вашему обновлению: верно, MySQL - не самые сложные RDBMS на рынке с точки зрения оптимизации. Не удивляйтесь, когда MySQL не может оптимизировать такие угловые дела, как это.

Я фанат MySQL за его простоту использования и открытого исходного кода и все эти хорошие вещи, но правда в том, что его конкуренты намного опережают MySQL с точки зрения технологий. У каждого RDBMS есть некоторые «слепые пятна», но MySQL, кажется, больше.

Также убедитесь, что вы используете последнюю версию MySQL. Они улучшают оптимизатор в каждом выпуске, так что вы можете получить лучшие результаты с более новой версией.

Другие советы

Старайтесь избегать коррелированных подразделений, используя Join, если можете.

Посмотрите это отличное видео на MySQL Performance на YouTube. Анкет Отправляйтесь в 31:00.

Если подзадные ссылки поля из его содержащегося запроса, подзадность должна быть повторно заново на каждом ряду в содержащемся запросе, потому что ссылочные поля могут отличаться в каждом ряду. Если он полностью автономен, его можно запустить один раз, прежде чем внешний запрос начнет обработку.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top