αž€αžΆαžšαž‡αŸ†αž“αž½αžŸ EAV αž‡αžΆαž˜αž½αž™ JSONB αž“αŸ…αž€αŸ’αž“αž»αž„ PostgreSQL

TL; DR: JSONB αž’αžΆαž…αž‡αž½αž™αžŸαž˜αŸ’αžšαž½αž›αžŠαž›αŸ‹αž€αžΆαžšαž’αž—αž·αžœαžŒαŸ’αžαž“αŸαž‚αŸ’αžšαŸ„αž„αž€αžΆαžšαžŽαŸαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž”αžΆαž“αž™αŸ‰αžΆαž„αž„αžΆαž™αžŸαŸ’αžšαž½αž›αžŠαŸ„αž™αž˜αž·αž“αž…αžΆαŸ†αž”αžΆαž…αŸ‹αž›αŸ‡αž”αž„αŸ‹αž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαžŸαŸ†αžŽαž½αžšαŸ”

αžŸαŸαž…αž€αŸ’αžαžΈαžŽαŸ‚αž“αžΆαŸ†

αž…αžΌαžšαž•αŸ’αžαž›αŸ‹αž§αž‘αžΆαž αžšαžŽαŸαž”αž»αžšαžΆαžŽαž“αŸƒαž€αžšαžŽαžΈαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž…αžΆαžŸαŸ‹αž”αŸ†αž•αž»αžαž˜αž½αž™αž“αŸ…αž€αŸ’αž“αž»αž„αž–αž·αž—αž–αž“αŸƒαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž‘αŸ†αž“αžΆαž€αŸ‹αž‘αŸ†αž“αž„ (αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™): αž™αžΎαž„αž˜αžΆαž“αž’αž„αŸ’αž‚αž—αžΆαž–αž˜αž½αž™ αž αžΎαž™αž™αžΎαž„αžαŸ’αžšαžΌαžœαžšαž€αŸ’αžŸαžΆαž‘αž»αž€αž›αž€αŸ’αžαžŽαŸˆαžŸαž˜αŸ’αž”αžαŸ’αžαž·αž‡αžΆαž€αŸ‹αž›αžΆαž€αŸ‹ (αž‚αž»αžŽαž›αž€αŸ’αžαžŽαŸˆ) αž“αŸƒαž’αž„αŸ’αž‚αž—αžΆαž–αž“αŸαŸ‡αŸ” αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž˜αž·αž“αž˜αŸ‚αž“αž‚αŸ’αžšαž”αŸ‹αž€αžšαžŽαžΈαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž’αžΆαž…αž˜αžΆαž“αžŸαŸ†αžŽαž»αŸ†αž›αž€αŸ’αžαžŽαŸˆαžŸαž˜αŸ’αž”αžαŸ’αžαž·αžŠαžΌαž…αž‚αŸ’αž“αžΆαž“αŸ„αŸ‡αž‘αŸ αž αžΎαž™αž›αž€αŸ’αžαžŽαŸˆαžŸαž˜αŸ’αž”αžαŸ’αžαž·αž‡αžΆαž…αŸ’αžšαžΎαž“αž‘αŸ€αžαž’αžΆαž…αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž“αŸ’αžαŸ‚αž˜αž“αžΆαž–αŸαž›αž’αž“αžΆαž‚αžαŸ”

αž˜αž’αŸ’αž™αŸ„αž”αžΆαž™αž„αžΆαž™αžŸαŸ’αžšαž½αž›αž”αŸ†αž•αž»αžαžŠαžΎαž˜αŸ’αž”αžΈαžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž”αž‰αŸ’αž αžΆαž“αŸαŸ‡αž‚αžΊαžŠαžΎαž˜αŸ’αž”αžΈαž”αž„αŸ’αž€αžΎαžαž‡αž½αžšαžˆαžšαž€αŸ’αž“αž»αž„αžαžΆαžšαžΆαž„αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžαž˜αŸ’αž›αŸƒαž‘αŸ’αžšαž–αŸ’αž™αžŸαž˜αŸ’αž”αžαŸ’αžαž·αž“αžΈαž˜αž½αž™αŸ— αž αžΎαž™αž‚αŸ’αžšαžΆαž“αŸ‹αžαŸ‚αž”αŸ†αž–αŸαž‰αž“αžΌαžœαž’αŸ’αžœαžΈαžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž€αžΆαžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžœαžαŸ’αžαž»αž‡αžΆαž€αŸ‹αž›αžΆαž€αŸ‹αžŽαžΆαž˜αž½αž™αŸ” αž’αžŸαŸ’αž…αžΆαžšαŸ’αž™! αž”αž‰αŸ’αž αžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™... αžšαž αžΌαžαžŠαž›αŸ‹αžαžΆαžšαžΆαž„αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž˜αžΆαž“αž€αŸ†αžŽαžαŸ‹αžαŸ’αžšαžΆαžšαžΆαž”αŸ‹αž›αžΆαž“ αž αžΎαž™αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž”αž“αŸ’αžαŸ‚αž˜αž€αŸ†αžŽαžαŸ‹αžαŸ’αžšαžΆαžαŸ’αž˜αžΈαŸ”

αž–αž·αž…αžΆαžšαžŽαžΆαž‚αŸ†αžšαžΌ EAV (αž’αžΆαžαž»-αž‚αž»αžŽαž›αž€αŸ’αžαžŽαŸˆ-αžαž˜αŸ’αž›αŸƒ) αžœαžΆαž€αžΎαžαž‘αžΎαž„αž‡αžΆαž‰αžΉαž€αž‰αžΆαž”αŸ‹αŸ” αžαžΆαžšαžΆαž„αž˜αž½αž™αž˜αžΆαž“αž’αžΆαžαž» (αž€αŸ†αžŽαžαŸ‹αžαŸ’αžšαžΆ) αžαžΆαžšαžΆαž„αž˜αž½αž™αž‘αŸ€αžαž˜αžΆαž“αžˆαŸ’αž˜αŸ„αŸ‡αž‘αŸ’αžšαž–αŸ’αž™αžŸαž˜αŸ’αž”αžαŸ’αžαž· (αž‚αž»αžŽαž›αž€αŸ’αžαžŽαŸˆ) αž“αž·αž„αžαžΆαžšαžΆαž„αž‘αžΈαž”αžΈαž—αŸ’αž‡αžΆαž”αŸ‹αž’αžΆαžαž»αž‡αžΆαž˜αž½αž™αž‚αž»αžŽαž›αž€αŸ’αžαžŽαŸˆαžšαž”αžŸαŸ‹αž–αž½αž€αž‚αŸ αž“αž·αž„αž˜αžΆαž“αžαž˜αŸ’αž›αŸƒαž“αŸƒαž‚αž»αžŽαž›αž€αŸ’αžαžŽαŸˆαž‘αžΆαŸ†αž„αž“αŸ„αŸ‡αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž’αž„αŸ’αž‚αž—αžΆαž–αž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αŸ” αžœαžΆαž•αŸ’αžαž›αŸ‹αž±αŸ’αž™αž’αŸ’αž“αž€αž“αžΌαžœαžŸαž˜αžαŸ’αžαž—αžΆαž–αž€αŸ’αž“αž»αž„αž€αžΆαžšαž˜αžΆαž“αžŸαŸ†αžŽαž»αŸ†αž›αž€αŸ’αžαžŽαŸˆαžŸαž˜αŸ’αž”αžαŸ’αžαž·αž•αŸ’αžŸαŸαž„αŸ—αž‚αŸ’αž“αžΆαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžœαžαŸ’αžαž»αž•αŸ’αžŸαŸαž„αŸ—αž‚αŸ’αž“αžΆ αž αžΎαž™αžαŸ‚αž˜αž‘αžΆαŸ†αž„αž”αž“αŸ’αžαŸ‚αž˜αž›αž€αŸ’αžαžŽαŸˆαžŸαž˜αŸ’αž”αžαŸ’αžαž·αž—αŸ’αž›αžΆαž˜αŸ—αžŠαŸ„αž™αž˜αž·αž“αž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αŸ”

