pg.ddx.io pgsql-ru-general@postgresql.org mailing list archive
help / color / mirror / Atom feedOPERATOR CLASS
6+ messages / 2 participants
[nested] [flat]
* OPERATOR CLASS
@ 2019-04-09 17:04 Dmitry E. Oboukhov <unera@debian.org>
0 siblings, 1 reply; 6+ messages in thread
From: Dmitry E. Oboukhov @ 2019-04-09 17:04 UTC (permalink / raw)
To: pgsql-ru-general@lists.postgresql.org
<div xmlns="http://www.w3.org/1999/xhtml">Есть вопросы по сабжу.</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">1. Можно ли как-то их просматривать в консоли (команды \d* не нашел). Если нет - в каких-то внутренних схемах?</div><div xmlns="http://www.w3.org/1999/xhtml">2. Можно ли как-то определить свой класс операторов по методу "такой же как оператор класс с таким-то именем, но оператор сравнения у него вот такой"?ции/</div><div xmlns="http://www.w3.org/1999/xhtml">3. Если п.2 нельзя, то можно ли вынуть из сабжа ссылки на его функции/операторы как-то?</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">Все вопросы про SQL, а не C :)</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">PS: что хочу</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">хочу GIN индекс по jsonb со своим оператором сортировки.</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">Насколько я понимаю для того что мне хочется нужно проделать следующее</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">1. Создать свой класс аналогичный jsonb_path_ops у которого будет всё так же как у предка, но моя функция FUNCTION 1 mycompare(jsonb, jsonb)</div><div xmlns="http://www.w3.org/1999/xhtml">2. Построить индекс по полю jsonb указав этот opclass</div><div xmlns="http://www.w3.org/1999/xhtml">3. PROFIT</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml"> </div;
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: OPERATOR CLASS
@ 2019-04-10 22:58 Nikita Glukhov <n.gluhov@postgrespro.ru>
parent: Dmitry E. Oboukhov <unera@debian.org>
0 siblings, 1 reply; 6+ messages in thread
From: Nikita Glukhov @ 2019-04-10 22:58 UTC (permalink / raw)
To: Dmitry E. Oboukhov <unera@debian.org>; +Cc: pgsql-ru-general@lists.postgresql.org
> Есть вопросы по сабжу.
> 1. Можно ли как-то их просматривать в консоли (команды \d* не нашел).
У нас есть патч для psql, который реализует требуемые команды для показа
информации об опклассах.
(см. тред "Psql patch to show access methods info"
https://www.postgresql.org/message-id/flat/1529675324.14193.5.camel%40postgrespro.ru)
Но он, к сожалению, уже не войдет в PostgreSQL 12.
Пример вывода этих команд для интересующего Вас jsonb_path_ops:
\dAo+ gin jsonb_path_ops
List operators of family related to access method
AM | Opfamily Schema | Opfamily Name | Operator | Strategy | Purpose | Sort family
-----+-----------------+----------------+----------------------+----------+---------+-------------
gin | pg_catalog | jsonb_path_ops | @> (jsonb, jsonb) | 7 | search |
gin | pg_catalog | jsonb_path_ops | @? (jsonb, jsonpath) | 15 | search |
gin | pg_catalog | jsonb_path_ops | @@ (jsonb, jsonpath) | 16 | search |
\dAp+ gin jsonb_path_ops
List of operator family procedures
AM | Family schema | Family name | Left | Right | Number | Proc name
-----+---------------+----------------+-------+-------+--------+------------------------------
gin | pg_catalog | jsonb_path_ops | jsonb | jsonb | 1 | btint4cmp
gin | pg_catalog | jsonb_path_ops | jsonb | jsonb | 2 | gin_extract_jsonb_path
gin | pg_catalog | jsonb_path_ops | jsonb | jsonb | 3 | gin_extract_jsonb_query_path
gin | pg_catalog | jsonb_path_ops | jsonb | jsonb | 4 | gin_consistent_jsonb_path
gin | pg_catalog | jsonb_path_ops | jsonb | jsonb | 6 | gin_triconsistent_jsonb_path
(5 rows)
\dAc gin jsonb*
Operator classes for index AM "gin"
Input type | Storage type | Operator class | Default?
------------+--------------+----------------------+----------
jsonb | text | jsonb_ops | yes
jsonb | integer | jsonb_path_ops | no
Если есть какие-то пожелания, каким хотелось бы видеть вывод этих
команд, мы рады будем их выслушать (а сообщение в том треде о полезности
этих команд от пользователя-разработчика опклассов, думаю, очень поможет
их продвижению в PostgreSQL 13).
> Если нет - в каких-то внутренних схемах?
pg_opclass, pg_opfamily, pg_amop, pg_amproc:
SELECT
amopstrategy AS "Strategy",
amoppurpose AS "Purpose",
oprname AS "Operator",
amoplefttype::regtype AS "Left type",
amoprighttype::regtype AS "Right type"
FROM
pg_amop amop,
pg_opfamily opf,
pg_operator opr
WHERE
opfname = 'jsonb_path_ops' AND
amopfamily = opf.oid AND
amopopr = opr.oid;
Strategy | Purpose | Operator | Left type | Right type
----------+---------+----------+-----------+------------
7 | s | @> | jsonb | jsonb
15 | s | @? | jsonb | jsonpath
16 | s | @@ | jsonb | jsonpath
(3 rows)
SELECT
amprocnum AS "Number",
amproc::regproc AS "Function",
amproclefttype::regtype AS "Left type",
amprocrighttype::regtype AS "Right type"
FROM
pg_amproc,
pg_opfamily
WHERE
opfname = 'jsonb_path_ops' AND
amprocfamily = pg_opfamily.oid;
Number | Function | Left type | Right type
--------+------------------------------+-----------+------------
1 | btint4cmp | jsonb | jsonb
2 | gin_extract_jsonb_path | jsonb | jsonb
3 | gin_extract_jsonb_query_path | jsonb | jsonb
4 | gin_consistent_jsonb_path | jsonb | jsonb
6 | gin_triconsistent_jsonb_path | jsonb | jsonb
(5 rows)
> 2. Можно ли как-то определить свой класс операторов по методу "такой
же как оператор класс с таким-то именем, но оператор сравнения у него
вот такой?"
> 3. Если п.2 нельзя, то можно ли вынуть из сабжа ссылки на его
функции/операторы как-то?
Создать новый опкласс на основе имеющегося, переопределяя только лишь
некоторые его операторы или функции, к сожалению, невозможно.
Но, используя CREATE OPERATOR CLASS, действительно можно выполнить эту
задачу, вручную добавив в него все переиспользумые операторы и функции,
помимо своего оператора сравнения. Как получить ссылки на
функции/операторы — описано выше.
> Все вопросы про SQL, а не C
> PS: что хочу
> хочу GIN индекс по jsonb со своим оператором сортировки.
> Насколько я понимаю для того что мне хочется нужно проделать следующее:
> 1. Создать свой класс аналогичный jsonb_path_ops у которого будет
всё так же как у предка, но моя функция FUNCTION 1 mycompare(jsonb, jsonb)
> 2. Построить индекс по полю jsonb указав этот opclass
> 3. PROFIT
Если переиспользовать jsonb_path_ops, то функция сравнения должна быть
не для jsonb, а для int4 — того типа, что используется для хранения
внутри (pg_opclass.opckeytype, "Storage type" в \dAc). Функцию
mycompare(jsonb, jsonb) вместе со своим оператором сравнения имеет смысл
использовать в опклассе для btree, а не для gin.
jsonb_path_ops хранит int4-хеши вида "hash (key1, key2, ..., keyN,
value)", где "key1, key2, ..., keyN" — это путь к полю объекта или
элемента массива "value", состоящий из названий ключей (массивы не
учитываются в путях).
jsonb_ops же хранит text'овые строки вида "Tvalue", где "T" это префикс
типа (key, string, number, boolean, null), а "value" это
название/значение поля объекта или значение элемента массива в тестовом
виде.
Поэтому для нового gin-опкласса, возможно, имеет смысл взять за основу
jsonb_ops, а не на jsonb_path_ops. Но вообще, хотелось бы поподробнее
узнать об этом новом операторе сравнения, тогда мы сможем лучше Вам помочь.
Вот на всякий случай пример создания копии jsonb_path_ops.
CREATE OPERATOR CLASS my_jsonb_path_ops
FOR TYPE jsonb USING gin AS
OPERATOR 7 @>,
OPERATOR 15 @? (jsonb, jsonpath),
OPERATOR 16 @@ (jsonb, jsonpath),
FUNCTION 1 btint4cmp,
FUNCTION 2 gin_extract_jsonb_path,
FUNCTION 3 gin_extract_jsonb_query_path,
FUNCTION 4 gin_consistent_jsonb_path,
FUNCTION 6 gin_triconsistent_jsonb_path,
STORAGE integer;
--
Nikita Glukhov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: OPERATOR CLASS
@ 2019-04-11 02:40 Dmitry E. Oboukhov <unera@debian.org>
parent: Nikita Glukhov <n.gluhov@postgrespro.ru>
0 siblings, 1 reply; 6+ messages in thread
From: Dmitry E. Oboukhov @ 2019-04-11 02:40 UTC (permalink / raw)
To: Nikita Glukhov <n.gluhov@postgrespro.ru>; +Cc: pgsql-ru-general@lists.postgresql.org <pgsql-ru-general@lists.postgresql.org>
<div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">11.04.2019, 01:58, "Nikita Glukhov" <n.gluhov@postgrespro.ru>:</div><blockquote xmlns="http://www.w3.org/1999/xhtml"; type="cite"><div bgcolor="#FFFFFF"><p>> Есть вопросы по сабжу.<br /><br />> 1. Можно ли как-то их просматривать в консоли (команды \d* не нашел).<br /><br />У нас есть патч для psql, который реализует требуемые команды для показа информации об опклассах.<br />(см. тред "Psql patch to show access methods info" <a rel="noopener noreferrer" href="https://www.postgresql.org/message-id/flat/1529675324.14193.5.camel%40postgrespro.ru">https:/... />Но он, к сожалению, уже не войдет в PostgreSQL 12.<br /><br />Пример вывода этих команд для интересующего Вас jsonb_path_ops:</p></div></blockquote><div xmlns="http://www.w3.org/1999/xhtml"><br />шикарно! будем ждать патча в релизе, а пока будем делать селекты :)</div><div xmlns="http://www.w3.org/1999/xhtml">спасибо!</div><blockquote xmlns="http://www.w3.org/1999/xhtml"; type="cite"><div bgcolor="#FFFFFF"> </div></blockquote><div xmlns="http://www.w3.org/1999/xhtml"> </div><blockquote xmlns="http://www.w3.org/1999/xhtml"; type="cite"><div bgcolor="#FFFFFF"> <p>> 2. Можно ли как-то определить свой класс операторов по методу "такой же как оператор класс с таким-то именем, но оператор сравнения у него вот такой?"<br />> 3. Если п.2 нельзя, то можно ли вынуть из сабжа ссылки на его функции/операторы как-то?<br /><br />Создать новый опкласс на основе имеющегося, переопределяя только лишь некоторые его операторы или функции, к сожалению, невозможно.<br />Но, используя CREATE OPERATOR CLASS, действительно можно выполнить эту задачу, вручную добавив в него все переиспользумые операторы и функции, помимо своего оператора сравнения. Как получить ссылки на функции/операторы — описано выше.</p></div></blockquote><div xmlns="http://www.w3.org/1999/xhtml"><br />:)</div><div xmlns="http://www.w3.org/1999/xhtml">я пока погрепал по исходникам и нашел структуру - сделал то же самое.</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">спасибо за более простой способ</div><blockquote xmlns="http://www.w3.org/1999/xhtml"; type="cite"><div bgcolor="#FFFFFF"> </div></blockquote><div xmlns="http://www.w3.org/1999/xhtml"> </div><blockquote xmlns="http://www.w3.org/1999/xhtml"; type="cite"><div bgcolor="#FFFFFF"> FUNCTION 1 btint4cmp, FUNCTION 2 gin_extract_jsonb_path, FUNCTION 3 gin_extract_jsonb_query_path, FUNCTION 4 gin_consistent_jsonb_path, FUNCTION 6 gin_triconsistent_jsonb_path, STORAGE integer;</div></blockquote><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">А вот по этим функциям где-то можно почитать разъяснения?</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">насколько я понимаю функция 1 - сравнивает именно то, что возвращает функция 2</div><div xmlns="http://www.w3.org/1999/xhtml">функция 3 нужна за тем же зачем и функция 2, но она работает над запросом</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">то есть если у нас</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">WHERE json_field @> json_query</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">то реально получается следующее</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">json_field пропускается через функцию 2 при индексировании</div><div xmlns="http://www.w3.org/1999/xhtml">json_query - пропускается через функцию 3 при самом запросе</div><div xmlns="http://www.w3.org/1999/xhtml">функция 1 используется для сравнения двух элементов между собой</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">а вот функции 4 и 6 - они для чего используются?</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">и вот еще вопрос. Некоторые из этих функций принимают internal в виде аргументов, соответственно вызвать их и посмотреть их поведение прямо из SELECT - непонятно как.</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">соответственно непонятно - как полностью с нуля написать свой OPERATOR CLASS не используя программирование на C (допустим хотим сделать скетч на SQL, возможно ли это сделать?)</div>
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: OPERATOR CLASS
@ 2019-04-11 10:31 Nikita Glukhov <n.gluhov@postgrespro.ru>
parent: Dmitry E. Oboukhov <unera@debian.org>
0 siblings, 1 reply; 6+ messages in thread
From: Nikita Glukhov @ 2019-04-11 10:31 UTC (permalink / raw)
To: Dmitry E. Oboukhov <unera@debian.org>; +Cc: pgsql-ru-general@lists.postgresql.org <pgsql-ru-general@lists.postgresql.org>
On 11.04.2019 5:40, Dmitry E. Oboukhov wrote:
> 11.04.2019, 01:58, "Nikita Glukhov" <n.gluhov@postgrespro.ru>:
>> FUNCTION 1 btint4cmp,
>> FUNCTION 2 gin_extract_jsonb_path,
>> FUNCTION 3 gin_extract_jsonb_query_path,
>> FUNCTION 4 gin_consistent_jsonb_path,
>> FUNCTION 6 gin_triconsistent_jsonb_path,
>> STORAGE integer;
> А вот по этим функциям где-то можно почитать разъяснения?
В официальной документации вроде бы все достаточно подробно описано:
https://www.postgresql.org/docs/11/gin-extensibility.html (на английском)
https://postgrespro.ru/docs/postgresql/11/gin-extensibility (на русском)
> насколько я понимаю функция 1 - сравнивает именно то, что возвращает
> функция 2
> функция 3 нужна за тем же зачем и функция 2, но она работает над запросом
> то есть если у нас
> WHERE json_field @> json_query
> то реально получается следующее
> json_field пропускается через функцию 2 при индексировании
> json_query - пропускается через функцию 3 при самом запросе
> функция 1 используется для сравнения двух элементов между собой
>
Да, все правильно. Хочу еще обратить внимание, что запрос может быть
другого, не jsonb, типа, а функция extractQuery() различает разные типы
запорсов по их номеру стратегии.
> а вот функции 4 и 6 - они для чего используются?
В документации про это написано, но если будут вопросы, отвечу на них.
Вот файл, в котором находится реализация этих функций для jsonb:
https://github.com/postgres/postgres/blob/master/src/backend/utils/adt/jsonb_gin.c
> и вот еще вопрос. Некоторые из этих функций принимают internal в виде
> аргументов, соответственно вызвать их и посмотреть их поведение прямо
> из SELECT - непонятно как.
> соответственно непонятно - как полностью с нуля написать свой OPERATOR
> CLASS не используя программирование на C (допустим хотим сделать скетч
> на SQL, возможно ли это сделать?)
Да, все GIN-функции, за исключением первой compare(), можно написать
сейчас только на C, и вызывать их из SQL нельзя. Но можно попробовать
сделать один раз специальный обобщенный OPERATOR CLASS, в котором из
функциий 2-6, написанных на C, будут вызываться другие функции с
соответствующими номерами (например, 12-16), в которых уже будут
использоваться только SQL-типы. Но полностью перенести всю
функциональность C-функций на уровень SQL будет не так просто, потому
что многие функции могут возвращать несколько значений сразу, а внутри
Postgres, по-моему, нет такого удобного способа вызова для функций с
OUT-параметрами, который есть для обычных функций. Например,
Datum *extractQuery(Datum query, int32 *nkeys, StrategyNumber n, bool
**pmatch, Pointer **extra_data, bool **nullFlags, int32 *searchMode)
возвращает массив извлеченных элементов, а также необязательные массив
флагов pmatch, массив произвольных С-указателй extra_data, массив
null-флагов nullFlags, и режим поиска searchMode. Если оставить только
обязательный массив элементов, то сигнатрура SQL-функции extract_query
будет совсем простой:
extract_query (query anyelement, strategy int2) RETURNS storage_type[]
но я не уверен, что с anyelement не возникнет каких-либо проблем.
И еще хочу на всякий случай напомнить, что у нас есть еще расширение
JsQuery (https://github.com/postgrespro/jsquery), которое содержит
опклассы, позволяющие выполнять по GIN-индексам более широкий ряд
jsonb-запросов (например, range-запросов, которые реализованы с
использования partialMatch). Возможно даже, что JsQuery решит Вашу
задачу. Сейчас мы работает в JsQuery на поддержкой jsonpath, который
выйдет в PostgreSQL12, а в будущем планируем даже перенести эти
JsQuery-опклассы в ядро.
--
Nikita Glukhov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: OPERATOR CLASS
@ 2019-04-11 12:40 Dmitry E. Oboukhov <unera@debian.org>
parent: Nikita Glukhov <n.gluhov@postgrespro.ru>
0 siblings, 1 reply; 6+ messages in thread
From: Dmitry E. Oboukhov @ 2019-04-11 12:40 UTC (permalink / raw)
To: Nikita Glukhov <n.gluhov@postgrespro.ru>; +Cc: pgsql-ru-general@lists.postgresql.org <pgsql-ru-general@lists.postgresql.org>
<div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">11.04.2019, 13:32, "Nikita Glukhov" <n.gluhov@postgrespro.ru>:</div><blockquote xmlns="http://www.w3.org/1999/xhtml"; type="cite"><div bgcolor="#FFFFFF"><p>On 11.04.2019 5:40, Dmitry E. Oboukhov wrote:</p><blockquote type="cite" cite="mid:2084391554950401@myt2-cd7fa496c4f7.qloud-c.yandex.net"><div>11.04.2019, 01:58, "Nikita Glukhov" <a rel="noopener noreferrer" href="mailto:n.gluhov@postgrespro.ru"><n.gluhov@postgrespro.ru></a>:</div> <blockquote type="cite"><div bgcolor="#FFFFFF"> FUNCTION 1 btint4cmp, <br /> FUNCTION 2 gin_extract_jsonb_path, <br /> FUNCTION 3 gin_extract_jsonb_query_path, <br /> FUNCTION 4 gin_consistent_jsonb_path,<br /> FUNCTION 6 gin_triconsistent_jsonb_path,<br />STORAGE integer;</div></blockquote><div> </div><div>А вот по этим функциям где-то можно почитать разъяснения?</div></blockquote><p>В официальной документации вроде бы все достаточно подробно описано:<br /><br /><a rel="noopener noreferrer" href="https://www.postgresql.org/docs/11/gin-extensibility.html">https://www.postgresql.org/docs/11...; (на английском)<br /><a rel="noopener noreferrer" href="https://postgrespro.ru/docs/postgresql/11/gin-extensibility">https://postgrespro.ru/docs/post...; (на русском)</p></div></blockquote><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">интересно - можно ли писать эти функции на SQL (plpgsql)?</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">если смотреть на функцию gin_triconsistent_jsonb, например, то</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">Тип данных результата | "char"<br />Типы данных аргументов | internal, smallint, jsonb, integer, internal, internal, internal</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">если посмотреть на неё со стороны документации, то</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml"><span><code>bool consistent(bool check[], StrategyNumber n, Datum query, int32 nkeys, Pointer extra_data[], bool *recheck, Datum queryKeys[], bool nullFlags[])</code></span></div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">я хочу (хотел, пока Ваш ответ не прочитал) написать скетч индекса на plpgsql. пусть он медленно работает в области сплита данных на индексируемые массивы итп, но если он заработает - появится смысл сесть это и на C написать.</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><blockquote xmlns="http://www.w3.org/1999/xhtml"; type="cite"><div bgcolor="#FFFFFF"><p> </p><blockquote type="cite" cite="mid:2084391554950401@myt2-cd7fa496c4f7.qloud-c.yandex.net"><div>и вот еще вопрос. Некоторые из этих функций принимают internal в виде аргументов, соответственно вызвать их и посмотреть их поведение прямо из SELECT - непонятно как.</div><div> </div><div>соответственно непонятно - как полностью с нуля написать свой OPERATOR CLASS не используя программирование на C (допустим хотим сделать скетч на SQL, возможно ли это сделать?)</div></blockquote><p><br />Да, все GIN-функции, за исключением первой compare(), можно написать сейчас только на C, и вызывать их из SQL нельзя. Но можно попробовать сделать один раз специальный обобщенный OPERATOR CLASS, в котором из функциий 2-6, написанных на C, будут вызываться другие функции с соответствующими номерами (например, 12-16), в которых уже будут использоваться только SQL-типы. Но полностью перенести всю функциональность C-функций на уровень SQL будет не так просто, потому что многие функции могут возвращать несколько значений сразу, а внутри Postgres, по-моему, нет такого удобного способа вызова для функций с OUT-параметрами, который есть для обычных функций. Например,<br /><br /> Datum *extractQuery(Datum query, int32 *nkeys, StrategyNumber n, bool **pmatch, Pointer **extra_data, bool **nullFlags, int32 *searchMode)</p></div></blockquote><div xmlns="http://www.w3.org/1999/xhtml">спасибо, помедитирую над этим всем.</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">я сишечную реализацию не смотрел вовсе, думал со стороны SQL до скетча добраться можно.</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><blockquote xmlns="http://www.w3.org/1999/xhtml"; type="cite"><div bgcolor="#FFFFFF"><p>возвращает массив извлеченных элементов, а также необязательные массив флагов pmatch, массив произвольных С-указателй extra_data, массив null-флагов nullFlags, и режим поиска searchMode. Если оставить только обязательный массив элементов, то сигнатрура SQL-функции extract_query будет совсем простой:<br /> <br /> extract_query (query anyelement, strategy int2) RETURNS storage_type[]</p><p>но я не уверен, что с anyelement не возникнет каких-либо проблем.<br /> </p><p>И еще хочу на всякий случай напомнить, что у нас есть еще расширение JsQuery (<a rel="noopener noreferrer" href="https://github.com/postgrespro/jsquery">https://github.com/postgrespro/jsquery</a><a href="https://github.com/postgrespro/jsquery), которое содержит опклассы, позволяющие выполнять по GIN-индексам более широкий ряд jsonb-запросов (например, range-запросов, которые реализованы с использования partialMatch). Возможно даже, что JsQuery решит Вашу задачу. Сейчас мы работает в JsQuery на поддержкой jsonpath, который выйдет в PostgreSQL12, а в будущем планируем даже перенести эти JsQuery-опклассы в ядро.">), которое содержит опклассы, позволяющие выполнять по GIN-индексам более широкий ряд jsonb-запросов (например, range-запросов, которые реализованы с использования partialMatch). Возможно даже, что JsQuery решит Вашу задачу. Сейчас мы работает в JsQuery на поддержкой jsonpath, который выйдет в PostgreSQL12, а в будущем планируем даже перенести эти JsQuery-опклассы в ядро.</a></p></div></blockquote><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">цитата оттуда:</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml"><blockquote><div><div><div><span>... compare(Datum a, Datum b)</code></span></div><div><p>Сравнивает два ключа (не индексированные объекты!) и возвращает целое меньше нуля, ноль или целое больше нуля, показывающее, что первый ключ меньше, равен или больше второго. Ключи NULL никогда не передаются этой функции.</p></div></div></div><p>Если же класс операторов не определяет метод <code>compare</code>, GIN попытается найти класс операторов B-дерева по умолчанию для типа данных ключа индекса и воспользоваться его функцией сравнения. Если класс операторов GIN предназначен только для одного типа данных, рекомендуется задавать функцию сравнения в этом классе операторов, так как поиск класса операторов B-дерева занимает несколько циклов. Однако для полиморфных классов операторов GIN (например, <code>array_ops</code>) задать одну функцию сравнения обычно не представляется возможным.</p></blockquote></div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">для полиморфных типов (например массивы) a и b - это ключи возвращённые <span><code>extractValue или это массивы ключей извлечённые из записей? (я еще не разобрался с API низкого уровня, сорри если </code></span>вопрос глупый: пытаюсь понять как индекс работает).</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">то есть extractValue вернул например:</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">1. для записи 1 - массив "a", "b", "c"</div><div xmlns="http://www.w3.org/1999/xhtml">2. для записи 2 - массив "c", "d", "e"</div><div xmlns="http://www.w3.org/1999/xhtml">3. для записи 3 - массив "x", "y", "z"</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">потом пользователь ищет</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">"ary"; @> [ "c" ]</div><div xmlns="http://www.w3.org/1999/xhtml"> </div><div xmlns="http://www.w3.org/1999/xhtml">compare что с чем сравнивает при этом? я хочу своей функцией compare иметь возможность поднять или опустить ввверх-низ списка записи в зависимости от своих критериев.</div>
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: OPERATOR CLASS
@ 2019-04-11 14:56 Nikita Glukhov <n.gluhov@postgrespro.ru>
parent: Dmitry E. Oboukhov <unera@debian.org>
0 siblings, 0 replies; 6+ messages in thread
From: Nikita Glukhov @ 2019-04-11 14:56 UTC (permalink / raw)
To: Dmitry E. Oboukhov <unera@debian.org>; +Cc: pgsql-ru-general@lists.postgresql.org <pgsql-ru-general@lists.postgresql.org>
On 11.04.2019 15:40, Dmitry E. Oboukhov wrote:
> 11.04.2019, 13:32, "Nikita Glukhov" <n.gluhov@postgrespro.ru>:
>>
>> On 11.04.2019 5:40, Dmitry E. Oboukhov wrote:
>>
>>> 11.04.2019, 01:58, "Nikita Glukhov" <n.gluhov@postgrespro.ru>
>>> <mailto:n.gluhov@postgrespro.ru>:
>>>> FUNCTION 1 btint4cmp,
>>>> FUNCTION 2 gin_extract_jsonb_path,
>>>> FUNCTION 3 gin_extract_jsonb_query_path,
>>>> FUNCTION 4 gin_consistent_jsonb_path,
>>>> FUNCTION 6 gin_triconsistent_jsonb_path,
>>>> STORAGE integer;
>>> А вот по этим функциям где-то можно почитать разъяснения?
>>
>> В официальной документации вроде бы все достаточно подробно описано:
>>
>> https://www.postgresql.org/docs/11/gin-extensibility.html (на английском)
>> https://postgrespro.ru/docs/postgresql/11/gin-extensibility (на русском)
>>
> интересно - можно ли писать эти функции на SQL (plpgsql)?
В plpgsql, конечно, тоже нельзя использовать internal типы, поэтому это
не получится.
> если смотреть на функцию gin_triconsistent_jsonb, например, то
> Тип данных результата | "char"
> Типы данных аргументов | internal, smallint, jsonb, integer, internal,
> internal, internal
> если посмотреть на неё со стороны документации, то
> |bool consistent(bool check[], StrategyNumber n, Datum query, int32
> nkeys, Pointer extra_data[], bool *recheck, Datum queryKeys[], bool
> nullFlags[])|
> я хочу (хотел, пока Ваш ответ не прочитал) написать скетч индекса на
> plpgsql. пусть он медленно работает в области сплита данных на
> индексируемые массивы итп, но если он заработает - появится смысл
> сесть это и на C написать.
Согласен, что для прототипирования опклассов возможность обходиться
только лишь SQL или PL/pgSQL была бы очень полезной.
>>> и вот еще вопрос. Некоторые из этих функций принимают internal в
>>> виде аргументов, соответственно вызвать их и посмотреть их поведение
>>> прямо из SELECT - непонятно как.
>>> соответственно непонятно - как полностью с нуля написать свой
>>> OPERATOR CLASS не используя программирование на C (допустим хотим
>>> сделать скетч на SQL, возможно ли это сделать?)
>>
>>
>> Да, все GIN-функции, за исключением первой compare(), можно написать
>> сейчас только на C, и вызывать их из SQL нельзя. Но можно попробовать
>> сделать один раз специальный обобщенный OPERATOR CLASS, в котором из
>> функциий 2-6, написанных на C, будут вызываться другие функции с
>> соответствующими номерами (например, 12-16), в которых уже будут
>> использоваться только SQL-типы. Но полностью перенести всю
>> функциональность C-функций на уровень SQL будет не так просто, потому
>> что многие функции могут возвращать несколько значений сразу, а
>> внутри Postgres, по-моему, нет такого удобного способа вызова для
>> функций с OUT-параметрами, который есть для обычных функций. Например,
>>
>> Datum *extractQuery(Datum query, int32 *nkeys, StrategyNumber n,
>> bool **pmatch, Pointer **extra_data, bool **nullFlags, int32 *searchMode)
>>
> спасибо, помедитирую над этим всем.
> я сишечную реализацию не смотрел вовсе, думал со стороны SQL до скетча
> добраться можно.
>>
>> возвращает массив извлеченных элементов, а также необязательные
>> массив флагов pmatch, массив произвольных С-указателй extra_data,
>> массив null-флагов nullFlags, и режим поиска searchMode. Если
>> оставить только обязательный массив элементов, то сигнатрура
>> SQL-функции extract_query будет совсем простой:
>>
>> extract_query (query anyelement, strategy int2) RETURNS storage_type[]
>>
>> но я не уверен, что с anyelement не возникнет каких-либо проблем.
>>
>> И еще хочу на всякий случай напомнить, что у нас есть еще расширение
>> JsQuery (https://github.com/postgrespro/jsquery), которое содержит
>> опклассы, позволяющие выполнять по GIN-индексам более широкий ряд
>> jsonb-запросов (например, range-запросов, которые реализованы с
>> использования partialMatch). Возможно даже, что JsQuery решит Вашу
>> задачу. Сейчас мы работает в JsQuery на поддержкой jsonpath, который
>> выйдет в PostgreSQL12, а в будущем планируем даже перенести эти
>> JsQuery-опклассы в ядро.
>>
> цитата оттуда:
>
> |int compare(Datum a, Datum b)|
>
> Сравнивает два ключа (не индексированные объекты!) и возвращает
> целое меньше нуля, ноль или целое больше нуля, показывающее, что
> первый ключ меньше, равен или больше второго. Ключи NULL никогда
> не передаются этой функции.
>
> Если же класс операторов не определяет метод |compare|, GIN
> попытается найти класс операторов B-дерева по умолчанию для типа
> данных ключа индекса и воспользоваться его функцией сравнения.
> Если класс операторов GIN предназначен только для одного типа
> данных, рекомендуется задавать функцию сравнения в этом классе
> операторов, так как поиск класса операторов B-дерева занимает
> несколько циклов. Однако для полиморфных классов операторов GIN
> (например, |array_ops|) задать одну функцию сравнения обычно не
> представляется возможным.
>
> для полиморфных типов (например массивы) a и b - это ключи
> возвращённые |extractValue или это массивы ключей извлечённые из
> записей? (я еще не разобрался с API низкого уровня, сорри если |вопрос
> глупый: пытаюсь понять как индекс работает).
> то есть extractValue вернул например:
> 1. для записи 1 - массив "a", "b", "c"
> 2. для записи 2 - массив "c", "d", "e"
> 3. для записи 3 - массив "x", "y", "z"
> потом пользователь ищет
> "ary" @> [ "c" ]
> compare что с чем сравнивает при этом?
a и b — это ключи (не массивы), извлеченнные extractValue() или
exrtactQuery(). compare() используется для поиска в B-дереве,
построенном на этих ключах.
Для приведенного выше примера дерево получится примерно таким:
d | *
/ \
a b c d e x y z
1 1 1,2 2 2 3 3 3
Т.е. в листьях хранятся указатели на записи, которые содержат данный
ключ. "c" содержится в двух записях, поэтому его список (он называется
"posting list" внутри GIN) содержит указатели на записи 1 и 2.
Немного более сложный запрос array @> [ "c", "e" ] будет выполняться
по этому индексу следующим образом:
1. extractQuery() извлекает ключи "c" и "e" из запроса.
2. GIN ищет эти ключи в B-дереве, и получает два списка указателей на
записи "1,2" и "1".
3. Далее, используя алгоритм слияния для этих списков, GIN вызывает
функцию [tri]consistent() ровно один раз для каждой из записей,
присутствующих хотя бы в одном из списков, передавая в
[tri]consistent() массив флагов, показывающих наличие данной записи
в списке записей каждого из ключей.
Таким образом, для записи 1 будет вызвана
consistent(check = [true, true]),
а для записи 2
consistent(check = [false, true])
4. consistent() в свою очередь интерпретирует этих флаги так, как ей нужно.
Для оператора @> (сontains) она вычислиет логическое И над этим
флагами и возвращент этот как результат, т.к. contains предполагает
наличие всех ключей в искомой записи.
Для оператора && (overlaps) наборот будет вычислено логическое ИЛИ,
т.к. тут достаточно наличия хотя бы одного из искомых ключей. Но на
самом деле здесь вычислять ничего не нужно, потому что один из check
флагов всегда будет true (правда, это касается только consistent(),
а в triconsistent() флаги могут иметь еще и GIN_MAYBE (NULL) значения).
5. Далее все записи, для которых [tri]consistent() вернула не false,
добавлются в результирующий битмап.
При этом, если consistent() установила флаг recheck или
trinconsistent() вернула GIN_MAYBE, запись будет еще раз
перепроверена (т.е. выполнен оператор @>), когда она будет вытащена
из таблицы. Это нужно для lossy-индексов (например, если в индексе
хранятся хеши) и lossy-запросов (например, оператор "=" потребует
проверки отутствия лишних элементов, а также соответствия порядка
элементов), которые нельзя выполнить по индексу точно.
> я хочу своей функцией compare иметь возможность поднять или опустить
> ввверх-низ списка записи в зависимости от своих критериев.
Не совсем понятно, что значит "поднять или опустить ввверх-вниз списка
записи". Тем более, что GIN выдает записи в физическом порядке из-за
использования BitmapIndexScan.
Если же на самом деле требуется отсутствующая сейчас возможность
выполнения ORDER BY по GIN (я про это думал недавно, кстати), то ее,
скорее всего, не так просто будет реализовать, но она выглядет довольно
полезной. Например, можно было бы выполнять по GIN запросы вида:
SELECT *
FROM tab
WHERE js @> '{"foo": "bar"}'
ORDER BY js -> 'baz';
--
Nikita Glukhov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company
^ permalink raw reply [nested|flat] 6+ messages in thread
end of thread, other threads:[~2019-04-11 14:56 UTC | newest]
Thread overview: 6+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2019-04-09 17:04 OPERATOR CLASS Dmitry E. Oboukhov <unera@debian.org>
2019-04-10 22:58 ` Nikita Glukhov <n.gluhov@postgrespro.ru>
2019-04-11 02:40 ` Dmitry E. Oboukhov <unera@debian.org>
2019-04-11 10:31 ` Nikita Glukhov <n.gluhov@postgrespro.ru>
2019-04-11 12:40 ` Dmitry E. Oboukhov <unera@debian.org>
2019-04-11 14:56 ` Nikita Glukhov <n.gluhov@postgrespro.ru>
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox