2015-05-28 1 views
1
SELECT COALESCE(tb2.number_new, tb1.number_original) as number 
FROM 
tb1 
LEFT JOIN tb2 ON tb2.id = tb1.id 
WHERE 
tb1.number_original = <PARAM> OR tb2.number_new = <PARAM> 

Вышеприведенный запрос генерирует полное сканирование таблицы. Как его оптимизировать?LEFT JOIN with WHERE в поле первой таблицы ИЛИ поле второй таблицы

EXPLAIN:

+----+-------------+-------+-------+----------------+----------------+---------+------+----------+----------------------------------------------------+ 
| id | select_type | table | type | possible_keys | key   | key_len | ref | rows  | Extra            | 
+----+-------------+-------+-------+----------------+----------------+---------+------+----------+----------------------------------------------------+ 
| 1 | SIMPLE  | tb1 | index | number_original| number_original| 5  | NULL | 11683843 | Using index          | 
| 1 | SIMPLE  | tb2 | ALL | PRIMARY  | NULL   | NULL | NULL |  2 | Using where; Using join buffer (Block Nested Loop) | 
+----+-------------+-------+-------+----------------+----------------+---------+------+----------+----------------------------------------------------+ 

Проблема мне нужно решить это:

Учитывая tb1 таблица, которая имеет поле number_original, я хочу, чтобы создать таблицу tb2 сохранить новое значение для этого поля, (я назвал number_new). Я сделал это, потому что не могу изменить значение number_original, и мне не понравилось создавать поле number_new в таблице tb1, потому что оно было бы NULL в 95% + из 11 миллионов записей.

+0

Я не уверен, что это поможет или нет, но ... избавиться от или с помощью той же инструкции, что и select WHERE COALESCE (tb2.number_new, tb1.number_original) = 'может быть более эффективным ... но ... он никогда не будет искать original_number, если new_number заселен .... Таким образом, результаты будут отличаться ... – xQbert

+0

'WHERE' с' COALESCE' не имеет значения, полное сканирование таблицы ... :( –

+0

You Если вы делаете 'CREATE TABLE', давайте посмотрим его и' INSERT'. Если вы делаете «CREATE TABLE», вы можете увидеть его и «ВСТАВИТЬ». –

ответ

0

Это ваш запрос:

SELECT COALESCE(tb2.number_new, tb1.number_original) as number 
FROM tb1 LEFT JOIN 
    tb2 
    ON tb2.id = tb1.id 
WHERE tb1.number_original = <PARAM> OR tb2.number_new = <PARAM>; 

Это сложная проблема. Сначала попробуйте два индекса: tb1(number_original, id) и tb2(number_new, id).

Вы могли бы переписать запрос как:

SELECT COALESCE(tb2.number_new, tb1.number_original) as number 
FROM tb1 LEFT JOIN 
    tb2 
    ON tb2.id = tb1.id 
WHERE tb1.number_original = <PARAM> 
UNION 
SELECT COALESCE(tb2.number_new, tb1.number_original) as number 
FROM tb1 LEFT JOIN 
    tb2 
    ON tb2.id = tb1.id 
WHERE tb2.number_new = <PARAM>; 

Каждый подзапрос должен использовать один из индексов. Это повлечет за собой накладные расходы union (с повторным удалением), но это может быть лучше, чем полное сканирование таблицы.

0

Вам нужны индексы для tb1.number_original и tb2.number_new, а также, возможно, также для tb1.id и tb2.id. Затем вам понадобится MySQL, чтобы воспользоваться вашими индексами. Я не знаю, будет ли это так.

В целом, СУБД будет сканировать таблицу, если ни один индекс не отвечает на аргументы поиска для запроса.

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