αž‘αŸ„αŸ‡αž‡αžΆαž™αŸ‰αžΆαž„αžŽαžΆαž€αŸαžŠαŸ„αž™ αžαŸ’αž‰αž»αŸ†αž“αžΉαž„αž˜αž·αž“αžŸαžšαžŸαŸαžšαž”αŸ’αžšαž€αžΆαžŸαž“αŸαŸ‡αž‘αŸ αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž˜αž·αž“αž˜αžΆαž“αž€αžΆαžšαž…αž»αŸ‡αž’αž“αŸ‹αžαž™αž˜αž½αž™αž…αŸ†αž“αž½αž“αž…αŸ†αž–αŸ„αŸ‡αžœαž·αž’αžΈαžŸαžΆαžŸαŸ’αžšαŸ’αž EVA αŸ” αžŠαžΌαž…αŸ’αž“αŸαŸ‡ αž‡αžΆαž§αž‘αžΆαž αžšαžŽαŸ αžŠαžΎαž˜αŸ’αž”αžΈαž‘αž‘αž½αž›αž”αžΆαž“αž’αžΆαžαž»αž˜αž½αž™ αž¬αž…αŸ’αžšαžΎαž“αžŠαŸ‚αž›αž˜αžΆαž“ 1 attribute αž“αžΈαž˜αž½αž™αŸ— 2 Joins αžαŸ’αžšαžΌαžœαž”αžΆαž“αž‘αžΆαž˜αž‘αžΆαžšαž“αŸ…αž€αŸ’αž“αž»αž„αžŸαŸ†αžŽαž½αžšαŸ– αž‘αžΈαž˜αž½αž™αž‚αžΊ Join with the attribute table αž‘αžΈαž–αžΈαžšαž‚αžΊ join with the values ​​tableαŸ” αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αž„αŸ’αž‚αž—αžΆαž–αž˜αž½αž™αž˜αžΆαž“αž‚αž»αžŽαž›αž€αŸ’αžαžŽαŸˆ 2 αž“αŸ„αŸ‡ 4 Joins αž‚αžΊαž…αžΆαŸ†αž”αžΆαž…αŸ‹! αž›αžΎαžŸαž–αžΈαž“αŸαŸ‡ αž‚αž»αžŽαž›αž€αŸ’αžαžŽαŸˆαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž‡αžΆαž’αž˜αŸ’αž˜αžαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αžšαž€αŸ’αžŸαžΆαž‘αž»αž€αž‡αžΆαžαŸ’αžŸαŸ‚αž’αž€αŸ’αžŸαžš αžŠαŸ‚αž›αž“αžΆαŸ†αž±αŸ’αž™αž€αžΆαžšαž”αž‰αŸ’αž‡αžΌαž“αž”αŸ’αžšαž—αŸαž‘αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž›αž‘αŸ’αž’αž•αž› αž“αž·αž„αžƒαŸ’αž›αžΆ WHERE αŸ” αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αžŸαžšαžŸαŸαžšαžŸαŸ†αžŽαž½αžšαž…αŸ’αžšαžΎαž“ αž“αŸ„αŸ‡αžœαžΆαž–αž·αžαž‡αžΆαžαŸ’αž‡αŸ‡αžαŸ’αž‡αžΆαž™αžŽαžΆαžŸαŸ‹ αž‘αžΆαž€αŸ‹αž‘αž„αž“αžΉαž„αž€αžΆαžšαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž’αž“αž’αžΆαž“αŸ”

αž‘αŸ„αŸ‡αž”αžΈαž‡αžΆαž˜αžΆαž“αž€αžΆαžšαžαŸ’αžœαŸ‡αžαžΆαžαž‡αžΆαž€αŸ‹αžŸαŸ’αžαŸ‚αž„αž‘αžΆαŸ†αž„αž“αŸαŸ‡αž€αŸαžŠαŸ„αž™ EAV αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž‡αžΆαž™αžΌαžšαž˜αž€αž αžΎαž™αžŠαžΎαž˜αŸ’αž”αžΈαžŠαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αž”αž‰αŸ’αž αžΆαž‘αžΆαŸ†αž„αž“αŸαŸ‡αŸ” αž‘αžΆαŸ†αž„αž“αŸαŸ‡αž‚αžΊαž‡αžΆαž…αŸ†αžŽαž»αž…αžαŸ’αžœαŸ‡αžαžΆαžαžŠαŸ‚αž›αž‡αŸ€αžŸαž˜αž·αž“αžšαž½αž… αž αžΎαž™αž˜αž·αž“αž˜αžΆαž“αž‡αž˜αŸ’αžšαžΎαžŸαž”αŸ’αžšαžŸαžΎαžšαž‡αžΆαž„αž“αŸαŸ‡αž‘αŸαŸ”
αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€ "αž”αž…αŸ’αž…αŸαž€αžœαž·αž‘αŸ’αž™αžΆ" αžαŸ’αž˜αžΈαž˜αž½αž™αž”αžΆαž“αž”αž„αŸ’αž αžΆαž‰αžαŸ’αž›αž½αž“αž“αŸ…αž€αŸ’αž“αž»αž„ PostgreSQL ...

αžŠαŸ„αž™αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž‡αžΆαž˜αž½αž™ PostgreSQL 9.4 αž”αŸ’αžšαž—αŸαž‘αž‘αž·αž“αŸ’αž“αž“αŸαž™ JSONB αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž“αŸ’αžαŸ‚αž˜αžŠαžΎαž˜αŸ’αž”αžΈαžšαž€αŸ’αžŸαžΆαž‘αž»αž€αž‘αž·αž“αŸ’αž“αž“αŸαž™αž‚αŸ„αž›αž–αžΈαžš JSON αŸ” αž‘αŸ„αŸ‡αž”αžΈαž‡αžΆαž€αžΆαžšαžšαž€αŸ’αžŸαžΆαž‘αž»αž€ JSON αž“αŸ…αž€αŸ’αž“αž»αž„αž‘αž˜αŸ’αžšαž„αŸ‹αž“αŸαŸ‡αž‡αžΆαž’αž˜αŸ’αž˜αžαžΆαžαŸ’αžšαžΌαžœαž€αžΆαžšαž‘αŸ†αž αŸ† αž“αž·αž„αž–αŸαž›αžœαŸαž›αžΆαž…αŸ’αžšαžΎαž“αž‡αžΆαž„αž”αž“αŸ’αžαž·αž… JSON αž’αžαŸ’αžαž”αž‘αž’αž˜αŸ’αž˜αžαžΆαž€αŸαžŠαŸ„αž™ αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžΆαžšαž›αžΎαžœαžΆαž‚αžΊαž›αžΏαž“αž‡αžΆαž„αŸ” JSONB αž€αŸαž‚αžΆαŸ†αž‘αŸ’αžšαž€αžΆαžšαž”αž„αŸ’αž€αžΎαžαž›αž·αž”αž·αž€αŸ’αžšαž˜αž•αž„αžŠαŸ‚αžš αžŠαŸ‚αž›αž’αŸ’αžœαžΎαž±αŸ’αž™αžŸαŸ†αžŽαž½αžšαž€αžΆαž“αŸ‹αžαŸ‚αž›αžΏαž“αŸ”

