| ÐокÑменÑаÑÐ¸Ñ Ð¿Ð¾ PostgreSQL 9.4.1 | |||
|---|---|---|---|
| ÐÑед. | УÑÐ¾Ð²ÐµÐ½Ñ Ð²ÑÑе | ÐÑиложение E. ÐополниÑелÑно поÑÑавлÑемÑе модÑли | След. |
E.18. intarray
ÐодÑÐ»Ñ intarray пÑедоÑÑавлÑÐµÑ ÑÑд полезнÑÑ ÑÑнкÑий и опеÑаÑоÑов Ð´Ð»Ñ ÑабоÑÑ Ñ Ð¼Ð°ÑÑивами ÑелÑÑ ÑиÑел без NULL. Также он поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ Ð¿Ð¾Ð¸Ñк по индекÑÑ Ð´Ð»Ñ Ð½ÐµÐºÐ¾ÑоÑÑÑ Ð¸Ð· ÑÑÐ¸Ñ Ð¾Ð¿ÐµÑаÑоÑов.
ÐÑе ÑÑи опеÑаÑии вÑдаÑÑ Ð¾ÑибкÑ, еÑли в пеÑедаваемом маÑÑиве оказÑваÑÑÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ NULL.
Ðногие из ÑÑÐ¸Ñ Ð¾Ð¿ÐµÑаÑий имеÑÑ ÑмÑÑл ÑолÑко Ñ Ð¾Ð´Ð½Ð¾Ð¼ÐµÑнÑми маÑÑивами. ХоÑи им можно пеÑедаÑÑ Ð²Ñ Ð¾Ð´Ð½Ð¾Ð¹ маÑÑив и болÑÑей ÑазмеÑноÑÑи, знаÑÐµÐ½Ð¸Ñ Ð±ÑдÑÑ ÑÑиÑÑваÑÑÑÑ Ð¸Ð· него как из линейного маÑÑива в поÑÑдке Ñ ÑанениÑ.
E.18.1. ФÑнкÑии и опеÑаÑоÑÑ intarray
РеализованнÑе в модÑле intarray ÑÑнкÑии пеÑеÑиÑÐ»ÐµÐ½Ñ Ð² ТаблиÑе E-8, а опеÑаÑоÑÑ â в ТаблиÑе E-9.
ТаблиÑа E-8. ФÑнкÑии intarray
| ФÑнкÑÐ¸Ñ | Тип ÑезÑлÑÑаÑа | ÐпиÑание | ÐÑÐ¸Ð¼ÐµÑ | РезÑлÑÑÐ°Ñ |
|---|---|---|---|---|
icount(int[]) | int | ÑиÑло ÑлеменÑов в маÑÑиве | icount('{1,2,3}'::int[]) | 3 |
sort(int[], text dir) | int[] | ÑоÑÑиÑÑÐµÑ Ð¼Ð°ÑÑив — в dir должно задаваÑÑÑÑ asc (по возÑаÑÑаниÑ) или desc (по ÑбÑваниÑ) | sort('{1,2,3}'::int[], 'desc') | {3,2,1} |
sort(int[]) | int[] | ÑоÑÑиÑÑÐµÑ Ð² поÑÑдке возÑаÑÑÐ°Ð½Ð¸Ñ | sort(array[11,77,44]) | {11,44,77} |
sort_asc(int[]) | int[] | ÑоÑÑиÑÑÐµÑ Ð² поÑÑдке возÑаÑÑÐ°Ð½Ð¸Ñ | ||
sort_desc(int[]) | int[] | ÑоÑÑиÑÑÐµÑ Ð² поÑÑдке ÑбÑÐ²Ð°Ð½Ð¸Ñ | ||
uniq(int[]) | int[] | ÑдалÑÐµÑ Ð´ÑбликаÑÑ | uniq(sort('{1,2,3,2,1}'::int[])) | {1,2,3} |
idx(int[], int item) | int | Ð¸Ð½Ð´ÐµÐºÑ Ð¿ÐµÑвого ÑлеменÑа, Ñавного item (0, еÑли Ñакого неÑ) | idx(array[11,22,33,22,11], 22) | 2 |
subarray(int[], int start, int len) | int[] | ÑаÑÑÑ Ð¼Ð°ÑÑива, наÑинаÑÑаÑÑÑ Ñ Ð¿Ð¾Ð·Ð¸Ñии start и ÑоÑÑоÑÑÐ°Ñ Ð¸Ð· len ÑлеменÑов | subarray('{1,2,3,2,1}'::int[], 2, 3) | {2,3,2} |
subarray(int[], int start) | int[] | ÑаÑÑÑ Ð¼Ð°ÑÑива, наÑинаÑÑаÑÑÑ Ñ Ð¿Ð¾Ð·Ð¸Ñии start | subarray('{1,2,3,2,1}'::int[], 2) | {2,3,2,1} |
intset(int) | int[] | ÑоздаÑÑ Ð¼Ð°ÑÑив Ñ Ð¾Ð´Ð½Ð¸Ð¼ ÑлеменÑом | intset(42) | {42} |
ТаблиÑа E-9. ÐпеÑаÑоÑÑ intarray
| ÐпеÑаÑÐ¾Ñ | ÐозвÑаÑÐ°ÐµÑ | ÐпиÑание |
|---|---|---|
| int[] && int[] | boolean | пеÑеÑекаеÑÑÑ Ñ — true, еÑли маÑÑÐ¸Ð²Ñ Ð¸Ð¼ÐµÑÑ Ð¼Ð¸Ð½Ð¸Ð¼Ñм один обÑий ÑÐ»ÐµÐ¼ÐµÐ½Ñ |
| int[] @> int[] | boolean | вклÑÑÐ°ÐµÑ — true, еÑли левÑй маÑÑив ÑодеÑÐ¶Ð¸Ñ Ð¿ÑавÑй маÑÑив |
| int[] <@ int[] | boolean | вклÑÑаеÑÑÑ Ð² — true, еÑли левÑй маÑÑив ÑодеÑжиÑÑÑ Ð² пÑавом маÑÑиве |
| # int[] | int | ÑиÑло ÑлеменÑов в маÑÑиве |
| int[] # int | int | Ð¸Ð½Ð´ÐµÐºÑ ÑлеменÑа (Ð´ÐµÐ»Ð°ÐµÑ Ñо же, ÑÑо и ÑÑнкÑÐ¸Ñ idx) |
| int[] + int | int[] | вÑÑавлÑÐµÑ ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð² маÑÑив (добавлÑÐµÑ ÐµÐ³Ð¾ в ÐºÐ¾Ð½ÐµÑ Ð¼Ð°ÑÑива) |
| int[] + int[] | int[] | ÑоединÑÐµÑ Ð¼Ð°ÑÑÐ¸Ð²Ñ (пÑавÑй маÑÑив добавлÑеÑÑÑ Ð² ÐºÐ¾Ð½ÐµÑ Ð»ÐµÐ²Ð¾Ð³Ð¾) |
| int[] - int | int[] | ÑдалÑÐµÑ Ð¸Ð· маÑÑива запиÑи, ÑавнÑе пÑÐ°Ð²Ð¾Ð¼Ñ Ð°ÑгÑменÑÑ |
| int[] - int[] | int[] | ÑдалÑÐµÑ Ð¸Ð· левого маÑÑива ÑлеменÑÑ Ð¿Ñавого маÑÑива |
| int[] | int | int[] | обÑединение аÑгÑменÑов |
| int[] | int[] | int[] | обÑединение маÑÑивов |
| int[] & int[] | int[] | пеÑеÑеÑение маÑÑивов |
| int[] @@ query_int | boolean | true, еÑли маÑÑив ÑдовлеÑвоÑÑÐµÑ Ð·Ð°Ð¿ÑоÑÑ (Ñм. ниже) |
| query_int ~~ int[] | boolean | true, еÑли запÑоÑÑ ÑдовлеÑвоÑÑÐµÑ Ð¼Ð°ÑÑив (коммÑÑиÑÑÑÑий опеÑаÑÐ¾Ñ Ðº @@) |
(Ðо веÑÑии PostgreSQL 8.2 опеÑаÑоÑÑ Ð²ÐºÐ»ÑÑÐµÐ½Ð¸Ñ @> и <@ обознаÑалиÑÑ ÑооÑвеÑÑÑвенно как @ и ~. ÐÑи имена по-пÑÐµÐ¶Ð½ÐµÐ¼Ñ Ð´ÐµÐ¹ÑÑвÑÑÑ, но ÑÑиÑаÑÑÑÑ ÑÑÑаÑевÑими и в конÑе конÑов бÑдÑÑ ÑпÑаздненÑ. ÐамеÑÑÑе, ÑÑо ÑÑаÑÑе имена пÑоизоÑли из ÑоглаÑениÑ, коÑоÑÐ¾Ð¼Ñ ÑанÑÑе Ñледовали клÑÑевÑе геомеÑÑиÑеÑкие ÑÐ¸Ð¿Ñ Ð´Ð°Ð½Ð½ÑÑ !)
ÐпеÑаÑоÑÑ &&, @> и <@ ÑавнознаÑÐ½Ñ Ð²ÑÑÑоеннÑм опеÑаÑоÑам PostgreSQL Ñ Ñеми же именами, за иÑклÑÑением Ñого, ÑÑо они ÑабоÑаÑÑ ÑолÑко Ñ ÑелоÑиÑленнÑми маÑÑивами, не ÑодеÑжаÑими NULL, Ñогда как вÑÑÑоеннÑе опеÑаÑоÑÑ ÑабоÑаÑÑ Ñ Ð¼Ð°ÑÑивами лÑбÑÑ Ñипов. ÐлагодаÑÑ ÑÑÐ¾Ð¼Ñ Ð¾Ð³ÑаниÑениÑ, в болÑÑинÑÑве ÑлÑÑаев они ÑабоÑаÑÑ Ð±ÑÑÑÑее, Ñем вÑÑÑоеннÑе опеÑаÑоÑÑ.
ÐпеÑаÑоÑÑ @@ и ~~ пÑовеÑÑÑÑ, ÑдовлеÑвоÑÑÐµÑ Ð»Ð¸ маÑÑив запÑоÑÑ, пÑедÑÑавлÑÐµÐ¼Ð¾Ð¼Ñ Ð² виде знаÑÐµÐ½Ð¸Ñ ÑпеÑиализиÑованного Ñипа даннÑÑ query_int. ÐапÑÐ¾Ñ ÑодеÑÐ¶Ð¸Ñ ÑелоÑиÑленнÑе знаÑениÑ, ÑÑавниваемÑе Ñ ÑлеменÑами маÑÑива, возможно Ñ Ð¸ÑполÑзованием опеÑаÑоÑов & (AND), | (OR) и ! (NOT). ÐÑи Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ÑÑи могÑÑ Ð¸ÑполÑзоваÑÑÑÑ Ñкобки. ÐапÑимеÑ, запÑоÑÑ 1&(2|3) ÑдовлеÑвоÑÑÑÑ Ð·Ð°Ð¿ÑоÑÑ, коÑоÑÑе ÑодеÑÐ¶Ð°Ñ 1 и Ñакже ÑодеÑÐ¶Ð°Ñ 2 или 3.
E.18.2. ÐоддеÑжка индекÑов
ÐодÑÐ»Ñ intarray поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ Ð¸Ð½Ð´ÐµÐºÑÑ Ð´Ð»Ñ Ð¾Ð¿ÐµÑаÑоÑов &&, @>, <@ и @@, а Ñакже обÑÑнÑÑ Ð¿ÑовеÑÐºÑ ÑавенÑÑва маÑÑивов.
ÐодÑÐ»Ñ Ð¿ÑедоÑÑавлÑÐµÑ Ð´Ð²Ð° клаÑÑа опеÑаÑоÑов GiST: gist__int_ops (иÑполÑзÑеÑÑÑ Ð¿Ð¾ ÑмолÑаниÑ), Ð¿Ð¾Ð´Ñ Ð¾Ð´ÑÑий Ð´Ð»Ñ Ð¼Ð°Ð»ÐµÐ½ÑÐºÐ¸Ñ Ð¸ ÑÑÐµÐ´Ð½Ð¸Ñ Ð¿Ð¾ ÑазмеÑÑ Ð½Ð°Ð±Ð¾Ñов даннÑÑ , и gist__intbig_ops, пÑименÑÑÑий ÑигнаÑÑÑÑ Ð±Ð¾Ð»ÑÑего ÑазмеÑа и Ð¿Ð¾Ð´Ñ Ð¾Ð´ÑÑий Ð´Ð»Ñ Ð¸Ð½Ð´ÐµÐºÑаÑии болÑÑÐ¸Ñ Ð½Ð°Ð±Ð¾Ñов даннÑÑ (Ñо еÑÑÑ ÐºÐ¾Ð»Ð¾Ð½Ð¾Ðº, ÑодеÑжаÑÐ¸Ñ Ð¼Ð½Ð¾Ð³Ð¾ ÑазлиÑнÑÑ Ð·Ð½Ð°Ñений маÑÑива). Ð ÑÑой ÑеализаÑии иÑполÑзÑеÑÑÑ ÑÑÑÑкÑÑÑа даннÑÑ RD-деÑева Ñо вÑÑÑоеннÑм ÑжаÑием Ñ Ð¿Ð¾ÑеÑÑми.
ÐÑÑÑ Ñакже неÑÑандаÑÑнÑй клаÑÑ Ð¾Ð¿ÐµÑаÑоÑов GIN, gin__int_ops, поддеÑживаÑÑий Ñе же опеÑаÑоÑÑ.
ÐÑÐ±Ð¾Ñ Ð¼ÐµÐ¶Ð´Ñ Ð¸Ð½Ð´ÐµÐºÑами GiST и GIN завиÑÐ¸Ñ Ð¾Ñ Ð¾ÑноÑиÑелÑнÑÑ Ñ Ð°ÑакÑеÑиÑÑик пÑоизводиÑелÑноÑÑи GiST и GIN, коÑоÑÑе здеÑÑ Ð½Ðµ ÑаÑÑмаÑÑиваÑÑÑÑ. Ðак пÑавило, Ð¸Ð½Ð´ÐµÐºÑ GIN бÑÑÑÑее индекÑа GiST пÑи поиÑке, но ÑÑÑоиÑÑÑ Ð¸Ð»Ð¸ обновлÑеÑÑÑ Ð¾Ð½ медленнее; поÑÑÐ¾Ð¼Ñ GIN лÑÑÑе Ð¿Ð¾Ð´Ñ Ð¾Ð´Ð¸Ñ Ð´Ð»Ñ ÑÑаÑиÑеÑÐºÐ¸Ñ , а GiST Ð´Ð»Ñ ÑаÑÑо изменÑемÑÑ Ð´Ð°Ð½Ð½ÑÑ .
E.18.3. ÐÑимеÑ
-- ÑообÑение Ð¼Ð¾Ð¶ÐµÑ Ð¾ÑноÑиÑÑÑÑ Ðº одной или неÑколÑким "ÑекÑиÑм"
CREATE TABLE message (mid INT PRIMARY KEY, sections INT[], ...);
-- ÑоздаÑÑ ÑпеÑиализиÑованнÑй индекÑ
CREATE INDEX message_rdtree_idx ON message USING GIST (sections gist__int_ops);
-- вÑвеÑÑи ÑообÑÐµÐ½Ð¸Ñ Ð¸Ð· ÑекÑий 1 или 2 â опеÑаÑÐ¾Ñ Ð¿ÐµÑеÑеÑениÑ
SELECT message.mid FROM message WHERE message.sections && '{1,2}';
-- вÑвеÑÑи ÑообÑÐµÐ½Ð¸Ñ Ð¸Ð· ÑекÑий 1 и 2 â опеÑаÑÐ¾Ñ Ð²ÐºÐ»ÑÑениÑ
SELECT message.mid FROM message WHERE message.sections @> '{1,2}';
-- ÑÐ¾Ñ Ð¶Ðµ ÑезÑлÑÑаÑ, но Ñ Ð¾Ð¿ÐµÑаÑоÑом запÑоÑа
SELECT message.mid FROM message WHERE message.sections @@ '1&2'::query_int;E.18.4. ТеÑÑиÑование пÑоизводиÑелÑноÑÑи
РкаÑалоге иÑÑ Ð¾Ð´Ð½Ð¾Ð³Ð¾ кода contrib/intarray/bench ÑодеÑжиÑÑÑ Ð½Ð°Ð±Ð¾Ñ ÑеÑÑов пÑоизводиÑелÑноÑÑи. ЧÑÐ¾Ð±Ñ Ð·Ð°Ð¿ÑÑÑиÑÑ ÑÑи ÑеÑÑÑ, вÑполниÑе:
cd .../bench createdb TEST psql TEST < ../_int.sql ./create_test.pl | psql TEST ./bench.pl
СкÑÐ¸Ð¿Ñ bench.pl пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ Ð½ÐµÑколÑко аÑгÑменÑов, о коÑоÑÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ ÑзнаÑÑ, запÑÑÑив его без аÑгÑменÑов.
E.18.5. ÐвÑоÑÑ
РазÑабоÑÐºÑ Ð¾ÑÑÑеÑÑвили ФÑÐ´Ð¾Ñ Ð¡Ð¸Ð³Ð°ÐµÐ² (<[email protected]>) и Ðлег ÐаÑÑÑнов (<[email protected]>). ÐополниÑелÑнÑе ÑÐ²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð¶Ð½Ð¾ найÑи на ÑÑÑаниÑе http://www.sai.msu.su/~megera/postgres/gist/. ÐндÑей ÐкÑÑбÑÑÑкий пÑоделал оÑлиÑнÑÑ ÑабоÑÑ, добавив новÑе ÑÑнкÑии и опеÑаÑоÑÑ.