Как стать автором
Обновить
83
4
Олег Самойлов @splarv

программист

Отправить сообщение

Разница по времени небольшая, но всё равно говорит о том, что max() можно оптимизировать до такой же скорости.

Нда, вы меня озадачили. И дело вовсе не в том, что похоже вы лидируете в этом негласном соревновании. Я думаю тут имеет место косяк в планировщике PostgreSQL, по идее (моей), ваш distinct и то что я предложил с max должны были бы давать одинаковый результат по времени. Для меня неочевидно, где max проигрывает. Но вот что я заметил. Похоже, когда я писал статью, я отключил
set enable_seqscan to false;
Потому что изначально экспериментировал с маленькой таблицей, а потом забыл включить его обратно. А это, оказалось, важно. Тестирование ниже проводилось с выбранным вами индексом
ON employees USING btree (department_id, salary DESC)
Если
set enable_seqscan to false;
то
method | execution_time
----------+---------------------
distinct | 0.21507000043988228
max | 0.24675499747693538
rank | 0.3294130029976368
window | 0.8126180001497268

А вот если
set enable_seqscan to true; -- это по умолчанию
method | execution_time
----------+---------------------
rank | 0.3307799963951111
distinct | 0.46438600090146065
max | 0.5562520008087158
window | 0.8275660008192063

И тут rank, внезапно, выходит на первое место (хотя быстрее работать не стал). Очевидно (по времени выполнения), что это ошибка планировщика. Здесь по дефолту стояло random_page_cost=4. Я попытался исправить это выставив random_page_cost=1, что разумно, всё целиком и полностью помещается в кэш ОЗУ.
set enable_seqscan to true; set random_page_cost=1;
method | execution_time
----------+---------------------
distinct | 0.21147700223326682
max | 0.30990499967336654
rank | 0.32765100106596945
window | 0.8102550018429756

Уже похоже на правду. но не очень. После random_page_cost=1 почти все демонстрируют такие же хорошие результаты как и с set enable_seqscan to false, кроме max. Который чуть-чуть все же работает медленнее и если сравнить планы:
Nested Loop
-> HashAggregate
Group Key: employees.department_id
-> Seq Scan on employees
-> Index Scan using ds2 on employees e
Index Cond: ((department_id = employees.department_id) AND (salary = (max(employees.salary))))
А с отключенным сиквенс сканом
Nested Loop
-> GroupAggregate
Group Key: employees.department_id
-> Index Only Scan using ds2 on employees
-> Index Scan using ds2 on employees e
Index Cond: ((department_id = employees.department_id) AND (salary = (max(employees.salary))))
Видно, что проблема в оптимизаторе планировщика.
И теперь я ломаю голову, чего бы еще такого подкрутить в конфиге, чтобы с включенным сиквенс сканом, postgresql все же бы выдавал оптимальный план (с двумя индекс сканами) для метода max. Изменение effective_cache_size не помогает.

Может он по запаху перегара от студента ориентировался.

Это значит, что ошибка в дашборде, надо там исправлять. Исправлять надо там, где "не подумали".

По поводу первого довода - контрдоводы. Не все, но некоторые компании практикуют, чтобы главным в проекте (продукте), был product owner, причем ключевое качество для такого по сути начальника это... не иметь вообще никакой профессии. Быть "эффективным менеджером" или бюрократом. Поскольку профессии у него нет, то он особенно сильно боится быть уволенным и панический держится за своё место. Очень сомнительная кадровая политика. Так вот, от таких начальником максимум чего добьёшься это фразы: "Хочу, чтобы всё было круто!" Но если сверху прилетит недовольство, он тут же переобуется и всю вину свалит на тех, кто ниже, т.е. на вас.
Но не в этом суть. Представьте себе строго математическую задачу по нахождению элементов из какого-то множества обладающих определённым свойством. Если таких элементов несколько, а вы в ответе напишите только одно, то ответ будет неправильным.
Запрос, тем более такой, в пяток строк, это не софтверная библиотека. Вот софтверную библиотеку там да, надо проектировать с взглядом на будущее. А проектировать запрос в пять строк с прицелом, как вы его будите переписывать под другие задачи, чтобы код был универсальным и reusable. Ну нет, выглядит гротескно. И дело даже не в количестве строк. Другое дело если бы вы мутили функцию, тогда да, можно было бы подумать об более широком её использовании в будущем.

Видимо у вас очень убедительный голос.

Почему? Если посмотрите направо, то там такая же. Тянется от к первичного ключа к foreign key и у foreign key значок бесконечность. Так и тут. У каждого босса может быть много сотрудников. Подумайте и вы поймете.

Ну нет. Даже на "один раз запустить" можно по быстрому накидать такое решение, которое положит всю базу данных, точнее не её, а микросервис, он перестанет отвечать на запросы. Как сказал один мой знакомый: "я пишу говнокод, зато делаю это очень быстро". Не надо так делать в любом случае.
Что же касается задачи, то если ответ условиям задачи соответствует, то он должен быть принят. Нужен другой ответ, изменяйте условия задачи. Например вместо сотрудника с максимальной зарплатой попросить вывести топ 3 было бы корректно, хотя и там можно было бы решить не через rank(). Но кандидат бы показал, что он умеет. А вот "угадай, какой вариант я знаю, там есть оконные функции", это уже неправильная постановка задачи. Такие задачи надо задавать не на собеседовании на тех.должность, а на битве экстрасенсов.

