Комментарии 36
Огромное спасибо за статью!
Интересно, а насколько сложно сделать эстиматор из последнего примера надёжным?
Кроме того все эти данные без костылей есть в системных таблицах, это уже 5 лет назад изложено в вики постгреса: wiki.postgresql.org/wiki/Count_estimate
Вот то что вам нужно:
SELECT reltuples::BIGINT AS estimate
FROM pg_class
WHERE oid = 'schema_name.table_name'::regclass;
Я-то, по старой привычке, пользуюсь, но не думал, что имеет смысл.
Неправда. Не было такого никогда и нет сейчас. Почитайте хотя бы Джонатана Льюиса: count(1) не лучше чем count(), более того оптимизатор заменяет count(1) на count()
Нет, не было такого никогда. Count(*) уже сам по себе оптимален. Никакие count(1) улучшить его не могут, а вот ухудшить всякие вариации типа count(rowid) или count(-2) могут. Это были мифы а-ля Бурлесоновщина…
Ссылки по теме:
jonathanlewis.wordpress.com/2008/10/31/count
jonathanlewis.wordpress.com/2020/02/25/count-again-2
Не аналогично. В оракле count(1) заменяется на звёздочку автоматически
Дочитайте до конца — там шутка про скорость набора. Оптимизатор трансформирует запрос ещё до выполнения — прочитайте по моей ссылке у льюиса
10122, 00000, "Disable transformation of count(col) to count(*)"
Резюмируя — давайте пользоваться открытым по чтобы не строить догадки )
Это не ошибка, а event, позволяющий отключить эту трансформацию. И оракл на порядок более документирован и имеет неимоверное количество средств же ага и траблшутинга. По возможностям оптимизатора, количеству трансформаций, гибкости и мощности движка, и бэкграунд сервисов он также всех опережает. Например, тот же full table scan или index fast full scan могут работать в параллели с direct path reads, в отличие от PostgreSql. У него, конечно же, есть свои огромные минусы(например, цена и выводящая из себя тех поддержка), но закрытость ПО — это несерьезный довод.
Да что вы говорите… Более предсказуема? Кому? И давно вы анализировали код PostgreSql? Достаточен ли ваш уровень чтобы анализировать его код? А сколько вообще разработчиков, работающей с СУБД с достаточным уровнем c/c++? Как вы считаете, что быстрее и удобнее и правильнее: прочитать гайд, документацию или исходный код СУБД?
Зы. Что-то своих статей не пишите с анализом кода pg, а только переводите чужие в которых нет ни одного куска кода...
Зыы. Может уже остановитесь со своей маркетинговой чушью?
Если у вас большой опыт работы с различным по, то уверен, что довольно часто сталкивались с ситуацией, когда сообщение от системы не информативно и не передает суть произошедшего события. И здесь помочь могут только исходники
п.с. я не понимаю, зачем вы стараетесь выгородить оракл, описывая его преимущества (маркетинговые), хотя речи об этом не было совсем. Может быть вы лично заинтересованы, не знаю
:D это смотря какую IDE использовать :D во многих из них count(*) вставляется автокомплитом, а 1 придётся вручную вводить, так что звездочка рулит :D
И в целом кодстайл так себе, процедуры счётчика лучше было разделить на две или три — позволит избежать интересных ошибок. Впрочем это перевод, так что претензии наверное не по адресу :-)
Запись count (1) или count (id) на самом деле медленнее, чем count (*)
А если Id — это поле (или колонка) NOT NULL, по которому построен уникальный индекс?
Помнится, это по крайней мере в некоторых реляционных СУБД давало заметное ускорение.
Использование deferred constraint trigger гарантирует, что блокировка строки в mytable_count будет максимально короткойЭто верно, но для TRUNCATE mytable триггер выполняется немедленно, и это может быть проблемой. Рассмотрим такой пример:
транзакция 1: begin; TRUNCATE mytable;…… commit; --начинается раньше, но долгая
транзакция 2: begin; Insert into mytable; commit; — позже и короткая
Но транзакции 2 придётся ожидать окончания транзакции 1, поскольку транзакция 1 заблокировала таблицу mytable_count
И надо учитывать, что deferred constraint trigger может привести к такой проблеме:
в транзакции сначала вставили\удалили строки в mytable, а позже есть логика, завязанная на количество записей в mytable, и берём мы его из mytable_count, но в mytable_count не учтены вставили\удаления, выполненные в этой транзакции
Делаем быстрее POSTGRESQL COUNT (*)