αž”αŸ’αžšαž—αŸαž‘αž‘αž·αž“αŸ’αž“αž“αŸαž™ JSONB αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αž™αžΎαž„αž‡αŸ†αž“αž½αžŸαž‚αŸ†αžšαžΌ EAV αžŠαŸαžŸαŸ’αž˜αž»αž‚αžŸαŸ’αž˜αžΆαž‰αžŠαŸ„αž™αž”αž“αŸ’αžαŸ‚αž˜αž‡αž½αžšαžˆαžš JSONB αž˜αž½αž™αž‘αŸ…αž€αŸ’αž“αž»αž„αžαžΆαžšαžΆαž„αž’αž„αŸ’αž‚αž—αžΆαž–αžšαž”αžŸαŸ‹αž™αžΎαž„ αžŠαŸ‚αž›αž’αŸ’αžœαžΎαž’αŸ„αž™αž€αžΆαžšαžšαž…αž“αžΆαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž˜αžΆαž“αž—αžΆαž–αžŸαžΆαž˜αž‰αŸ’αž‰αŸ” αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž˜αž“αž»αžŸαŸ’αžŸαž‡αžΆαž…αŸ’αžšαžΎαž“αž”αžΆαž“αž”αŸ’αžšαž€αŸ‚αž€αžαžΆ αž“αŸαŸ‡αž‚αž½αžšαžαŸ‚αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αž˜αžŠαŸ„αž™αž€αžΆαžšαžαž™αž…αž»αŸ‡αž“αŸƒαž•αž›αž·αžαž—αžΆαž–... αž“αŸ„αŸ‡αž αžΎαž™αž‡αžΆαž˜αžΌαž›αž αŸαžαž»αžŠαŸ‚αž›αžαŸ’αž‰αž»αŸ†αžŸαžšαžŸαŸαžšαž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡αŸ”

αž€αžΆαžšαžŠαŸ†αž‘αžΎαž„αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αžŸαžΆαž€αž›αŸ’αž”αž„

αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž”αŸ’αžšαŸ€αž”αž’αŸ€αž”αž“αŸαŸ‡ αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αž”αž„αŸ’αž€αžΎαžαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž“αŸ…αž›αžΎαž€αžΆαžšαžŠαŸ†αž‘αžΎαž„αžαŸ’αž˜αžΈαž“αŸƒ PostgreSQL 9.5 αž“αŸ…αž›αžΎ $80 build DigitalOcean Ubuntu 14.04. ПослС настройки Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² Π² postgresql.conf я запустил αž“αŸαŸ‡ αžŸαŸ’αž‚αŸ’αžšαžΈαž”αžŠαŸ„αž™αž”αŸ’αžšαžΎ psql αŸ” αžαžΆαžšαžΆαž„αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž„αŸ’αž€αžΎαžαž‘αžΎαž„αžŠαžΎαž˜αŸ’αž”αžΈαž”αž„αŸ’αž αžΆαž‰αž‘αž·αž“αŸ’αž“αž“αŸαž™αž€αŸ’αž“αž»αž„αž‘αž˜αŸ’αžšαž„αŸ‹ EAVαŸ–

CREATE TABLE entity ( 
  id           SERIAL PRIMARY KEY, 
  name         TEXT, 
  description  TEXT
);
CREATE TABLE entity_attribute (
  id          SERIAL PRIMARY KEY, 
  name        TEXT
);
CREATE TABLE entity_attribute_value (
  id                  SERIAL PRIMARY KEY, 
  entity_id           INT    REFERENCES entity(id), 
  entity_attribute_id INT    REFERENCES entity_attribute(id), 
  value               TEXT
);

αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αž“αŸαŸ‡αž‚αžΊαž‡αžΆαžαžΆαžšαžΆαž„αžŠαŸ‚αž›αž‘αž·αž“αŸ’αž“αž“αŸαž™αžŠαžΌαž…αž‚αŸ’αž“αžΆαž“αžΉαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αžšαž€αŸ’αžŸαžΆαž‘αž»αž€ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž‚αž»αžŽαž›αž€αŸ’αžαžŽαŸˆαž“αŸ…αž€αŸ’αž“αž»αž„αž‡αž½αžšαžˆαžšαž”αŸ’αžšαž—αŸαž‘ JSONB – αž›αž€αŸ’αžαžŽαŸˆαžŸαž˜αŸ’αž”αžαŸ’αžαž·.

CREATE TABLE entity_jsonb (
  id          SERIAL PRIMARY KEY, 
  name        TEXT, 
  description TEXT,
  properties  JSONB
);

αž˜αžΎαž›αž‘αŸ…αžŸαžΆαž˜αž‰αŸ’αž‰αž‡αžΆαž„αž“αŸαŸ‡αžŽαžΆαžŸαŸ‹αž˜αŸ‚αž“αž‘αŸ? αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αžœαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž“αŸ’αžαŸ‚αž˜αž‘αŸ…αžαžΆαžšαžΆαž„αž’αž„αŸ’αž‚αž—αžΆαž– (αž’αž„αŸ’αž‚αž—αžΆαž– & entity_jsonb) 10 αž›αžΆαž“αž€αŸ†αžŽαžαŸ‹αžαŸ’αžšαžΆ αž αžΎαž™αžαžΆαž˜αž“αŸ„αŸ‡ αžαžΆαžšαžΆαž„αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ†αž–αŸαž‰αžŠαŸ„αž™αž‘αž·αž“αŸ’αž“αž“αŸαž™αžŠαžΌαž…αž‚αŸ’αž“αžΆαžŠαŸ„αž™αž”αŸ’αžšαžΎαž›αŸ†αž“αžΆαŸ† EAV αž“αž·αž„αžœαž·αž’αžΈαžŸαžΆαžŸαŸ’αžšαŸ’αžαž‡αžΆαž˜αž½αž™αž‡αž½αžšαžˆαžš JSONB - entity_jsonb.properties. αžŠαžΌαž…αŸ’αž“αŸαŸ‡αž αžΎαž™ αž™αžΎαž„αž”αžΆαž“αž‘αž‘αž½αž›αž”αŸ’αžšαž—αŸαž‘αž‘αž·αž“αŸ’αž“αž“αŸαž™αž•αŸ’αžŸαŸαž„αŸ—αž‚αŸ’αž“αžΆαž‡αžΆαž…αŸ’αžšαžΎαž“αž€αŸ’αž“αž»αž„αž…αŸ†αžŽαŸ„αž˜αžŸαŸ†αžŽαž»αŸ†αž›αž€αŸ’αžαžŽαŸˆαžŸαž˜αŸ’αž”αžαŸ’αžαž·αž‘αžΆαŸ†αž„αž˜αžΌαž›αŸ” αž§αž‘αžΆαž αžšαžŽαŸαž‘αž·αž“αŸ’αž“αž“αŸαž™αŸ–

{
  id:          1
  name:        "Entity1"
  description: "Test entity no. 1"
  properties:  {
    color:        "red"
    lenght:       120
    width:        3.1882420
    hassomething: true
    country:      "Belgium"
  } 
}

αžŠαžΌαž…αŸ’αž“αŸαŸ‡αž₯αž‘αžΌαžœαž“αŸαŸ‡αž™αžΎαž„αž˜αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αžŠαžΌαž…αž‚αŸ’αž“αžΆαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž‡αž˜αŸ’αžšαžΎαžŸαž‘αžΆαŸ†αž„αž–αžΈαžšαŸ” αžαŸ„αŸ‡αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž”αŸ’αžšαŸ€αž”αž’αŸ€αž”αž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαž“αŸ…αž€αž“αŸ’αž›αŸ‚αž„αž’αŸ’αžœαžΎαž€αžΆαžš!

αžŸαž˜αŸ’αžšαž½αž›αž€αžΆαžšαžšαž…αž“αžΆαžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αŸ”

αžœαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž‰αŸ’αž‡αžΆαž€αŸ‹αž–αžΈαž˜αž»αž“αžαžΆαž€αžΆαžšαžšαž…αž“αžΆαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αŸ’αžœαžΎαž±αŸ’αž™αžŸαžΆαž˜αž‰αŸ’αž‰αž™αŸ‰αžΆαž„αžαŸ’αž›αžΆαŸ†αž„: αžαžΆαžšαžΆαž„αž˜αž½αž™αžŠαŸ„αž™αž”αŸ’αžšαžΎαž‡αž½αžšαžˆαžš JSONB αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž›αž€αŸ’αžαžŽαŸˆαžŸαž˜αŸ’αž”αžαŸ’αžαž·αž‡αŸ†αž“αž½αžŸαž±αŸ’αž™αž€αžΆαžšαž”αŸ’αžšαžΎαžαžΆαžšαžΆαž„αž”αžΈαžŸαž˜αŸ’αžšαžΆαž”αŸ‹ EAV αŸ” αž”αŸ‰αž»αž“αŸ’αžαŸ‚ αžαžΎβ€‹αž“αŸαŸ‡β€‹αžαŸ’αžšαžΌαžœβ€‹αž”αžΆαž“β€‹αž†αŸ’αž›αž»αŸ‡β€‹αž”αž‰αŸ’αž…αžΆαŸ†αž„β€‹αž™αŸ‰αžΆαž„β€‹αžŽαžΆβ€‹αž“αŸ…β€‹αž€αŸ’αž“αž»αž„β€‹αžŸαŸ†αžŽαžΎ? αž€αžΆαžšαž’αŸ’αžœαžΎαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž—αžΆαž–αž‘αŸ’αžšαž–αŸ’αž™αžŸαž˜αŸ’αž”αžαŸ’αžαž·αž’αž„αŸ’αž‚αž—αžΆαž–αž˜αž½αž™αž˜αžΎαž›αž‘αŸ…αžŠαžΌαž…αž“αŸαŸ‡αŸ–

-- EAV
UPDATE entity_attribute_value 
SET value = 'blue' 
WHERE entity_attribute_id = 1 
  AND entity_id = 120;

-- JSONB
UPDATE entity_jsonb 
SET properties = jsonb_set(properties, '{"color"}', '"blue"') 
WHERE id = 120;

αžŠαžΌαž…αžŠαŸ‚αž›αž’αŸ’αž“αž€αž’αžΆαž…αžƒαžΎαž‰αžŸαŸ†αžŽαžΎαž…αž»αž„αž€αŸ’αžšαŸ„αž™αž˜αž·αž“αž˜αžΎαž›αž‘αŸ…αžŸαžΆαž˜αž‰αŸ’αž‰αž‡αžΆαž„αž“αŸαŸ‡αž‘αŸαŸ” αžŠαžΎαž˜αŸ’αž”αžΈαž’αŸ’αžœαžΎαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž—αžΆαž–αžαž˜αŸ’αž›αŸƒαž“αŸƒαž‘αŸ’αžšαž–αŸ’αž™αž“αŸ…αž€αŸ’αž“αž»αž„αžœαžαŸ’αžαž» JSONB αž™αžΎαž„αžαŸ’αžšαžΌαžœαž”αŸ’αžšαžΎαž˜αž»αžαž„αžΆαžš jsonb_set()αž αžΎαž™αž‚αž½αžšαžαŸ‚αž αž»αž…αžαž˜αŸ’αž›αŸƒαžαŸ’αž˜αžΈαžšαž”αžŸαŸ‹αž™αžΎαž„αž‡αžΆαžœαžαŸ’αžαž» JSONB αŸ” αž‘αŸ„αŸ‡αž™αŸ‰αžΆαž„αžŽαžΆαž€αŸαžŠαŸ„αž™ αž™αžΎαž„αž˜αž·αž“αž…αžΆαŸ†αž”αžΆαž…αŸ‹αžŸαŸ’αž‚αžΆαž›αŸ‹αž’αžαŸ’αžαžŸαž‰αŸ’αž‰αžΆαžŽαžŽαžΆαž˜αž½αž™αž‡αžΆαž˜αž»αž“αž‘αŸαŸ” αž€αŸ’αžšαž‘αŸαž€αž˜αžΎαž›αž§αž‘αžΆαž αžšαžŽαŸ EAV αž™αžΎαž„αžαŸ’αžšαžΌαžœαžŠαžΉαž„αž‘αžΆαŸ†αž„ entity_id αž“αž·αž„ entity_attribute_id αžŠαžΎαž˜αŸ’αž”αžΈαž’αŸ’αžœαžΎαž€αžΆαžšαž’αžΆαž”αŸ‹αžŠαŸαžαŸ” αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž…αž„αŸ‹αž’αŸ’αžœαžΎαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž—αžΆαž–αž›αž€αŸ’αžαžŽαžŸαž˜αŸ’αž”αžαŸ’αžαž·αž“αŸ…αž€αŸ’αž“αž»αž„αž‡αž½αžšαžˆαžš JSONB αžŠαŸ„αž™αž•αŸ’αž’αŸ‚αž€αž›αžΎαžˆαŸ’αž˜αŸ„αŸ‡αžœαžαŸ’αžαž»αž“αŸ„αŸ‡ αžœαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αŸ’αžœαžΎαž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž“αŸ…αž€αŸ’αž“αž»αž„αž”αž“αŸ’αž‘αžΆαžαŸ‹αžŸαžΆαž˜αž‰αŸ’αž‰αž˜αž½αž™αŸ”

αž₯αž‘αžΌαžœαž“αŸαŸ‡ αž…αžΌαžšαž™αžΎαž„αž‡αŸ’αžšαžΎαžŸαžšαžΎαžŸαž’αžΆαžαž»αžŠαŸ‚αž›αž™αžΎαž„αž‘αžΎαž”αžαŸ‚αž’αŸ’αžœαžΎαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž—αžΆαž–αžŠαŸ„αž™αž•αŸ’αž’αŸ‚αž€αž›αžΎαž–αžŽαŸŒαžαŸ’αž˜αžΈαžšαž”αžŸαŸ‹αžœαžΆαŸ–

-- EAV
SELECT e.name 
FROM entity e 
  INNER JOIN entity_attribute_value eav ON e.id = eav.entity_id
  INNER JOIN entity_attribute ea ON eav.entity_attribute_id = ea.id
WHERE ea.name = 'color' AND eav.value = 'blue';

-- JSONB
SELECT name 
FROM entity_jsonb 
WHERE properties ->> 'color' = 'blue';

αžαŸ’αž‰αž»αŸ†β€‹αž‚αž·αžβ€‹αžαžΆβ€‹αž™αžΎαž„β€‹αž’αžΆαž…β€‹αž™αž›αŸ‹β€‹αžŸαŸ’αžšαž”β€‹αžαžΆβ€‹αž›αŸαžβ€‹αž‘αžΈβ€‹αž–αžΈαžšβ€‹αžαŸ’αž›αžΈβ€‹αž‡αžΆαž„ (αž‚αŸ’αž˜αžΆαž“β€‹αž€αžΆαžšβ€‹αž…αžΌαž›αžšαž½αž˜!) αžŠαžΌαž…αŸ’αž“αŸαŸ‡β€‹αž αžΎαž™β€‹αž’αžΆαž…β€‹αž’αžΆαž“β€‹αž”αžΆαž“β€‹αž…αŸ’αžšαžΎαž“β€‹αž‡αžΆαž„αŸ” JSONB αžˆαŸ’αž“αŸ‡αž“αŸ…αž‘αžΈαž“αŸαŸ‡! αž™αžΎαž„αž”αŸ’αžšαžΎαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžš JSON ->> αžŠαžΎαž˜αŸ’αž”αžΈαž‘αž‘αž½αž›αž”αžΆαž“αž–αžŽαŸŒαž‡αžΆαžαž˜αŸ’αž›αŸƒαž’αžαŸ’αžαž”αž‘αž–αžΈαžœαžαŸ’αžαž» JSONB αŸ” αžœαžΆαž€αŸαž˜αžΆαž“αžœαž·αž’αžΈαž‘αžΈαž–αžΈαžšαžŠαžΎαž˜αŸ’αž”αžΈαžŸαž˜αŸ’αžšαŸαž…αž”αžΆαž“αž›αž‘αŸ’αž’αž•αž›αžŠαžΌαž…αž‚αŸ’αž“αžΆαž“αŸ…αž€αŸ’αž“αž»αž„αž‚αŸ†αžšαžΌ JSONB αžŠαŸ„αž™αž”αŸ’αžšαžΎ @> operatorαŸ–

