LINUX.ORG.RU

Есть разница этих SQL запросов?

 


0

1

Подготовка

CREATE TABLE product_types (
	id serial PRIMARY key,
	type_name text	
);

CREATE TABLE products (
	id serial PRIMARY key,
	product_name TEXT,
	type_id int REFERENCES product_types(id)
);

INSERT INTO product_types (type_name) 
	VALUES ('Фрукт'),('Овощь'),('Ягода');

INSERT INTO products (product_name, type_id) 
	VALUES ('Яблоко', 1),
		   ('Груша', 1),
		   ('Картофель', 2),
		   ('Вишня', 3),
		   ('Клубника', 3),
		   ('Малина', 3);

Между этими запросами есть отличия? Joinы же позже появились ?

SELECT 
	product_name,
	type_name
FROM 
	products p, 
	product_types pt
WHERE 
	p.type_id = pt.id;

SELECT 
	product_name,
	type_name
FROM 
	products p 
		JOIN product_types pt ON p.type_id = pt.id;

Ответ на: комментарий от mythCreator
explain SELECT     
        product_name,
        type_name
FROM 
        products p, 
        product_types pt
WHERE 
        p.type_id = pt.id;
                                   QUERY PLAN                                    
---------------------------------------------------------------------------------
 Hash Join  (cost=38.58..63.74 rows=1200 width=64)
   Hash Cond: (p.type_id = pt.id)
   ->  Seq Scan on products p  (cost=0.00..22.00 rows=1200 width=36)
   ->  Hash  (cost=22.70..22.70 rows=1270 width=36)
         ->  Seq Scan on product_types pt  (cost=0.00..22.70 rows=1270 width=36)
(5 rows)

=# explain 
SELECT 
        product_name,
        type_name
FROM 
        products p 
                JOIN product_types pt ON p.type_id = pt.id;
                                   QUERY PLAN                                    
---------------------------------------------------------------------------------
 Hash Join  (cost=38.58..63.74 rows=1200 width=64)
   Hash Cond: (p.type_id = pt.id)
   ->  Seq Scan on products p  (cost=0.00..22.00 rows=1200 width=36)
   ->  Hash  (cost=22.70..22.70 rows=1270 width=36)
         ->  Seq Scan on product_types pt  (cost=0.00..22.70 rows=1270 width=36)

не нашел отличий в планах.

AlexKiriukha ★★★★ ()
Последнее исправление: AlexKiriukha (всего исправлений: 2)
Ответ на: комментарий от AlexKiriukha

Не касательно этого тривиального случая - есть практика написания тестов, чекающих планы используемых запросов?

sislochka ()

Разницы нет. В оракле есть прикольная штука для outer join-ов для такого синтаксиса - пишешь where product.type_id (+)= product_types.id (могу порядок путать, уже не помню точно).

Но вообще лучше писать явные join-ы. Проще читать.

Legioner ★★★★★ ()
Ответ на: комментарий от perl5_guy

в умном вопросе содержится 80% ответа.
зачем его задавать?

Minona ★★ ()

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

Конкретно в твоём случае, разницы может не будет, но всё может резко поменяться, если ты начнёшь вкидывать индексы, пойдёт дисбаланс по объёмам данных и пр.

Я практикую такую херню: во-первых join'ы, во-вторых, если join'ов больше двух, первым строить тот, который вернёт наименьшую выборку, а потом до-join'ить остатки + оооочень внимательно следить за индексами, вот чтоб ни-ни не промахнуться, иначе TABLE SCAN и привет.

DarkAmateur ★★★ ()
Ответ на: комментарий от DarkAmateur

Не, те два запроса полностью эквивалентны, разница только в том, что запятая как синоним CROSS JOIN – это архаизм.
Это как не использовать прототипы из C89, машинный код от такого не меняется.

Darth_Revan ★★★★★ ()
Ответ на: комментарий от Darth_Revan

разница только в том, что запятая как синоним CROSS JOIN – это архаизм

Ни разу не видел, чтобы кто-то использовал CROSS JOIN вместо запятой.

theNamelessOne ★★★★★ ()
Ответ на: комментарий от theNamelessOne

Я так написал для точности, CROSS JOIN сам по себе нужен очень редко.
Если взять декартово произведение (CROSS JOIN) и добавить к нему условие (WHERE), то получится внутреннее соединение с тем же условием.
Так запятую почти всегда и используют.

Darth_Revan ★★★★★ ()
Последнее исправление: Darth_Revan (всего исправлений: 1)
Ответ на: комментарий от DarkAmateur

первым строить тот, который вернёт наименьшую выборку, а потом до-join’ить остатки

В postgres если у тебя количество джойнов меньше join_collapse_limit (по умолчанию 8) планировщик проигнорирует то в каком порядке ты джойны пишешь.

Если ты знаешь что делаешь ты можешь явно задать для своей транзакции join_collapse_limit = 1, но вообще это костыль.

Алсо планировщик может работать не правильно потому что не знает о данных что-то что знаешь ты и в некоторых случаях можно ему помочь создав статистику.

mythCreator ()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.