- 1
- 2
- 3
- 4
- 5
- 6
SELECT id FROM (
SELECT a.id, b.idNOT FROM stable a
LEFT JOIN
(SELECT idNOT FROM nottable) b
ON a.id = b.idNOT ) fromtable
WHERE idNOT IS NULL
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
−170
SELECT id FROM (
SELECT a.id, b.idNOT FROM stable a
LEFT JOIN
(SELECT idNOT FROM nottable) b
ON a.id = b.idNOT ) fromtable
WHERE idNOT IS NULL
SQL Server compact не понимает NOT IN.
Эквивалент будет:
SELECT id FROM stable
WHERE id NOT IN (SELECT idNOT FROM nottable)
SELECT a.id FROM stable a LEFT JOIN nottable b ON (a.id = b.idNOT) WHERE b.idNOT IS NULL;
Там еще много чего... урезано.
Почему люди себе так усложняют жизнь? Ведь можно просто:
а) not in - стрёмная штука, если можно то стоит избегать её использования. в индекс оно не попадает.
б) подзапросы - плохо
в) left join на некоторых бд быстрее, так что в этом случае может просто не говно, а даже благо - не даёт написать кривой запрос.
Выше DBdev предложил вариант.
Но суть не в том: говном были обе попытки автора. :) Первая попадает под ваше а), а вторая... Ну... Утверждение б) не верно, правильно составленные подзапросы там, где они действительно нужны - хорошо. Но в реализации автора они таки не нужны, у него получился очень достойный этого сайта запрос. :)
потому и запостил;)
или это в ms sql не попадает?
WHERE id NOT IN (SELECT idNOT FROM nottable)
Один полуебок в подобном стиле заменил join, а потом оказалось, что во внутреннем запросе десятки тысяч идов и мускул тормозил, а потом падал.
>Пока данных было мало,
Причем тут кроссплатформенность-то?
приведи пример, а мы просто посмотрим explain plan
WHERE id IN (SELECT id FROM nottable)
Только подзапрос возвращает большое число строк (>10k)
Например, чтобы выбирать поля одновременно из джвух и более таблиц: Ваш кэп.
In most cases JOINs are faster than sub-queries and it is very rare for a sub-query to be faster.
In JOINs RDBMS can create an execution plan that is better for your query and can predict what data should be loaded to be processed and save time, unlike the sub-query where it will run all the queries and load all their data to do the processing.
Но реально на практике у меня подзапрос работал быстрее только когда надо было "дырки" в последовательностях значений считать: удалённые ID, пропущенные даты... Там просто с джоином слишком много повторяющихся строк получалось. :)
Не всегда, а только если тебе нахер не сдались поля из второй таблицы.
Подзапросы учили не юзать готовя вас к встрече с СУБД, которые не умеют их толком оптимизировать ;)
А с точки зрения реляционной теории, в таких случаях, если я не ошибаюсь, что in, что exists, что join - все однохуйственно. Главное not in никогда не юзай, у него засада с null'ами и троичной логикой.
Ты ее в вузе проходил?
Нет конечно. Откуда реляционная теория в нашем Бобруйском Институте?) У нас на предмете, посвященном СУБД, рассказывали о Профессиональной Лисе...
А у нас тип приезжал, постоянно причесывал волосы, но про нормальные формы рассказал. Сети вел придурок зав.кафедры, и расказывал о модуляциях.
Но самое веселое было перед дипломом, ни один из наших кандидатов наук радистов не мог припаять ARM (нужна неделя и десяток микросхем, чтобы заполучить этот скилл). Из моих одногрупников только 2 нормальных, и то один из них одинэсник. Еще один типок также может припаивать армы, но дурачок уже не может использовать их возможности по-серьезному, хотя армы подгоняли много исходников для прошивки. Да, воспоминания.
60 ваттным паяльником с жалом в 5мм? :) Феном на хорошо залуженную плату то они влет садятся ;)
А ты где с ними встречался?
Да игрался для души с ARM и AVR :)
> Тот другой типок делал все это дело утюгом.
Жесть. А остальные детали в это время уплывали со своих мест? :) Самое зверство которое я учинял с электроникой - распайка материнки над печкой, которую топят углём... SMDятина падала и вспыхивала красивыми искорками, а я в перчатках варежках дергал разъемы, полевики, и прочие крупные и полезные вещи... Суровый сибирский демонтаж ;)
Остальное приходилось делать рассыпухой (её легко впаивать из-за малоножья) и впаивать после этой зверской операции.
Хм. LispGovno == crastinus?
Хотя, конечно,LispGovno тоже может быть рыжим, но не моим знакомым.
А хрен знает :) Полевики живые, микрухи, которые ими управляют - тоже. А остальные чипы проверить было нечем, да и незачем...
потому то я и переспросил, что может дело в мс скл
а по твоей ситуации - 1) твои таблицы свежие, может в постгресе тоже, как в оракле, надо сделать analyze table для достоверных тестов?, 2) в таблице особо данных не хранится, вот ты навесь по килобайту данных на строку, чтобы индекс было ещё выгодней юзать
Навесил по три колонки с char(255), сделал analyze... Планы не поменялись. Не хочет он юзать индексы для разности множеств, и хеширует вторую табличку заново...
Кажется понял в чем причина... В первых двух запросах он индексы использует в merge (как я понимаю тупо бежит по обоим индексам и выбирает общее).
В запросах на разность множеств же ему нужно проверять отсутствие записи во второй таблице для каждой записи из первой. И, видимо, хеш для этого подходит лучше чем b-tree, поэтому он и хеширует айдишки вместо использования индекса. Так что надо увеличить количество записей в nottable, чтобы затраты на построение хеша перевесили...
очевидно, что в подзапросе idnot должен быть fk на первую таблицу (иначе какого черта вообще вычитать две несвязанные друг с другом колонки)
оракл не делает лишнего индекса для колонки fk, вот, видимо и приходится ему только юзать натуральный индекс (pk) от stable
...сейчас уже лень открывать опять удаленный стол на работу, чтобы вставить план запроса от ОП
Since PostgreSQL cannot flush a hashed subplan onto the disk, it will estimate the subquery size, and if it decides that it will not fit into work_mem, it will resort to using a mere subplan which will be either executed for each row from t_left, or materialized and the rows will be searched for in a loop.
This can be very bad since the optimizer will just change the plan as t_right will overgrow a certain limit and one day the query will just become very slow without any apparent reason.
Печалька ;)
Вывод: в постгресе not in работает быстро ровно до тех пор, пока хеш входит в память. А просто in, join, exists/not exists и решение от DBdev с left join + not null планируются и исполняются вполне адекватно даже при 3кк различных id в nottable.
т.е. везде косты получились одинаковые
на самом деле всю эту портянку я привёл лишь в качестве примера того, что в нормальной субд должен быть нормальный оптимизатор - выкидывающий подзапросы, если их можно выкинуть, знающий состав индексов и умеющих их к месту применить и т.д.
mysql - это явно не нормальная субд
у меня тут _таблицы_ по 300гб остались в наследство в субд, не вылезшей из 80х, то ли дело MyISAM
> копеечные 10к строк в подзапросе
Уже на них стало плохо. И?
Ну если "субд из 80х" работает быстрее и стабильнее "субд 21го века", и не залипает на жалких 10к строк в подзапросе, то у меня для тебя плохие новости :)
как комариный укус в анус.
Однокласники?
Все, адью, засиделся я с вами. Парсер давно написан. Подрочить и спать. Хотя можно и просто спать, я подумаю.
зачем пользоваться консольным клиентом, если есть нормальные инструменты
в частности, все что я поднасрал в топик, я сделал через sql developer
однако, sql developer имеет фичу нагло виснуть при открытии 50+ МБ .sql файлов, но это уже совсем другая история
dbms_xplan же
вумудщзук красиво с раскрывающимся меню план выдает, но это непригодно для копипаста в наш уютный
Что это?
sql developer нагуглил и пользовался им только ради этого.
Все-таки интересно, почему эти полуебки выбрали такую сортировку?
При этом, на DB2 объёмы были вполне промышленными (ну и сервера не бытовые, конечно), а вот для обрушения mysql хватило десятков тысяч записей.
Не исправили.
SELECT * FROM tabl WHERE id IN (...)
Превращается в
SELECT * FROM tabl WHERE EXIST(...).
Что в этом плохого? У нормального оптимизатора что exists, что in одинаково быстры.
Исходный запрос был не хай лоад, а примерно такой
SELECT id FROM stable
WHERE id NOT IN
(SELECT idNOT FROM nottable1
UNION
SELECT idNOT FROM nottable2
.....)
Юнион удалил бы повторяющиеся индексы, и никаких бы проблем не было (даже десятка индексов не выбрал бы).
Нагруженные системы это другое дело. Да и какая нагрузка будет в MS-эквиваленте sqlite?