-- JSONB 
SELECT name 
FROM entity_jsonb 
WHERE properties @> '{"color": "blue"}';

αžœαžΆαž˜αžΆαž“αž—αžΆαž–αžŸαŸ’αž˜αž»αž‚αžŸαŸ’αž˜αžΆαž‰αž”αž“αŸ’αžαž·αž…αŸ– αž™αžΎαž„αž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž›αžαžΆαžαžΎαžœαžαŸ’αžαž» JSON αž“αŸ…αž€αŸ’αž“αž»αž„αž‡αž½αžšαžˆαžšαž›αž€αŸ’αžαžŽαžŸαž˜αŸ’αž”αžαŸ’αžαž·αžšαž”αžŸαŸ‹αžœαžΆαž˜αžΆαž“αžœαžαŸ’αžαž»αžŠαŸ‚αž›αž“αŸ…αžαžΆαž„αžŸαŸ’αžαžΆαŸ†αž“αŸƒαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžš @> αžŠαŸ‚αžšαž¬αž‘αŸαŸ” αž’αžΆαž“αžαž·αž… αž•αž›αž·αžαž—αžΆαž–αž…αŸ’αžšαžΎαž“ (αžŸαžΌαž˜αž˜αžΎαž›αžαžΆαž„αž€αŸ’αžšαŸ„αž˜)αŸ”

αž…αžΌαžšαž’αŸ’αžœαžΎαž±αŸ’αž™αž€αžΆαžšαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ JSONB αž€αžΆαž“αŸ‹αžαŸ‚αž„αžΆαž™αžŸαŸ’αžšαž½αž›αž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž€αžΆαžšαž‡αŸ’αžšαžΎαžŸαžšαžΎαžŸαž›αž€αŸ’αžαžŽαŸˆαžŸαž˜αŸ’αž”αžαŸ’αžαž·αž‡αžΆαž…αŸ’αžšαžΎαž“αž€αŸ’αž“αž»αž„αž–αŸαž›αžαŸ‚αž˜αž½αž™αŸ” αž“αŸαŸ‡αž‚αžΊαž‡αžΆαž€αž“αŸ’αž›αŸ‚αž„αžŠαŸ‚αž›αžœαž·αž’αžΈαžŸαžΆαžŸαŸ’αžšαŸ’αž JSONB αž–αž·αžαž‡αžΆαž…αžΌαž›αž˜αž€αŸ– αž™αžΎαž„αž‚αŸ’αžšαžΆαž“αŸ‹αžαŸ‚αž‡αŸ’αžšαžΎαžŸαžšαžΎαžŸαž›αž€αŸ’αžαžŽαŸˆαžŸαž˜αŸ’αž”αžαŸ’αžαž·αž‡αžΆαž‡αž½αžšαžˆαžšαž”αž“αŸ’αžαŸ‚αž˜αž“αŸ…αž€αŸ’αž“αž»αž„αžŸαŸ†αžŽαž»αŸ†αž›αž‘αŸ’αž’αž•αž›αžšαž”αžŸαŸ‹αž™αžΎαž„αžŠαŸ„αž™αž˜αž·αž“αž…αžΆαŸ†αž”αžΆαž…αŸ‹αž˜αžΆαž“αž€αžΆαžšαž…αžΌαž›αžšαž½αž˜αŸ–

-- JSONB 
SELECT name
  , properties ->> 'color'
  , properties ->> 'country'
FROM entity_jsonb 
WHERE id = 120;

αž‡αžΆαž˜αž½αž™αž“αžΉαž„ EAV αž’αŸ’αž“αž€αž“αžΉαž„αžαŸ’αžšαžΌαžœαž€αžΆαžš 2 αž…αžΌαž›αžšαž½αž˜αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž‘αŸ’αžšαž–αŸ’αž™αžŸαž˜αŸ’αž”αžαŸ’αžαž·αž“αžΈαž˜αž½αž™αŸ—αžŠαŸ‚αž›αž’αŸ’αž“αž€αž…αž„αŸ‹αžŸαž½αžšαŸ” αžαžΆαž˜αž‚αŸ†αž“αž·αžαžšαž”αžŸαŸ‹αžαŸ’αž‰αž»αŸ† αžŸαŸ†αžŽαž½αžšαžαžΆαž„αž›αžΎαž”αž„αŸ’αž αžΆαž‰αž–αžΈαž—αžΆαž–αžŸαžΆαž˜αž‰αŸ’αž‰αžŠαŸαž’αžŸαŸ’αž…αžΆαžšαŸ’αž™αž€αŸ’αž“αž»αž„αž€αžΆαžšαžšαž…αž“αžΆαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αŸ” αžŸαžΌαž˜αž˜αžΎαž›αž§αž‘αžΆαž αžšαžŽαŸαž”αž“αŸ’αžαŸ‚αž˜αž’αŸ†αž–αžΈαžšαž”αŸ€αž”αžŸαžšαžŸαŸαžšαžŸαŸ†αžŽαž½αžš JSONB αž•αž„αžŠαŸ‚αžšαŸ” αž“αŸαŸ‡ αž”αŸ’αžšαž€αžΆαžŸαŸ”
αž₯αž‘αžΌαžœαž“αŸαŸ‡αžœαžΆαžŠαž›αŸ‹αž–αŸαž›αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž“αž·αž™αžΆαž™αž’αŸ†αž–αžΈαž€αžΆαžšαžŸαž˜αŸ’αžαŸ‚αž„αŸ”

αž•αž›αž·αžαž—αžΆαž–

