2015-11-05 2 views
2
TableA 
------ 
id 
Name 
other_fields 

TableB 
------ 
A_id (foreign key to TableA.id) 
other_fields 

Выбор записей из TableB которых ссылки на записи в TableA с некоторым специфическим свойством (например Name = "Alice")Объединение здесь кажется излишние

Это можно легко сделать с помощью присоединения:

SELECT TableB.* 
FROM TableA INNER JOIN TableB on TableA.id = TableB.A_id 
WHERE TableA.Name = "Alice" 

Бытии используемый для процедурного программирования, объединение кажется излишним и ненужным, поскольку нам фактически не нужна информация от TableA, кроме id из Alice.

Так что - если предположить, что Alice уникален - есть способ сделать это (псевдокод):

variable alice_id = get id of Alice from TableA 

SELECT * 
FROM TableB 
WHERE A_id = alice_id 

Если да, то она должна быть использована в пользу классического метода JOIN? Это быстрее? (В принципе, конечно)

+0

Связанный: http://stackoverflow.com/questions/5274618/inner-join-and-where-in-clause-performance –

ответ

3

Вы спрашиваете, если вы можете сделать это:

SELECT * FROM TableB WHERE A_id = (SELECT id FROM TableA WHERE Name = 'Alice'); 

Это совершенно законный вопрос, но MySQL будет работать гораздо лучше делает присоединиться, потому что подзапрос трактуется как второй отдельный запрос. Используя команду MySQL EXPLAIN (просто положите ее перед запросом SELECT), будут показаны индексы, временные таблицы и другие ресурсы, которые используются для запроса. Это должно дать вам представление, когда один запрос быстрее или эффективнее другого.

+0

Используется для C++, для меня JOINS кажутся худшим злом. Я мысленно связываю их с созданием новой матрицы из 2-х матриц. Нужно оборачивать голову тем, как делать вещи. – bolov

+0

SQL - это другая парадигма. Реляционные базы данных оптимизированы для обработки объединений. Использование процедурного кода, чтобы избежать объединения, в значительной степени является анти-шаблоном. – APC

+0

С другой стороны ... C++ может работать только со скалярами; SQL оптимизирован для работы с векторами. Делайте что-то в массе, не идите. –

1

Для вашей рабочей нагрузки и индексов вам необходимо выполнить план выполнения запросов и время выполнения запросов. В любом случае вам будет полезно иметь индекс по имени.

Я считаю, что оба запроса будут в конечном итоге схожими планами. Давайте проверим это.

Создание таблиц

create table tablea (id int primary key, nm as varchar(50)); 
create index idx_tablea_nm on tablea(nm); 
create table tableb(a_id int, anotherfield varchar(100), 
     key idx_tableb_id(a_id), 
     constraint fk_tableb_tablea_id foreign key (a_id) references tablea (id)); 

Давайте сделаем EXPLAIN на первый:

explain select tableb.* from tablea inner join tableb on tablea.id = tableb.a_id where tablea.nm = 'Alice'; 
+----+-------------+--------+------+-----------------------+---------------+---------+-------------------+------+--------------------------+ 
| id | select_type | table | type | possible_keys   | key   | key_len | ref    | rows | Extra     | 
+----+-------------+--------+------+-----------------------+---------------+---------+-------------------+------+--------------------------+ 
| 1 | SIMPLE  | tablea | ref | PRIMARY,idx_tablea_nm | idx_tablea_nm | 53  | const    | 1 | Using where; Using index | 
| 1 | SIMPLE  | tableb | ref | idx_tableb_id   | idx_tableb_id | 5  | tablea.id   | 1 | Using where    | 
+----+-------------+--------+------+-----------------------+---------------+---------+-------------------+------+--------------------------+ 

Давайте EXPLAIN на второй:

explain select * from tableb where a_id = (select id from tablea where nm = 'Alice'); 
+----+-------------+--------+------+---------------+---------------+---------+-------+------+--------------------------+ 
| id | select_type | table | type | possible_keys | key   | key_len | ref | rows | Extra     | 
+----+-------------+--------+------+---------------+---------------+---------+-------+------+--------------------------+ 
| 1 | PRIMARY  | tableb | ref | idx_tableb_id | idx_tableb_id | 5  | const | 1 | Using where    | 
| 2 | SUBQUERY | tablea | ref | idx_tablea_nm | idx_tablea_nm | 53  |  | 1 | Using where; Using index | 
+----+-------------+--------+------+---------------+---------------+---------+-------+------+--------------------------+ 

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

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