explain analyze
select * from products
where id in (
select product_id from products_attributes
where attribute_id = 1 AND value BETWEEN 1 AND 400
)
and id in (
select product_id from products_attributes
where attribute_id = 2 AND value BETWEEN 1 AND 400
)
and id in (
select product_id from products_attributes
where attribute_id = 3 AND value BETWEEN 20 AND 700
) limit 20;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=2.14..2479.76 rows=20 width=12) (actual time=1.597..4.402 rows=20 loops=1)
-> Nested Loop (cost=2.14..15835625.09 rows=127829 width=12) (actual time=1.595..4.396 rows=20 loops=1)
-> Nested Loop (cost=1.70..15109691.39 rows=114248 width=12) (actual time=1.373..4.023 rows=20 loops=1)
-> Nested Loop (cost=1.14..12802989.51 rows=340327 width=8) (actual time=1.142..3.550 rows=50 loops=1)
-> Index Scan using ix_attr_attribute_id on products_attributes products_attributes_1 (cost=0.57..188921.62 rows=1860415 width=4) (actual time=0.885..1.399 rows=289 loops=1)
Index Cond: (attribute_id = 2)
Filter: ((value >= '1'::double precision) AND (value <= '400'::double precision))
Rows Removed by Filter: 425
-> Index Scan using uk_attr_attr_product on products_attributes (cost=0.57..6.78 rows=1 width=4) (actual time=0.007..0.007 rows=0 loops=289)
Index Cond: ((product_id = products_attributes_1.product_id) AND (attribute_id = 1))
Filter: ((value >= '1'::double precision) AND (value <= '400'::double precision))
Rows Removed by Filter: 0
-> Index Scan using uk_attr_attr_product on products_attributes products_attributes_2 (cost=0.57..6.78 rows=1 width=4) (actual time=0.009..0.009 rows=0 loops=50)
Index Cond: ((product_id = products_attributes.product_id) AND (attribute_id = 3))
Filter: ((value >= '20'::double precision) AND (value <= '700'::double precision))
Rows Removed by Filter: 0
-> Index Scan using products_pkey on products (cost=0.43..6.35 rows=1 width=12) (actual time=0.018..0.018 rows=1 loops=20)
Index Cond: (id = products_attributes.product_id)
Planning Time: 14.654 ms
Execution Time: 4.459 ms
(20 rows)
$s = <<<EOD
{"numberKkt": "00107602708218", "code": 3, "ecashTotalSum": 287300, "kktRegId": "0004879715000853 ",
"requested_by_api_client": null, "totalSum": 287300, "machineNumber": "KZN045136", "sellerAddress": "ExchangeSupportMetazon@ozon.ru",
"messageFiscalSign": 9297266365794917084, "appliedTaxationType": 1, "prepaidSum": 0, "provisionSum": 0, "operationType": 1, "retailPlace": "ozon.ru",
"cashTotalSum": 0, "internetSign": 1, "fiscalSign": 2937630159,
"user": "\u041e\u0411\u0429\u0415\u0421\u0422\u0412\u041e \u0421 \u041e\u0413\u0420\u0410\u041d\u0418\u0427\u0415\u041d\u041d\u041e\u0419 \u041e\u0422\u0412\u0415\u0422\u0421\u0422\u0412\u0415\u041d\u041d\u041e\u0421\u0422\u042c\u042e \"\u0418\u041d\u0422\u0415\u0420\u041d\u0415\u0422 \u0420\u0415\u0428\u0415\u041d\u0418\u042f\"",
"fiscalDocumentFormatVer": 2, "buyerPhoneOrAddress": "l0vujkeofficial@mail.ru", "fiscalDriveNumber": "9289440300745441", "creditSum": 0,
"requested_at": "2021-04-02T14:29:36.784192Z",
"items": [{"name": "\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0430\u0432\u0430\u043d\u0441\u0430", "payMethod": 3,
"price": 287300, "paymentType": 3, "productType": 1, "nds": 3, "ndsSum": 47883, "sum": 287300, "unit": "\u0448\u0442", "quantity": 1}],
"region": "77", "fiscalDocumentNumber": 160517, "dateTime": "2021-04-02T13:34:00", "redefine_mask": 2, "nds18118": 47883,
"ofdId": "ofd7", "userInn": "7704217370", "requestNumber": 1793, "shiftNumber": 34}
EOD;
$a = json_decode($s, true);
echo $a['items'][0]['price'];
echo $json['items'][0]['price'];
main_thinghistory.history_date = date(main_thingownershiphistory.date_start)
main_thinghistory.history_date = main_thingownershiphistory.date_start
1. "PostgreSQL не просто реляционная, а объектно-реляционная СУБД" - маркетинг какой-то, честно говоря, не понимаю, что это значит, даже после пояснений. В PG есть условно объектные фишки (наследование таблиц, полиморфизм, те же композитные типы), но, на мой взгляд, часто это призраки из прошлого.
2. По-моему, это примерно то же, что и 1. Я бы оба этих пункта объеденил и назвал "расширяемость" или "гибкость".
ну, многое из этого есть и в других СУБД.
3. Такая небольшая фишка, ограниченного применения, особенно многомерные массивы. Уж если нужно работать с денормализованными данными, тот же json мощнее.
4. Это сейчас общая тенденция. До этого все внедряли xml, теперь json (да и в стандарте SQL все это появилось).
5. Вот это реальное преимущество, точнее несколько. Следование стандарту (тут как раз другие СУБД часто кто в лес, кто по дрова; иногда у них по историческим причинам своя реализация, иногда просто художник так видит).
ACID - конечно, тоже. Хотя это заметно в основном на фоне mysql, нормальные СУБД все же всегда уважали ACID.
Накидаю еще особенностей/преимуществ:
GIN/GIST позволяют индексировать вещи, которые по-другому вообще непонятно, как индексировать. Причем их часто несложно расширить на новые типы. Можно вообще создавать полностью свои виды индексов, хотя не то чтобы это работа для DBA/DBD.
Вы отмечали про множество типов и расширяемость, я бы просто выделил именно это, как минимум за PostGIS.
Вы это тоже упоминали вскользь. На самом деле редкая фишка, позволяет PG синтаксически очень упростить использование тех же новых типов XML/JSON и геометрии
Позволяет прозрачно работать с удаленными БД, файлами и другими источниками данных, включая многие другие СУБД
Немало интересных и полезных. Конечно, можно писать свои, имея соответствующие навыки.
Без какого-то рейтинга, просто (неполный) список того, что мне кажется важным и уникальным (или редким в мире СУБД)