αžŠαžΎαž˜αŸ’αž”αžΈαž”αŸ’αžšαŸ€αž”αž’αŸ€αž”αž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαžŠαŸ‚αž›αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αž”αŸ’αžšαžΎ αž–αž“αŸ’αž™αž›αŸ‹αž€αžΆαžšαžœαž·αž—αžΆαž‚ αž“αŸ…αž€αŸ’αž“αž»αž„αžŸαŸ†αžŽαž½αžš αžŠαžΎαž˜αŸ’αž”αžΈαž‚αžŽαž“αžΆαž–αŸαž›αžœαŸαž›αžΆαž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αŸ” αžŸαŸ†αžŽαž½αžšαž“αžΈαž˜αž½αž™αŸ—αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž™αŸ‰αžΆαž„αž αŸ„αž…αžŽαžΆαžŸαŸ‹αž”αžΈαžŠαž„ αžŠαŸ„αž™αžŸαžΆαžšαž’αŸ’αž“αž€αžšαŸ€αž”αž…αŸ†αž•αŸ‚αž“αž€αžΆαžšαžŸαŸ†αžŽαž½αžšαž…αŸ†αžŽαžΆαž™αž–αŸαž›αž™αžΌαžšαž‡αžΆαž„αž›αžΎαž€αžŠαŸ†αž”αžΌαž„αŸ” αžŠαŸ†αž”αžΌαž„αžαŸ’αž‰αž»αŸ†αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŸαŸ†αžŽαž½αžšαžŠαŸ„αž™αž‚αŸ’αž˜αžΆαž“αž›αž·αž”αž·αž€αŸ’αžšαž˜αžŽαžΆαž˜αž½αž™ αž‡αžΆαž€αŸ‹αžŸαŸ’αžαŸ‚αž„ αž“αŸαŸ‡αž‚αžΊαž‡αžΆαž’αžαŸ’αžαž”αŸ’αžšαž™αŸ„αž‡αž“αŸαž˜αž½αž™αžšαž”αžŸαŸ‹ JSONB αž…αžΆαž”αŸ‹αžαžΆαŸ†αž„αž–αžΈαž€αžΆαžšαž—αŸ’αž‡αžΆαž”αŸ‹αžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž€αžΆαžšαžŸαž˜αŸ’αžšαžΆαž”αŸ‹ EAV αž˜αž·αž“αž’αžΆαž…αž”αŸ’αžšαžΎαž›αž·αž”αž·αž€αŸ’αžšαž˜αž”αžΆαž“αž‘αŸ (αžœαžΆαž›αž‚αž“αŸ’αž›αžΉαŸ‡αž”αžšαž‘αŸαžŸαž˜αž·αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αŸ’αžœαžΎαž›αž·αž”αž·αž€αŸ’αžšαž˜αž‘αŸ)αŸ” αž”αž“αŸ’αž‘αžΆαž”αŸ‹β€‹αž–αžΈβ€‹αž“αŸαŸ‡ αžαŸ’αž‰αž»αŸ†β€‹αž”αžΆαž“β€‹αž”αž„αŸ’αž€αžΎαžβ€‹αž›αž·αž”αž·αž€αŸ’αžšαž˜β€‹αž˜αž½αž™β€‹αž“αŸ…β€‹αž›αžΎβ€‹αž‡αž½αžšβ€‹αžˆαžšβ€‹αž‚αž“αŸ’αž›αžΉαŸ‡β€‹αž”αžšαž‘αŸαžŸ 2 αž“αŸƒβ€‹αžαžΆαžšαžΆαž„β€‹αžαž˜αŸ’αž›αŸƒ EAV αž–αŸ’αžšαž˜β€‹αž‘αžΆαŸ†αž„β€‹αžŸαž“αŸ’αž‘αžŸαŸ’αžŸαž“αŸ αž‡αžΈαž“αŸ” αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž‡αž½αžšαžˆαžš JSONB αŸ”

αž€αžΆαžšαž’αŸ’αžœαžΎαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž—αžΆαž–αž‘αž·αž“αŸ’αž“αž“αŸαž™αž”αžΆαž“αž”αž„αŸ’αž αžΆαž‰αž–αžΈαž›αž‘αŸ’αž’αž•αž›αžŠαžΌαž…αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αž€αŸ’αž“αž»αž„αž›αž€αŸ’αžαžαžŽαŸ’αžŒαž“αŸƒαž–αŸαž›αžœαŸαž›αžΆ (αž‚αž·αžαž‡αžΆ ms)αŸ” αž…αŸ†αžŽαžΆαŸ†αžαžΆαž˜αžΆαžαŸ’αžšαžŠαŸ’αž‹αžΆαž“αž‚αžΊαž›αŸ„αž€αžΆαžšαžΈαžαŸ–

αž€αžΆαžšαž‡αŸ†αž“αž½αžŸ EAV αž‡αžΆαž˜αž½αž™ JSONB αž“αŸ…αž€αŸ’αž“αž»αž„ PostgreSQL

αž™αžΎαž„αžƒαžΎαž‰αžαžΆ JSONB αž˜αžΆαž“αž…αŸ’αžšαžΎαž“ (> 50000-x) αž›αžΏαž“αž‡αžΆαž„ EAV αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž˜αž·αž“αž”αŸ’αžšαžΎαž›αž·αž”αž·αž€αŸ’αžšαž˜αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž αŸαžαž»αž•αž›αžŠαŸ‚αž›αž”αžΆαž“αžšαŸ€αž”αžšαžΆαž”αŸ‹αžαžΆαž„αž›αžΎαŸ” αž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αž™αžΎαž„αž’αŸ’αžœαžΎαž›αž·αž”αž·αž€αŸ’αžšαž˜αž‡αž½αžšαžˆαžšαž‡αžΆαž˜αž½αž™αžŸαŸ„αž…αž˜αŸ’αž”αž„ αž—αžΆαž–αžαž»αžŸαž‚αŸ’αž“αžΆαžŸαŸ’αž‘αžΎαžšαžαŸ‚αž”αžΆαžαŸ‹αž‘αŸ…αž αžΎαž™ αž”αŸ‰αž»αž“αŸ’αžαŸ‚ JSONB αž“αŸ…αžαŸ‚αž›αžΏαž“αž‡αžΆαž„ EAV 1,3 αžŠαž„αŸ” αž…αŸ†αžŽαžΆαŸ†αžαžΆαž›αž·αž”αž·αž€αŸ’αžšαž˜αž“αŸ…αž›αžΎαž‡αž½αžšαžˆαžš JSONB αž˜αž·αž“αž˜αžΆαž“αž₯αž‘αŸ’αž’αž·αž–αž›αž“αŸ…αž‘αžΈαž“αŸαŸ‡αž‘αŸ αžŠαŸ„αž™αžŸαžΆαžšαž™αžΎαž„αž˜αž·αž“αž”αŸ’αžšαžΎαž‡αž½αžšαžˆαžšαž›αž€αŸ’αžαžŽαžŸαž˜αŸ’αž”αžαŸ’αžαž·αž€αŸ’αž“αž»αž„αž›αž€αŸ’αžαžŽαŸˆαžœαž·αž“αž·αž…αŸ’αž†αŸαž™αžœαžΆαž™αžαž˜αŸ’αž›αŸƒαŸ”

αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαž‡αŸ’αžšαžΎαžŸαžšαžΎαžŸαž‘αž·αž“αŸ’αž“αž“αŸαž™αžŠαŸ„αž™αž•αŸ’αž’αŸ‚αž€αž›αžΎαžαž˜αŸ’αž›αŸƒαž’αž…αž›αž“αž‘αŸ’αžšαž–αŸ’αž™ αž™αžΎαž„αž‘αž‘αž½αž›αž”αžΆαž“αž›αž‘αŸ’αž’αž•αž›αžŠαžΌαž…αžαžΆαž„αž€αŸ’αžšαŸ„αž˜ (αžαŸ’αž“αžΆαžαž’αž˜αŸ’αž˜αžαžΆ)αŸ–

αž€αžΆαžšαž‡αŸ†αž“αž½αžŸ EAV αž‡αžΆαž˜αž½αž™ JSONB αž“αŸ…αž€αŸ’αž“αž»αž„ PostgreSQL