По поводу первого тезиса аргумент не принимается. Запросы надо писать с нуля под задачу, а не костылить старые под "похожую" задачу.
А по поводу вашего варианта, уже было.
https://habr.com/ru/articles/828728/comments/#comment_27040894

За "Гости из будущего" (если я не ошибаюсь) респект, а за "помучил", повторю еще раз. На собеседовании вы будите показывать то, как вы реально собираетесь работать, свои рабочие навыки. За демонстрацию того, что в армии называется "тупить", вы можете услышать "спасибо, было очень интересно" очень быстро. :)

Из всех собеседований два стоят особняком, то в Национальный Российский Депозитарий и в Промсвязьбанк, через который проходит гос. и оборонный заказ. Обе конторы официально крышует ФСБ. И только там на собеседовании собеседовали мне нагло и беспардонно врали, самым уверенным голосом.
Например в НРД вешали лапшу на уши, что если в столбце одно значение преобладает 100, то он считается "нерепрезентативным" и его postgresql никогда в индексированном поиске использоваться не будет. Я возражал, что не бывает нерепрезентативных столбцов, всё дело в конкретном значении и Postgresql не использует поиск по 100 потому что он находится в списке наиболее часто встречаемых значений. И для доказательства своей правоты предложил вместо 100 выбрать 1. На что собеседователь сверился с какой-то табличкой и выбрал 5, как я понимаю еще одно число из списка наиболее часто встречаемых значений и тем самым "доказал" мою неправоту. А еще там меня убеждали, что если в процедуре встречается begin end, то это "анонимный блок" и входя в него postgresql всегда открывает вложенную транзакцию.
В Промсвязьбанке, меня убеждали, что если написать выражение, например:
with cte as (select * from table) delete from cte; то оно нормально отработает и якобы он сам лично это протестировал и так работает начиная с версии 9.4. Разумеется ложь.
Парадокс в том, что жулики занимают ведущие, руководящие посты в тех.отделах именно там, где ФСБ следит, чтобы этого не было. Другими словами значимых для государства конторах. А в обычных коммерческих фирмах я ни разу не встречал ничего подобного, разная степень знаний, но всегда адекватное поведение, никаких наглых развешиваний лапши.
Так что с вашими талантами нести пургу, идите туда. Там вы отлично впишитесь в коллектив.

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

Как бы да, ваш вариант хорош. Но например при приёме на работу в государственные или окологосударственные структуры, которые крышует ФСБ и в которые есть реальный интерес у вражеских разведок внедрить своих людей, там накладывается ограничение, что им важно видеть, что именно этот человек реально решает задачу, а не группа поддержки из вражеских разведок. :) Да даже если это коммерческий банк, у него такой же интерес, но быть может уже против агентов из ОПГ. Так что дать задачку на дом это встречается очень редко. Чаще собеседование должно проводится онлайн, а иногда и требуют обязательно видеть твоё лицо при этом. :)

Ну смотрите, статья на самом деле не про то, какой самый эффективный алгоритм для решения поиска строки с максимальным значением. Как в комментах мудро заметили, вообще нет смысла заморачиваться с оптимизацией, если нет выборки реальных данных. Ваш "вырожденный" случай с одним отделом означает что в предприятии вообще отделов нет, а это уже противоречит условию задачи.
Статья была про другое, о чём я и написал в выводах статьи. Но если вам интересно очень тщательно изучить алгоритмы поиска строки с максимальным значением, вы можете это сделать сами.

Ну смотрите. В отделе два сотрудника с максимальной зарплатой. Вы выводите только одного. Причем случайного. Как вы объясните, почему у вас возникло такое "усмотрение"? Потому что так вам было ленивее и проще? :) Даже не смотря на то, что вы придумали какое-то "негласное правило на собеседовании", которого нет, на собеседовании вы демонстрируете именно то, как вы потом и будите работать. Если так, то умный человек вас на работу не возьмёт.

Вас научили врать твёрдым и уверенным голосом? :)

Так я ничего не говорил плохого про код или функционал. А вот документация иногда несовершенна, все же программистам больше нравится писать код, а не обычный текст. Нравилось бы писать текст, стали бы писателями. Но её исправляют, если предложить как.

Я же не просто рассказал, как было на собеседовании, тут вы могли бы придумать, что это я всё нафантазировал, всё было по другому, уж вы то точно знаете, вас там не было. Это хрестоматийная задача, которая есть и на Stack Overflow (с лидирующим решением как раз через rank()) и я привел ссылку на оригинал в блоге JitBit. Последнее я даже перевёл и выложил на Хабр.

Даже боюсь предположить, где у вас "задний end". У меня есть только передний.

1
23 ...

Информация

В рейтинге
1 023-й
Откуда
Москва, Москва и Московская обл., Россия
Дата рождения
Зарегистрирован
Активность