А при чем тут антипатии? :D Это вот это уже смешно. До сих пор в техническом вопросе антипатии проявляли только вы: "это я люблю, это я не люблю". Вот если бы я вас назвал извращенцем, не имея на то оснований, только подозрения, вот это да, было бы проявлений эмоций или антипатий. Потому что было бы оскорбление. А в контексте Кончиты Вурст это не было ни оскорблением, ни проявлением каких-либо эмоций. Это было техническим термином. Как бы вам объяснить. Вот если бы назвать мужчину женщиной, это да, оскорбление. А называть мужчину мужчиной, женщину женщиной, извращенца извращенцем тут нет никаких оскорблений. Это объективная характеристика человека. И использовал я её для указания типа, к кому может применяться пол other, там как бы два случая, по медицинским показаниям и извращенцы, которые сами себя так представляют.
Не хамите, сейчас вы осознанно хамите. Да, я указал, что такой пол может употребляться как к людям с генетической патологией, так и к бородатым мужикам, которые даже не евнухи, а просто извращенцы. Это надо было чтобы объяснить читателем, почему не boolean.
И для того чтобы закрыть тему вашего глубокого внутреннего мира и ваших переживаний как связанных с тем, что я назвал Томаса Нойвирта извращенцем, как и с тем, что вы так и не научились пользоватьсяe enum, я предлагаю посмотреть следующий ролик.
То что вы испытываете какие-то чувства типа любовь или нелюбовь к элементам языка программирования никакого отношения к рациональной аргументации не имеет. Из того, что вы написали дальше, я понял, что вы во-первых не понимаете для чего этот инструмент, а во-вторых не умеете им пользоваться.
Нет, конкретный пример, кто может использовать пол other указанный в стандарте ИКАО. В контексте, почему не надо использовать boolean для пола, что чрезвычайно широко распространено.
Такой тип данных как перечисление есть во многих языках программирования. Есть и у PostgreSQL. Да, остро заточенный инструмент с конкретным предназначением.
То что программировать вы пытаетесь через эмоции "это я люблю, это я не люблю", это я понял. Почему вы к enum испытываете какие-то определенные эмоции, это я уже не понял. Но может мне и не стоит понимать ваш богатый внутренний мир и какие вы эмоции испытываете, когда пытаетесь программировать?
Да нет, это только означает что лично вас в этой статье интересует только неприязнь и любовь. Причем в выдуманном вами столбце. Я же отношение к людям в никакой столбец не заношу. Но ко всяким озабоченным троллям к которые к технической статье громоздят комментарии на тему их сексуальной озабоченности я действительно испытываю неприязнь. Ибо оффтопик.
Во-первых вы критикуете не статью про PostgreSQL, а какой-то столбец "любовь и неприязнь", которой в статье не было.
А во-вторых если вы "про него" имеете в виду Томаса Нойвирта (а такие слова были только про него), то про него такими словами говорить можно.
В-третих, судя по вашим комментам вы искали вовсе не PostgreSQL.
К счастью, в комментах ничего не кажется. Но озабоченных понабежало, это точно. Такое ощущение, что есть люди, которые постоянно мониторят хабр запуская запросы поисковые "sex" и "извращенцы".
Апдейтить на что? Я не вижу в этом смысла. Более того, я так и не понял, как именно вы хотите "улучшить". Таблицу с несколькими enum я еще представить себе могу, но вот запрос по всем сразу с общим индексом… Это настолько редкая и специфичная тема, что не вижу смысла придумывать какие-то общеполезные тесты, потому что там их попросту нет. Если вы сами понимаете, чего вы хотите — сделайте. Для вас адаптировать мои скрипты (или написать свои еще лучше) это плевое дело. Даже не понимаю, почему вы пускаетесь в демагогию. Кода бы пришлось напечатать гораздо меньше, чем букв, что вы уже напечатали. Или вы только умничать умеете?
Что значит "изобретать сегрегацию разработчиков"? Вы даже этого не понимаете? Разработчики на PostgreSQL пишут на SQL и plpgsql, разработчики PostgreSQL пишут на С. Первые работают с внешним интерфейсом БД, вторые лезут во внутренности. Это совершенно разные люди, с разными навыками и знаниями.
То есть на одной странице индекса у вас всего раз 7 встретится ваш "female", занимая эдак байт 28, а все остальные >8K будут забиты tid'ами соответствующих записей. То есть колебание размера типа привело бы к колебанию размера индекса на жалкие доли процента.
Да, это объясняет.
Так enum это и есть связанная таблица. Вы сами меня в это убедили))
Есть концептуальная разница. enum редактируется с помощью DDL, внешняя таблица с помощью DML. DDL это прерогатива программиста (ну или другими словами database owner), обычный юзер работает с DML и DDL используется только для временных объектов. На планете около 200 стран, причем ситуация постоянно меняется. Страны разделяются, сливаются, происходят революции и переименовываются. А еще возникают непризнанные признанные Россией республики, с которыми у нас особые отношения в том числе по правилам пересечения границы и законодательству. И сейчас наблюдаем как одна из непризнанных республик может исчезнуть. Что программистам каждый раз переписывать код в случае изменения политических раскладов? Поэтому список стран лучше сделать в виде внешней таблицы, а не enum. Чтобы сами пользователи могли его редактировать.
Вы лучше вот что расскажите, раз вы так хорошо знаете внутренности PostgreSQL. Правда интересно. Почему запросы с join (nested loops) настолько заметно медленнее, чем запросы с подзапросом? Планы же у них одинаковые. И почему хэш индекс в PostgreSQL настолько трешовый? А переписать его можете? Ведь правда, очень позорно выглядит.
Не волнуйтесь, к извращенцам я совершенно равнодушен. Кроме тех случаев, когда они пытаются меня соблазнить, а такое, к сожалению, бывает. И тех случаев когда они к технической статье пишут комментарии об их тяжелой судьбе, мол они все такие из себя "цивилизованные", а никто этого не ценит. Вот я, например, не пишу к каждой технической статье комменты, что я обычный мужчина и предпочитаю женщин. Почему вам надо обязательно громко заявить, что вы предпочитаете использовать задний проход не по назначению или вообще себе яйца отрезать? Писать об этом в интернете, ходить на "парады" и т.д. Если по каким-то причинам не хотите брать пример с нормальных людей, так берите пример людей с другими отклонениями: зоофилов, некрофилов, копрофилов. Они никакие парады не устраивают и нигде о свои пристрастия не афишируют, просто уединяются где-то со своим объектом любви и тихо радуются жизни.
Даже не знаю, какого признания вы хотите от меня добиться. :) Я признаюсь, что я разработчик на PostgreSQL, а не разработчик PostgreSQL, а это, как вы, наверное, догадываетесь, две большие разницы. До эксперимента я не знал, что PostgreSQL выравнивает строки по машинным словам. Никогда не нужно было, да и в документации для разработчиков на PostgreSQL об этом не упоминается. Узнал я об этом только в результате эксперимента, что было для меня маленьким открытием. И это знание мне показалось полезным и интересным. И не только это, я думаю многие мои маленькие "открытия" разработчики PostgreSQL могли бы предугадать, зная всю эту кухню изнутри.
Более того, статья адресована даже не разработчикам на PostgreSQL, а в первую очередь веб разработчикам, типа тех, что в качестве enum используют внешнюю таблицу с ключом serial (и нулевым шагом у sequence) или создают таблицы из двух полей: bigserial primary key и jsonb, куда упихивают абсолютно все данные в денормализованном виде, а потом удивляются результам.
А по поводу ваших пожеланий, то я вам могу ответить примерно теми же словами, что мне ответил Том Лейн: "Если думаете, что можете сделать лучше, сделайте." :)
Может и не до конца. О такой проблеме впервые слышу. Теоретический такого быть не должно. Добавление нового значения enum это добавление одной новой строчки в служебную таблицу pg_enum. Откуда там может взяться такая блокировка? Откуда такая инфа?
Я пытался сказать, что даже без "tuple alignment" разница в размерах кортежа очень мала и такой тест в принципе теряет смысл.
Нет, не теряет, тем более в принципе. Именно благодаря тесту стало очевидно и что размеры таблиц одинаковы и что разница во времени выполнения запросов очень мала. Но больше всего меня удивило, что не смотря на все сказанное, при последовательном чтении таблиц разница между запросом по enum и "char" оказалось достаточно большой, чтобы превысить погрешность измерения. Так вас послушать, то и экспериментальная физика в принципе теряет всякий смысл. Зачем? Ведь теоретики все уже придумали. :) В общем если вы не видите смысл, это не значит что смысла нет, это значит что вы его не видите. :) Да и про индексы не понял, да значений всего три, но ведь распределение у этих значений не равновероятное, а 75%, 24%, 1%.
И моё опасение в том, что стоит только добавить ещё одно enum/"char"/smallint-поле (то есть сделать таблицу более приближённой к реальности) и картина тут же поменяется.
Да не сильно. Ведь поиск будет по индексу, а в индексе скорее всего будет только один enum. Не, конечно можно придумать всякие синтетические случаи, но думаю, это не интересно.
Пусть таблица состоит не только из пола, но скажем возраста и страны происхождения.
Категорический против. :) Пол в качестве enum это еще куда ни шло. А вот возраст… ни в какие ворота. Обычно возраст это дата. Но и то не всегда. :) У иностранцев в паспортах вполне может указан только год рождения. Или год и месяц. Потому что арабы или еще кто кочевал в это время по пустыни и не знали точную дату рождения. :) И как оформлять в таком случае дату рождения в БД это отдельный гемор, тоже знаю как минимум два способа. Все же такое, говорят, встречается (или встречалось?) только у пожилых, у молодые как правило свою точную дату рождения знают. Но возраст как enum??? Как это?
Страна происхождения, тоже. Т.е. да, бизнес логика может быть завязана на страну. Но я бы это реализовал через структуру связанных таблиц. А для того чтобы увязать все это с захардкоженной бизнес логикой с помощью enum ставил бы метки для бизнес логики.
Но суть вашего предложения я понял. Что будет, если в таблице будет несколько enum?
=> create table multisex1 (id float, sex1 sex_enum not null, sex2 sex_enum not null, sex3 sex_enum not null);
CREATE TABLE
=> create table multisex2 (id float, sex_char1 "char" not null, sex_char2 "char" not null, sex_char3 "char" not null);
CREATE TABLE
=> insert into multisex1 (id,sex1,sex2,sex3) select id,sex,sex,sex from sex1;
INSERT 0 10000000
=> insert into multisex2 (id,sex_char1,sex_char2,sex_char3) select id,sex_char,sex_char,sex_char from sex2;
INSERT 0 10000000
=> vacuum full freeze analyze multisex1, multisex2;
VACUUM
\dt+
=> \dt+
List of relations
Schema | Name | Type | Owner | Persistence | Size | Description
--------+-----------+-------+-------+-------------+--------+-------------
public | multisex1 | table | olleg | permanent | 498 MB |
public | multisex2 | table | olleg | permanent | 422 MB |
public | sex1 | table | olleg | permanent | 422 MB |
public | sex2 | table | olleg | permanent | 422 MB |
public | sex5 | table | olleg | permanent | 498 MB |
Да, размер таблицы стал различаться, а в случае тремя enum (multisex1) таблица ровно такая же, как… таблица с одним varchar (sex5). А в случае с тремя "char" размер таблицы не изменился вовсе. Т.е. выравнивание там скорее всего не по столбцам, а по строкам. Мне кажется про то как размер небольших полей, которых в таблице несколько, влияет на размеры таблиц и на производительность запросов, на эту тему можно писать другую статью. :)
Что же касается собственно поиска, то тут я уже не могу придумать достаточно универсальный и интересный для исследования поиск. Все случаи уже будут синтетические. Но если кому интересно поэкспериментировать применительно к конкретно его случаю, он сможет легко адаптировать мои скрипты для своей цели.
Это просто смешно. :) Но позоритесь как раз вы. :) Не я же извращенец. А вы почему-то этот пример воспринимаете слишком лично. Поэтому я предлагаю вместо того чтобы обсуждать почему вас так сильно оскорбило то, что я Кончиту Вурст (точнее Томаса Нойвирта) называл извращенцем вернуться к PostgreSQL.
А мне стыдно читать комменты, где вместо того чтобы обсуждать технические вопросы, пишут всякие подозрительные "цивилизованные" люди, которые обижаются на то, что я извращенцев называл извращенцами. Вот если бы я нормальных людей называл извращенцами, тогда бы да, это было бы оскорбление. А извращенцев называть извращенцами это констатация факта. Ну это все равно что женщину называть женственной или человека с диагнозом имбицил называть имбицилом. Ну или как еще можно охарактеризовать бородатого мужика, который надевает на себя женское платье и идет отлить в женский туалет?
Хотя нет, зря я не проверил.
=> SELECT
-> pg_column_size(row(0::float, 'a'::"char")),
-> pg_column_size(row(0::float, 0::smallint)),
-> pg_column_size(row(0::float, 0::oid));
pg_column_size | pg_column_size | pg_column_size
----------------+----------------+----------------
33 | 34 | 36
(1 row)
Все таки так разница есть, на столько байт, сколько и должно было бы быть. А вот размеры таблиц точно равны.
Не знаю, экспериментальный факт. :) После pg_prewarm видел, что запросы сначала выполняются несколько более медленно, но со временем "ускоряются". Уточню, это видел я еще на 11 PostgreSQL, не знаю как сейчас. Сейчас я просто "обновил" старый эксперимент на 13 PostgreSQL и выложил в хабр.
ну вообще-то и индексы обычно читаются совсем не последовательно.
Не совсем так. Мы же говоря абстрактно про индекс имеем в виду btree, ведь так? Движение по дереву да, непоследовательно. Но потом же в конце концов попадаем в листовые страницы, а там уже последовательное чтение. :) Подробнее можете почитать здесь: https://habr.com/ru/company/postgrespro/blog/330544/
может. но изменение размера одного поля на несколько байт не особо повлияет на размер таблицы.
Опять же, наша разница в том, что вы рассуждаете гипотетический, а у меня эмпирические данные, поэтому могу не теоретизировать опираясь на интуицию и "здравый смысл", а отсылать к конкретным данным, ради чего все это и было и сделано.
И так, sex1 это таблица enum с 4 байтными oid, sex5 таблица с varchar. Cлово "мужчина" (как наиболее часто встречаемое) 7 букв в UTF-8, т.е. 14 байт. Ну а в реальности:
=> select pg_column_size(sex) from sex1 limit 1;
pg_column_size
4
(1 row)
=> select pg_column_size(sex),sex from sex5 limit 1;
pg_column_size | sex
15 | мужчина
(1 row)
т.е. разница почти в 4 раза, столько же, сколько разница между enum и гипотетическим 1 байтовым типом данных. Поэтому можно использовать разницу между sex1 и sex5 для того, чтобы спрогнозировать выигрыш от использования 1 байтных данных. Хотя, конечно, зависимость не будет пропорциональной, но качественно можно.
Размер таблицы и индекса можете посмотреть в статье. Индексы почти не отличаются, таблицы по размерам отличаются более заметно. Но размеры таблиц я упомянул только в теоретических рассуждениях. Интересно же было время выполнения запроса. При поиске последовательном чтением разница заметна, не в разы, но визуально в десятки процентов. Кстати, только заметил, при последовательном чтении даже очевидно, что "char" немного быстрее, чем enum, хотя размеры у них одинаковые, причем разница очевидна даже с учетом погрешности измерений (высота полосок). В случае поиска по индексу разница не столь существенна, но все равно она есть и её можно оценить.
Да я согласен с вашими "не особо", "практический нет" и т.д. Просто не понимаю с чем вы спорите? Вам не нравится, что вместо гипотетических рассуждений в стиле "не особо или быть может особо" я взял и померил? И поэтому есть эмпирические данные, которые можно анализировать.
Разница все равно есть. Конечно, скорее всего можно пренебречь процессорным временем, сравнивается ли в регистрах 1 байт или 4 байта. Но меньше размер — меньше размер таблицы и индекса -> они лучше влазят во все уровни кэшей, их больше попадает в различные write ahead в различные кэши и т.д. Это может быть таблица читается случайным образом, но индекс то нет. Да и таблица может искаться последовательным чтением. И на это я тоже тестировал.
Согласен с тем, что разница, скорее всего, будет небольшая. Это можно увидеть на примерах с enum и varchar. Данные в varchar тоже в несколько раз больше 4 байт в enum, точно так же как 4 байтный enum больше 1 байтных данных. Но это стало понятно только после того как я задался этим вопросом и померил эмпирический. Тогда то и стало понятно точно, какой выигрыш есть и на сколько. Больше всего разница как раз в поиске последовательном чтении, при поиске по индексу (1% выборка) она небольшая, примерно 3%, но она все же есть. А теоретический рассуждать за и против, приводить доводы одни и другие можно было бы долго.
А при чем тут антипатии? :D Это вот это уже смешно. До сих пор в техническом вопросе антипатии проявляли только вы: "это я люблю, это я не люблю". Вот если бы я вас назвал извращенцем, не имея на то оснований, только подозрения, вот это да, было бы проявлений эмоций или антипатий. Потому что было бы оскорбление. А в контексте Кончиты Вурст это не было ни оскорблением, ни проявлением каких-либо эмоций. Это было техническим термином. Как бы вам объяснить. Вот если бы назвать мужчину женщиной, это да, оскорбление. А называть мужчину мужчиной, женщину женщиной, извращенца извращенцем тут нет никаких оскорблений. Это объективная характеристика человека. И использовал я её для указания типа, к кому может применяться пол other, там как бы два случая, по медицинским показаниям и извращенцы, которые сами себя так представляют.
Не хамите, сейчас вы осознанно хамите. Да, я указал, что такой пол может употребляться как к людям с генетической патологией, так и к бородатым мужикам, которые даже не евнухи, а просто извращенцы. Это надо было чтобы объяснить читателем, почему не boolean.
И для того чтобы закрыть тему вашего глубокого внутреннего мира и ваших переживаний как связанных с тем, что я назвал Томаса Нойвирта извращенцем, как и с тем, что вы так и не научились пользоватьсяe enum, я предлагаю посмотреть следующий ролик.
https://youtu.be/bYraAP4UbF4
Не весь, но первые минута пять секунд там как раз про это.
На этом разговор закончен.
То что вы испытываете какие-то чувства типа любовь или нелюбовь к элементам языка программирования никакого отношения к рациональной аргументации не имеет. Из того, что вы написали дальше, я понял, что вы во-первых не понимаете для чего этот инструмент, а во-вторых не умеете им пользоваться.
Нет, конкретный пример, кто может использовать пол other указанный в стандарте ИКАО. В контексте, почему не надо использовать boolean для пола, что чрезвычайно широко распространено.
Такой тип данных как перечисление есть во многих языках программирования. Есть и у PostgreSQL. Да, остро заточенный инструмент с конкретным предназначением.
То что программировать вы пытаетесь через эмоции "это я люблю, это я не люблю", это я понял. Почему вы к enum испытываете какие-то определенные эмоции, это я уже не понял. Но может мне и не стоит понимать ваш богатый внутренний мир и какие вы эмоции испытываете, когда пытаетесь программировать?
Да нет, это только означает что лично вас в этой статье интересует только неприязнь и любовь. Причем в выдуманном вами столбце. Я же отношение к людям в никакой столбец не заношу. Но ко всяким озабоченным троллям к которые к технической статье громоздят комментарии на тему их сексуальной озабоченности я действительно испытываю неприязнь. Ибо оффтопик.
Во-первых вы критикуете не статью про PostgreSQL, а какой-то столбец "любовь и неприязнь", которой в статье не было.
А во-вторых если вы "про него" имеете в виду Томаса Нойвирта (а такие слова были только про него), то про него такими словами говорить можно.
В-третих, судя по вашим комментам вы искали вовсе не PostgreSQL.
К счастью, в комментах ничего не кажется. Но озабоченных понабежало, это точно. Такое ощущение, что есть люди, которые постоянно мониторят хабр запуская запросы поисковые "sex" и "извращенцы".
Апдейтить на что? Я не вижу в этом смысла. Более того, я так и не понял, как именно вы хотите "улучшить". Таблицу с несколькими enum я еще представить себе могу, но вот запрос по всем сразу с общим индексом… Это настолько редкая и специфичная тема, что не вижу смысла придумывать какие-то общеполезные тесты, потому что там их попросту нет. Если вы сами понимаете, чего вы хотите — сделайте. Для вас адаптировать мои скрипты (или написать свои еще лучше) это плевое дело. Даже не понимаю, почему вы пускаетесь в демагогию. Кода бы пришлось напечатать гораздо меньше, чем букв, что вы уже напечатали. Или вы только умничать умеете?
Что значит "изобретать сегрегацию разработчиков"? Вы даже этого не понимаете? Разработчики на PostgreSQL пишут на SQL и plpgsql, разработчики PostgreSQL пишут на С. Первые работают с внешним интерфейсом БД, вторые лезут во внутренности. Это совершенно разные люди, с разными навыками и знаниями.
Да, это объясняет.
Есть концептуальная разница. enum редактируется с помощью DDL, внешняя таблица с помощью DML. DDL это прерогатива программиста (ну или другими словами database owner), обычный юзер работает с DML и DDL используется только для временных объектов. На планете около 200 стран, причем ситуация постоянно меняется. Страны разделяются, сливаются, происходят революции и переименовываются. А еще возникают непризнанные признанные Россией республики, с которыми у нас особые отношения в том числе по правилам пересечения границы и законодательству. И сейчас наблюдаем как одна из непризнанных республик может исчезнуть. Что программистам каждый раз переписывать код в случае изменения политических раскладов? Поэтому список стран лучше сделать в виде внешней таблицы, а не enum. Чтобы сами пользователи могли его редактировать.
Вы лучше вот что расскажите, раз вы так хорошо знаете внутренности PostgreSQL. Правда интересно. Почему запросы с join (nested loops) настолько заметно медленнее, чем запросы с подзапросом? Планы же у них одинаковые. И почему хэш индекс в PostgreSQL настолько трешовый? А переписать его можете? Ведь правда, очень позорно выглядит.
Нету там графы "отношения", статья не про это.
Не волнуйтесь, к извращенцам я совершенно равнодушен. Кроме тех случаев, когда они пытаются меня соблазнить, а такое, к сожалению, бывает. И тех случаев когда они к технической статье пишут комментарии об их тяжелой судьбе, мол они все такие из себя "цивилизованные", а никто этого не ценит. Вот я, например, не пишу к каждой технической статье комменты, что я обычный мужчина и предпочитаю женщин. Почему вам надо обязательно громко заявить, что вы предпочитаете использовать задний проход не по назначению или вообще себе яйца отрезать? Писать об этом в интернете, ходить на "парады" и т.д. Если по каким-то причинам не хотите брать пример с нормальных людей, так берите пример людей с другими отклонениями: зоофилов, некрофилов, копрофилов. Они никакие парады не устраивают и нигде о свои пристрастия не афишируют, просто уединяются где-то со своим объектом любви и тихо радуются жизни.
Даже не знаю, какого признания вы хотите от меня добиться. :) Я признаюсь, что я разработчик на PostgreSQL, а не разработчик PostgreSQL, а это, как вы, наверное, догадываетесь, две большие разницы. До эксперимента я не знал, что PostgreSQL выравнивает строки по машинным словам. Никогда не нужно было, да и в документации для разработчиков на PostgreSQL об этом не упоминается. Узнал я об этом только в результате эксперимента, что было для меня маленьким открытием. И это знание мне показалось полезным и интересным. И не только это, я думаю многие мои маленькие "открытия" разработчики PostgreSQL могли бы предугадать, зная всю эту кухню изнутри.
Более того, статья адресована даже не разработчикам на PostgreSQL, а в первую очередь веб разработчикам, типа тех, что в качестве enum используют внешнюю таблицу с ключом serial (и нулевым шагом у sequence) или создают таблицы из двух полей: bigserial primary key и jsonb, куда упихивают абсолютно все данные в денормализованном виде, а потом удивляются результам.
А по поводу ваших пожеланий, то я вам могу ответить примерно теми же словами, что мне ответил Том Лейн: "Если думаете, что можете сделать лучше, сделайте." :)
Может и не до конца. О такой проблеме впервые слышу. Теоретический такого быть не должно. Добавление нового значения enum это добавление одной новой строчки в служебную таблицу pg_enum. Откуда там может взяться такая блокировка? Откуда такая инфа?
Нет, не теряет, тем более в принципе. Именно благодаря тесту стало очевидно и что размеры таблиц одинаковы и что разница во времени выполнения запросов очень мала. Но больше всего меня удивило, что не смотря на все сказанное, при последовательном чтении таблиц разница между запросом по enum и "char" оказалось достаточно большой, чтобы превысить погрешность измерения. Так вас послушать, то и экспериментальная физика в принципе теряет всякий смысл. Зачем? Ведь теоретики все уже придумали. :) В общем если вы не видите смысл, это не значит что смысла нет, это значит что вы его не видите. :) Да и про индексы не понял, да значений всего три, но ведь распределение у этих значений не равновероятное, а 75%, 24%, 1%.
Да не сильно. Ведь поиск будет по индексу, а в индексе скорее всего будет только один enum. Не, конечно можно придумать всякие синтетические случаи, но думаю, это не интересно.
Страна происхождения, тоже. Т.е. да, бизнес логика может быть завязана на страну. Но я бы это реализовал через структуру связанных таблиц. А для того чтобы увязать все это с захардкоженной бизнес логикой с помощью enum ставил бы метки для бизнес логики.
Но суть вашего предложения я понял. Что будет, если в таблице будет несколько enum?
Да, размер таблицы стал различаться, а в случае тремя enum (multisex1) таблица ровно такая же, как… таблица с одним varchar (sex5). А в случае с тремя "char" размер таблицы не изменился вовсе. Т.е. выравнивание там скорее всего не по столбцам, а по строкам. Мне кажется про то как размер небольших полей, которых в таблице несколько, влияет на размеры таблиц и на производительность запросов, на эту тему можно писать другую статью. :)
Что же касается собственно поиска, то тут я уже не могу придумать достаточно универсальный и интересный для исследования поиск. Все случаи уже будут синтетические. Но если кому интересно поэкспериментировать применительно к конкретно его случаю, он сможет легко адаптировать мои скрипты для своей цели.
Это просто смешно. :) Но позоритесь как раз вы. :) Не я же извращенец. А вы почему-то этот пример воспринимаете слишком лично. Поэтому я предлагаю вместо того чтобы обсуждать почему вас так сильно оскорбило то, что я Кончиту Вурст (точнее Томаса Нойвирта) называл извращенцем вернуться к PostgreSQL.
А мне стыдно читать комменты, где вместо того чтобы обсуждать технические вопросы, пишут всякие подозрительные "цивилизованные" люди, которые обижаются на то, что я извращенцев называл извращенцами. Вот если бы я нормальных людей называл извращенцами, тогда бы да, это было бы оскорбление. А извращенцев называть извращенцами это констатация факта. Ну это все равно что женщину называть женственной или человека с диагнозом имбицил называть имбицилом. Ну или как еще можно охарактеризовать бородатого мужика, который надевает на себя женское платье и идет отлить в женский туалет?
Хотя нет, зря я не проверил.
=> SELECT
-> pg_column_size(row(0::float, 'a'::"char")),
-> pg_column_size(row(0::float, 0::smallint)),
-> pg_column_size(row(0::float, 0::oid));
pg_column_size | pg_column_size | pg_column_size
----------------+----------------+----------------
33 | 34 | 36
(1 row)
Все таки так разница есть, на столько байт, сколько и должно было бы быть. А вот размеры таблиц точно равны.
Вы нашли эту статью через поиск хабр по слову sex? :) Часто статьи на эту тему попадаются?
Не знаю, экспериментальный факт. :) После pg_prewarm видел, что запросы сначала выполняются несколько более медленно, но со временем "ускоряются". Уточню, это видел я еще на 11 PostgreSQL, не знаю как сейчас. Сейчас я просто "обновил" старый эксперимент на 13 PostgreSQL и выложил в хабр.
Если так интересно, то можете сами все проверить.
Не совсем так. Мы же говоря абстрактно про индекс имеем в виду btree, ведь так? Движение по дереву да, непоследовательно. Но потом же в конце концов попадаем в листовые страницы, а там уже последовательное чтение. :) Подробнее можете почитать здесь:
https://habr.com/ru/company/postgrespro/blog/330544/
Опять же, наша разница в том, что вы рассуждаете гипотетический, а у меня эмпирические данные, поэтому могу не теоретизировать опираясь на интуицию и "здравый смысл", а отсылать к конкретным данным, ради чего все это и было и сделано.
И так, sex1 это таблица enum с 4 байтными oid, sex5 таблица с varchar. Cлово "мужчина" (как наиболее часто встречаемое) 7 букв в UTF-8, т.е. 14 байт. Ну а в реальности:
=> select pg_column_size(sex) from sex1 limit 1;
pg_column_size
4
(1 row)
=> select pg_column_size(sex),sex from sex5 limit 1;
pg_column_size | sex
15 | мужчина
(1 row)
т.е. разница почти в 4 раза, столько же, сколько разница между enum и гипотетическим 1 байтовым типом данных. Поэтому можно использовать разницу между sex1 и sex5 для того, чтобы спрогнозировать выигрыш от использования 1 байтных данных. Хотя, конечно, зависимость не будет пропорциональной, но качественно можно.
Размер таблицы и индекса можете посмотреть в статье. Индексы почти не отличаются, таблицы по размерам отличаются более заметно. Но размеры таблиц я упомянул только в теоретических рассуждениях. Интересно же было время выполнения запроса. При поиске последовательном чтением разница заметна, не в разы, но визуально в десятки процентов. Кстати, только заметил, при последовательном чтении даже очевидно, что "char" немного быстрее, чем enum, хотя размеры у них одинаковые, причем разница очевидна даже с учетом погрешности измерений (высота полосок). В случае поиска по индексу разница не столь существенна, но все равно она есть и её можно оценить.
Да я согласен с вашими "не особо", "практический нет" и т.д. Просто не понимаю с чем вы спорите? Вам не нравится, что вместо гипотетических рассуждений в стиле "не особо или быть может особо" я взял и померил? И поэтому есть эмпирические данные, которые можно анализировать.
Разница все равно есть. Конечно, скорее всего можно пренебречь процессорным временем, сравнивается ли в регистрах 1 байт или 4 байта. Но меньше размер — меньше размер таблицы и индекса -> они лучше влазят во все уровни кэшей, их больше попадает в различные write ahead в различные кэши и т.д. Это может быть таблица читается случайным образом, но индекс то нет. Да и таблица может искаться последовательным чтением. И на это я тоже тестировал.
Согласен с тем, что разница, скорее всего, будет небольшая. Это можно увидеть на примерах с enum и varchar. Данные в varchar тоже в несколько раз больше 4 байт в enum, точно так же как 4 байтный enum больше 1 байтных данных. Но это стало понятно только после того как я задался этим вопросом и померил эмпирический. Тогда то и стало понятно точно, какой выигрыш есть и на сколько. Больше всего разница как раз в поиске последовательном чтении, при поиске по индексу (1% выборка) она небольшая, примерно 3%, но она все же есть. А теоретический рассуждать за и против, приводить доводы одни и другие можно было бы долго.