αž’αŸ’αž“αž€αž’αžΆαž…αž€αžαŸ‹αžŸαŸ†αž‚αžΆαž›αŸ‹αžαžΆ JSONB αž˜αŸ’αžαž„αž‘αŸ€αžαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž›αžΏαž“αž‡αžΆαž„ EAV αžŠαŸ„αž™αž‚αŸ’αž˜αžΆαž“αž›αž·αž”αž·αž€αŸ’αžšαž˜ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž“αŸ…αž–αŸαž›αžŠαŸ‚αž› EAV αž‡αžΆαž˜αž½αž™αž›αž·αž”αž·αž€αŸ’αžšαž˜ αžœαžΆαž“αŸ…αžαŸ‚αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž›αžΏαž“αž‡αžΆαž„ JSONB αŸ” αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αžƒαžΎαž‰αžαžΆαž–αŸαž›αžœαŸαž›αžΆαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžŸαŸ†αžŽαž½αžš JSONB αž‚αžΊαžŠαžΌαž…αž‚αŸ’αž“αžΆ αž“αŸαŸ‡αž”αžΆαž“αž‡αŸ†αžšαž»αž‰αž±αŸ’αž™αžαŸ’αž‰αž»αŸ†αžŠαžΉαž„αžαžΆαžŸαž“αŸ’αž‘αžŸαŸ’αžŸαž“αŸ GIN αž˜αž·αž“αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαŸ” αž‡αžΆαž€αŸ‹αžŸαŸ’αžαŸ‚αž„αž“αŸ…αž–αŸαž›αžŠαŸ‚αž›αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαžŸαž“αŸ’αž‘αžŸαŸ’αžŸαž“αŸ GIN αž“αŸ…αž›αžΎαž‡αž½αžšαžˆαžšαžŠαŸ‚αž›αž˜αžΆαž“αž›αž€αŸ’αžαžŽαŸˆαžŸαž˜αŸ’αž”αžαŸ’αžαž·αžŠαŸ‚αž›αž”αžΆαž“αž”αž‰αŸ’αž…αžΌαž› αžœαžΆαž˜αžΆαž“αž”αŸ’αžšαžŸαž·αž‘αŸ’αž’αž—αžΆαž–αžαŸ‚αž“αŸ…αž–αŸαž›αž”αŸ’αžšαžΎαžšαž½αž˜αž”αž‰αŸ’αž…αžΌαž›αž”αŸ’αžšαžαž·αž”αžαŸ’αžαž·αž€αžš @> αž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡αŸ” αžαŸ’αž‰αž»αŸ†αž”αžΆαž“αž”αŸ’αžšαžΎαžœαžΆαž“αŸ…αž€αŸ’αž“αž»αž„αž€αžΆαžšαž’αŸ’αžœαžΎαžαŸαžŸαŸ’αžαžαŸ’αž˜αžΈαž αžΎαž™αžœαžΆαž˜αžΆαž“αž₯αž‘αŸ’αž’αž·αž–αž›αž™αŸ‰αžΆαž„αžαŸ’αž›αžΆαŸ†αž„αž‘αŸ…αž›αžΎαž–αŸαž›αžœαŸαž›αžΆαŸ– αžαŸ’αžšαžΉαž˜αžαŸ‚ 0,153ms αž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡! αž“αŸαŸ‡αž‚αžΊαž›αžΏαž“αž‡αžΆαž„ EAV 15000 αžŠαž„ αž“αž·αž„αž›αžΏαž“αž‡αžΆαž„ 25000 αžŠαž„αž‡αžΆαž„ ->> operatorαŸ”

αžαŸ’αž‰αž»αŸ†αž‚αž·αžαžαžΆαžœαžΆαž›αžΏαž“αž›αŸ’αž˜αž˜!

αž‘αŸ†αž αŸ†αžαžΆαžšαžΆαž„αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™

αž…αžΌαžšαž™αžΎαž„αž”αŸ’αžšαŸ€αž”αž’αŸ€αž”αž‘αŸ†αž αŸ†αžαžΆαžšαžΆαž„αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžœαž·αž’αžΈαžŸαžΆαžŸαŸ’αžšαŸ’αžαž‘αžΆαŸ†αž„αž–αžΈαžšαŸ” αž“αŸ…αž€αŸ’αž“αž»αž„ psql αž™αžΎαž„αž’αžΆαž…αž”αž„αŸ’αž αžΆαž‰αž‘αŸ†αž αŸ†αž“αŸƒαžαžΆαžšαžΆαž„ αž“αž·αž„αž›αž·αž”αž·αž€αŸ’αžšαž˜αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αžŠαŸ„αž™αž”αŸ’αžšαžΎαž–αžΆαž€αŸ’αž™αž”αž‰αŸ’αž‡αžΆ dti+

αž€αžΆαžšαž‡αŸ†αž“αž½αžŸ EAV αž‡αžΆαž˜αž½αž™ JSONB αž“αŸ…αž€αŸ’αž“αž»αž„ PostgreSQL

αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžœαž·αž’αžΈαžŸαžΆαžŸαŸ’αžšαŸ’αž EAV αž‘αŸ†αž αŸ†αžαžΆαžšαžΆαž„αž‚αžΊαž”αŸ’αžšαž αŸ‚αž› 3068 MB αž“αž·αž„αž›αž·αž”αž·αž€αŸ’αžšαž˜αžšαž αžΌαžαžŠαž›αŸ‹ 3427 MB αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž‘αŸ†αž αŸ†αžŸαžšαž»αž” 6,43 GBαŸ” αžœαž·αž’αžΈαžŸαžΆαžŸαŸ’αžšαŸ’αž JSONB αž”αŸ’αžšαžΎ 1817 MB αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžαžΆαžšαžΆαž„ αž“αž·αž„ 318 MB αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž›αž·αž”αž·αž€αŸ’αžšαž˜ αžŠαŸ‚αž›αž˜αžΆαž“αž‘αŸ†αž αŸ† 2,08 GBαŸ” αžœαžΆαž”αŸ’αžšαŸ‚αž‡αžΆαžαž·αž…αž‡αžΆαž„ 3 αžŠαž„! αž€αžΆαžšαž–αž·αžαž“αŸαŸ‡αž”αžΆαž“αž’αŸ’αžœαžΎαž±αŸ’αž™αžαŸ’αž‰αž»αŸ†αž—αŸ’αž‰αžΆαž€αŸ‹αž•αŸ’αž’αžΎαž›αž”αž“αŸ’αžαž·αž…αž–αŸ’αžšαŸ„αŸ‡αž™αžΎαž„αžšαž€αŸ’αžŸαžΆαž‘αž»αž€αžˆαŸ’αž˜αŸ„αŸ‡αž’αž…αž›αž“αž‘αŸ’αžšαž–αŸ’αž™αž“αŸ…αž€αŸ’αž“αž»αž„αž‚αŸ’αžšαž”αŸ‹αžœαžαŸ’αžαž» JSONB αŸ”

αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž“αŸ…αžαŸ‚αž›αŸαžαž“αž·αž™αžΆαž™αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžαŸ’αž›αž½αž“αž‚αŸαŸ– αž“αŸ…αž€αŸ’αž“αž»αž„ EAV αž™αžΎαž„αžšαž€αŸ’αžŸαžΆαž‘αž»αž€ 2 integer Foreign keys αž€αŸ’αž“αž»αž„αž˜αž½αž™αžαž˜αŸ’αž›αŸƒ attribute αžŠαŸ‚αž›αž”αžŽαŸ’αžαžΆαž›αž±αŸ’αž™αž˜αžΆαž“ 8 bytes αž“αŸƒαž‘αž·αž“αŸ’αž“αž“αŸαž™αž”αž“αŸ’αžαŸ‚αž˜αŸ” αž›αžΎαžŸαž–αžΈαž“αŸαŸ‡αž‘αŸ€αž EAV αžšαž€αŸ’αžŸαžΆαž‘αž»αž€αžαž˜αŸ’αž›αŸƒαž‘αŸ’αžšαž–αŸ’αž™αžŸαž˜αŸ’αž”αžαŸ’αžαž·αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αž‡αžΆαž’αžαŸ’αžαž”αž‘ αžαžŽαŸˆαž–αŸαž›αžŠαŸ‚αž› JSONB αž“αžΉαž„αž”αŸ’αžšαžΎαž›αŸαž αž“αž·αž„αžαž˜αŸ’αž›αŸƒαž”αŸŠαžΌαž›αžΈαž“αž“αŸ…αžαžΆαž„αž€αŸ’αž“αž»αž„αžαžΆαž˜αžŠαŸ‚αž›αž’αžΆαž…αž’αŸ’αžœαžΎαž‘αŸ…αž”αžΆαž“ αžŠαŸ‚αž›αž”αžŽαŸ’αžαžΆαž›αž±αŸ’αž™αž˜αžΆαž“αžŸαŸ’αž“αžΆαž˜αž‡αžΎαž„αžαžΌαž…αž‡αžΆαž„αŸ”

αž›αž‘αŸ’αž’αž•αž›

