Pull to refresh

Comments 8

Как-то по тексту, особенно поначалу, плохо понятно, что именно Вы делаете, на каком запросе получаете данные. Если смотреть по тексту, то создаётся странное впечатление.

Сначала Вы выполняете "извлечение из него только уникальных значений", то есть словно бы используете GROUP BY вместо DISTINCT.

Однако далее по тексту Вы получаете "количество встретившихся значений для каждого элемента" - то есть словно получаете COUNT(*).

И наконец Вы всё же публикуете запросы - становится понятно, что Вы считаете COUNT(DISTINCT x).

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

Согласен, возможно, стоило чуть более подробно описать, что конкретно делалось. Однако запросы, которые выполнялись и скрипт инициализации был приведен. Это обычные запросы вида SELECT A, COUNT(*) FROM TABLE GROUP BY A, и он действительно будет возвращать только уникальные значения из колонки A. Дополнительный COUNT(*) был сделан, чтобы сократить выдачу из запроса только одной строкой, чтобы исключить из сравнения время, которое уходит на передачу данных из сервера до клиента. Опять же для максимальной честности результатов, потому что один запрос будет выдавать 100 тыс. строк, а другой только 10. Довольно распространенные запросы во всех СУБД, с которыми можно столкнуться. Цель статьи была подсветить, что такие запросы могут выполняться значительно быстрее, если количество уникальных значений мало. И вот MySQL и другие СУБД могут делать это автоматически из коробки, однако для PostgreSQL и MS SQL Server я привел примеры, как это тоже можно оптимизировать.

Дополнительный COUNT(*) был сделан, чтобы сократить выдачу из запроса только одной строкой, чтобы исключить из сравнения время, которое уходит на передачу данных из сервера до клиента.

Вообще странно, что Вы смотрите не чистое время выполнения запроса, а время вместе со временем взаимодействия с клиентом.

Собственно привлечение клиента у Вас и дало странные по времени результаты. Например, для MySQL 8.0.30 на моей сравнительно слабой машинке (AMD Athlon(tm) 64 X2 Dual Core Processor 6000+ 3.00 GHz, 8 Gb RAM, Windows 10 x64 22H2) на Ваших запросах (в запросах на SELECT x был добавлен LIMIT с выбором одной, самой последней, записи, чтобы сервер получил весь промежуточный набор) получены такие результаты (усреднённо по 10 запускам, разброс ~ 10%):

Вывод COUNT(*) - 625, 13 и 5 мс.

Вывод SELECT x - 534, 8 и 4 мс.

Так что мне кажется, что бОльшая часть полученного Вами времени выполнения запроса к собственно выполнению запроса имеет весьма слабое отношение. Хотя тенденция по снижению времени выполнения - та же.

Спасибо большое за комментарии! Постарался убрать все неточности по тексту, поменял тестовые запросы и перезапустил весь тест заново. Идея действительно была показать как работают SELECT DISTINCT или COUNT DISTINCT в разных СУБД. Что MySQL из коробки работает очень хорошо на столбце в любой кадинальностью, и что можно оптимизировать в PostgreSQL и MS SQL Server, чтобы добиться схожего результата.

Насчет методики все-таки не соглашусь. Все равно все запросы надо запускать из какого-то клиента к СУБД (например, стандартной консольной утилите локально). Это, конечно, даст более чистые результаты, но они не будут кардинально отличаться от тех, которые будут получены общим внешним клиентом. Тут задача была именно показать кардинальное снижение времени выполнения, если запускать на колонках с низкой кардинальностью в MySQL, и что такого снижения нет в остальных двух СУБД и там надо действовать по-другому, чтобы добиться ускорения.

Все равно все запросы надо запускать из какого-то клиента к СУБД (например, стандартной консольной утилите локально).

Ну если совсем строго - то в случае MySQL можно обойтись и без внешнего клиента при выполнении теста. При этом сам тест выполняется из Event Procedure. Да, процесс Event Scheduler при этом является клиентом, конечно, но он обеспечивает настолько минимальный расход времени на взаимодействие клиента с сервером, что им можно смело пренебречь. Правда, такая методика накладывает определённые ограничения на сам тест (скажем, невозможен возврат значений в выходной поток, и вывод, если он нужен, придётся сохранять в таблицу либо файл, недоступны некоторые типы запросов и пр.).

Идея действительно была показать как работают SELECT DISTINCT или COUNT DISTINCT в разных СУБД.

Не скажу за другие СУБД, а в случае MySQL разница между SELECT x FROM t GROUP BY x и аналогичным по результату SELECT DISTINCT x FROM t довольно любопытна..

вы подогрели жопы многих баз? бывает такое понятие "кэш субд", у разных субд он ведет себя по разному, иногда его нужно настраивать, чтобы он по вашему "нагревался" данными..

Как раз я не ставил задачу затюнить каждую СУБД по максимуму под конкретный запрос. Поэтому были взяты Docker контейнеры с настройками по умолчанию. Да и я сомневаюсь, что кэш в этом запросе даст какой-то другой результат. Первые 5 запусков я делал холостыми, потому что на них как раз время может сильно варьироваться. Само время выполнения запроса тут вторично, важно скорее, что loose scan или его имитация дает качественно другое время выполнения. А то, что MS SQL что-то выполняет за 2 секунды, а PostgreSQL за одну, например, не суть важно, потому что в продакшене конечно все будет по-другому. Тут важнее смотреть не столько разницу между СУБД, сколько в пределах одной СУБД.

Если вы можете подсказать какие-то настройки, которые могут сделать сравнение еще более честным, буду вам очень благодарен.

Sign up to leave a comment.

Articles