2016-01-28 2 views
2

У меня есть две таблицы, каждая из которых содержит по шесть строк. Я пытаюсь присоединиться к двум, используя внутреннее соединение, но запрос выполнялся в течение 2 дней без завершения. Присоединиться в (обратите внимание, я использовал count(*) просто, чтобы я мог запустить объяснить, я на самом деле с помощью join в CTAS):MySQL Query с внутренним соединением очень медленным

SELECT count(*) 
FROM table1 t1, 
    table2 t2 
WHERE t1.col1 = t2.colA 
    AND t1.col2 = t2.colB; 

После небольшого исследования я нашел ниже запрос прекрасно работает:

SELECT count(*) 
FROM 
    (SELECT * 
    FROM table1) t1, 

    (SELECT * 
    FROM table2) t2 
WHERE t1.col1 = t2.colA 
    AND t1.col2 = t2.colB; 

Единственное различие между тем, что вместо таблицы, я использую подзапрос SELECT * FROM table;

Запуск планов объяснений показывает, что последний запрос создает индекс, когда он выбирает таблицу2. В то время как первый запрос использует буфер соединения (Block Nested Loop).

Несомненно, MySQL достаточно умен, чтобы решить, что два запроса практически идентичны и делают то же самое с обоими запросами? Я не понимаю, почему индекс нужен, потому что в любом случае требуется полное сканирование для обеих таблиц. Это временные/временные таблицы, поэтому, если бы я включил индекс, это было бы буквально просто для этого объединения.

Есть ли способ исправить это через конфигурацию MySQL?

+0

Можете ли вы опубликовать объяснения для обоих вариантов? Какая версия вашего mysql? – Shadow

ответ

1

Вы НУЖЕН индекс по крайней мере, одна из таблиц, даже такие, как

create index Temp1 on Table2 (colA, colB) 

Таким образом, ваш запрос из таблицы 1, соединенного с таблицей 2, так что даже если просмотр таблицы на всех таблицы 1 , вам нужно быстро найти записи (записи), которые соответствуют таблице 2. Если у НИКТА есть индекс, подумайте об этом так. Для каждой записи в таблице 1 просмотрите ВСЕ записи в таблице 2 и возьмите все записи, которые соответствуют ColA, ColB. Теперь вернемся к таблице 1 для записи SECOND ... вернитесь к таблице 2 для ВСЕХ записей, пока не найдете совпадение.

Поскольку у вас есть записи 6M, вы можете практически задушить корову (так сказать) на производительность. Имея индекс даже во второй таблице, когда запрос находится в первой записи, он может сразу перейти к строкам, которые соответствуют ColA, ColB, и как только эти записи A/B будут выполнены, он возвращается к первому Таблица.

Теперь для повышения эффективности служебной информации. Если таблицы BOTH проиндексированы на соответствующие Col1, Col2 и ColA, ColB, тогда у механизма будет в своей памяти/кеше весь блок записей для каждой общей области и не нужно будет возвращаться к необработанным страницам данных для другие элементы неоднократно.

Итак, хотя вы считаете, что это может быть непрактично, по-прежнему полезно обрабатывать большие табличные запросы. Кроме того, если в первой таблице есть несколько записей с одинаковыми значениями для Col1, Col2, но для других столбцов в таблице есть разные значения, и аналогично во второй таблице для нескольких ColA, ColB вы получите декартово результат , Рассмотрим следующий сценарий

Table1 
Col1 Col2 OtherColumn 
X  Y  blah1 
X  Y  blah2 
X  Y  blah3 


Table2 
ColA ColB OtherColumn 
X  Y  second blah1 
X  Y  second blah2 
X  Y  second blah3 

Простой запрос, как у вас есть

SELECT count(*) 
FROM table1 t1, 
    table2 t2 
WHERE t1.col1 = t2.colA 
    AND t1.col2 = t2.colB; 

приведет к отсчету 9. У вас есть 6M записи и возможный декартово результат? Надеюсь, это разъяснит некоторые проблемы, с которыми вы можете столкнуться.

+0

Спасибо за ваш ответ.Я понимаю, что вы говорите о перекрестном продукте, и если мне нужно добавить индекс, пусть будет так. Но это было достаточно умно, чтобы оптимизировать второй запрос, почему не первый? Я понимаю, что индексы в первую очередь относятся к тому, когда вы пытаетесь получить доступ к подмножеству ваших данных, и поэтому поиск большого набора выполняется намного быстрее. Я уверен, что индекс не понадобится в Oracle. –

+0

@AndrewEdwards, USE INDEXES. Вы получаете доступ к подмножеству данных. Каждый раз, когда вы находитесь в записи 1 в таблице «A», вы заботитесь только о подмножестве записей в таблице «B», которые соответствуют записям (ColA, ColB), связанным с записью таблицы «A». В противном случае вы сканируете каждую строку во второй таблице ... Теперь вы получаете, что используете ARE подмножество данных? – DRapp

Смежные вопросы