αžŸαžšαž»αž”αž˜αž€ αžαŸ’αž‰αž»αŸ†αž‚αž·αžαžαžΆαž€αžΆαžšαžšαž€αŸ’αžŸαžΆαž‘αž»αž€αž›αž€αŸ’αžαžŽαŸˆαžŸαž˜αŸ’αž”αžαŸ’αžαž·αž’αž„αŸ’αž‚αž—αžΆαž–αž€αŸ’αž“αž»αž„αž‘αž˜αŸ’αžšαž„αŸ‹ JSONB αž’αžΆαž…αž’αŸ’αžœαžΎαž±αŸ’αž™αž€αžΆαžšαžšαž…αž“αžΆ αž“αž·αž„αž€αžΆαžšαžαŸ‚αžšαž€αŸ’αžŸαžΆαž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αž€αžΆαž“αŸ‹αžαŸ‚αž„αžΆαž™αžŸαŸ’αžšαž½αž›αŸ” αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž€αŸ†αž–αž»αž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžŸαŸ†αžŽαž½αžšαž‡αžΆαž…αŸ’αžšαžΎαž“ αž“αŸ„αŸ‡αž€αžΆαžšαžšαž€αŸ’αžŸαžΆαž’αŸ’αžœαžΈαŸ—αž‚αŸ’αžšαž”αŸ‹αž™αŸ‰αžΆαž„αž“αŸ…αž€αŸ’αž“αž»αž„αžαžΆαžšαžΆαž„αžŠαžΌαž…αž‚αŸ’αž“αžΆαž‡αžΆαž˜αž½αž™αž“αžΉαž„αž’αž„αŸ’αž‚αž—αžΆαž–αž“αžΉαž„αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αžΆαž“αŸ‹αžαŸ‚αž˜αžΆαž“αž”αŸ’αžšαžŸαž·αž‘αŸ’αž’αž—αžΆαž–αŸ” αž αžΎαž™αž€αžΆαžšαž–αž·αžαžŠαŸ‚αž›αžαžΆαž€αžΆαžšαž“αŸαŸ‡αž‡αž½αž™αžŸαž˜αŸ’αžšαž½αž›αž’αž“αŸ’αžαžšαž€αž˜αŸ’αž˜αžšαžœαžΆαž„αž‘αž·αž“αŸ’αž“αž“αŸαž™αž‚αžΊαž‡αžΆαž€αžΆαžšαž”αžΌαž€αž˜αž½αž™αžšαž½αž…αž‘αŸ…αž αžΎαž™ αž”αŸ‰αž»αž“αŸ’αžαŸ‚αž˜αžΌαž›αžŠαŸ’αž‹αžΆαž“αž‘αž·αž“αŸ’αž“αž“αŸαž™αž›αž‘αŸ’αž’αž•αž›αž‚αžΊαžαžΌαž…αž‡αžΆαž„ 3 αžŠαž„αž€αŸ’αž“αž»αž„αž”αžšαž·αž˜αžΆαžŽαŸ”

αžŠαžΌαž…αž‚αŸ’αž“αžΆαž“αŸαŸ‡αž•αž„αžŠαŸ‚αžš αžŠαŸ„αž™αž•αŸ’αž’αŸ‚αž€αž›αžΎαž€αžΆαžšαž’αŸ’αžœαžΎαžαŸαžŸαŸ’αžαžŠαŸ‚αž›αž”αžΆαž“αž’αž“αž»αžœαžαŸ’αž αž™αžΎαž„αž’αžΆαž…αžŸαž“αŸ’αž“αž·αžŠαŸ’αž‹αžΆαž“αžαžΆαž€αžΆαžšαžαžΆαžαž”αž„αŸ‹αž“αŸƒαž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαž‚αžΊαž˜αž·αž“αžŸαŸ†αžαžΆαž“αŸ‹αžαŸ’αž›αžΆαŸ†αž„αžŽαžΆαžŸαŸ‹αŸ” αž€αŸ’αž“αž»αž„αž€αžšαžŽαžΈαžαŸ’αž›αŸ‡ JSONB αž›αžΏαž“αž‡αžΆαž„ EAV αžŠαŸ‚αž›αž’αŸ’αžœαžΎαž±αŸ’αž™αžœαžΆαž€αžΆαž“αŸ‹αžαŸ‚αž”αŸ’αžšαžŸαžΎαžšαŸ” αž‘αŸ„αŸ‡αž‡αžΆαž™αŸ‰αžΆαž„αžŽαžΆαž€αŸαžŠαŸ„αž™ αžŸαŸ’αžαž„αŸ‹αžŠαžΆαžšαž“αŸαŸ‡αž‡αžΆαž€αžΆαžšαž–αž·αžαžŽαžΆαžŸαŸ‹αž˜αž·αž“αž‚αŸ’αžšαž”αžŠαžŽαŸ’αžαž”αŸ‹αž‚αŸ’αžšαž”αŸ‹αž‘αž·αžŠαŸ’αž‹αž—αžΆαž–αž‘αžΆαŸ†αž„αž’αžŸαŸ‹ (ឧ. αž’αž„αŸ’αž‚αž—αžΆαž–αžŠαŸ‚αž›αž˜αžΆαž“αž›αž€αŸ’αžαžŽαŸˆαžŸαž˜αŸ’αž”αžαŸ’αžαž·αž˜αž½αž™αž…αŸ†αž“αž½αž“αž’αŸ† αž€αžΆαžšαž€αžΎαž“αž‘αžΎαž„αž‚αž½αžšαž±αŸ’αž™αž€αžαŸ‹αžŸαž˜αŸ’αž‚αžΆαž›αŸ‹αž“αŸƒαž…αŸ†αž“αž½αž“αž›αž€αŸ’αžαžŽαŸˆαžŸαž˜αŸ’αž”αžαŸ’αžαž·αž“αŸƒαž‘αž·αž“αŸ’αž“αž“αŸαž™αžŠαŸ‚αž›αž˜αžΆαž“αžŸαŸ’αžšαžΆαž”αŸ‹...) αžŠαžΌαž…αŸ’αž“αŸαŸ‡αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž’αŸ’αž“αž€αž˜αžΆαž“αž€αžΆαžšαžŽαŸ‚αž“αžΆαŸ†αž’αŸ†αž–αžΈαžœαž·αž’αžΈαž€αŸ‚αž›αž˜αŸ’αž’αž–αž½αž€αžœαžΆαŸ” , αžŸαžΌαž˜αž˜αžΆαž“αž’αžΆαžšαž˜αŸ’αž˜αžŽαŸαžŸαŸαžšαžΈαž€αŸ’αž“αž»αž„αž€αžΆαžšαž”αž‰αŸ’αž…αŸαž‰αž˜αžαž·!

αž”αŸ’αžšαž—αž–: www.habr.com

αž‘αž·αž‰αž€αžΆαžšαž”αž„αŸ’αž αŸ„αŸ‡αžŠαŸ‚αž›αž’αžΆαž…αž‘αž»αž€αž…αž·αžαŸ’αžαž”αžΆαž“αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž‚αŸαž αž‘αŸ†αž–αŸαžšαžŠαŸ‚αž›αž˜αžΆαž“αž€αžΆαžšαž€αžΆαžšαž–αžΆαžš DDoS, αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸ VPS VDS πŸ”₯ αž‘αž·αž‰αžŸαŸαžœαžΆαž”αž„αŸ’αž αŸ„αŸ‡αž‚αŸαž αž‘αŸ†αž–αŸαžšαžŠαŸ‚αž›αž’αžΆαž…αž‘αž»αž€αž…αž·αžαŸ’αžαž”αžΆαž“αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαž€αžΆαžšαž–αžΆαžš DDoS αž“αž·αž„αž˜αŸ‰αžΆαžŸαŸŠαžΈαž“αž˜αŸ VPS VDS | ProHoster