ΠΠΈΠΊΡΠΎΡΠ΅ΡΠ²ΠΈΡΠ½Π°Ρ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ°, ΠΊΠ°ΠΊ ΠΈ Π²ΡΠ΅ Π² ΡΡΠΎΠΌ ΠΌΠΈΡΠ΅, ΠΈΠΌΠ΅Π΅Ρ ΡΠ²ΠΎΠΈ ΠΏΠ»ΡΡΡ ΠΈ ΡΠ²ΠΎΠΈ ΠΌΠΈΠ½ΡΡΡ. ΠΠ΄Π½ΠΈ ΠΏΡΠΎΡΠ΅ΡΡΡ Ρ Π½Π΅ΠΉ ΡΡΠ°Π½ΠΎΠ²ΡΡΡΡ ΠΏΡΠΎΡΠ΅, Π΄ΡΡΠ³ΠΈΠ΅ β ΡΠ»ΠΎΠΆΠ½Π΅Π΅. Π Π² ΡΠ³ΠΎΠ΄Ρ ΡΠΊΠΎΡΠΎΡΡΠΈ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ ΠΈ Π»ΡΡΡΠ΅ΠΉ ΠΌΠ°ΡΡΡΠ°Π±ΠΈΡΡΠ΅ΠΌΠΎΡΡΠΈ Π½ΡΠΆΠ½ΠΎ ΠΏΡΠΈΠ½ΠΎΡΠΈΡΡ ΡΠ²ΠΎΠΈ ΠΆΠ΅ΡΡΠ²Ρ. ΠΠ΄Π½Π° ΠΈΠ· Π½ΠΈΡ β ΡΡΠ»ΠΎΠΆΠ½Π΅Π½ΠΈΠ΅ Π°Π½Π°Π»ΠΈΡΠΈΠΊΠΈ. ΠΡΠ»ΠΈ Π² ΠΌΠΎΠ½ΠΎΠ»ΠΈΡΠ΅ Π²ΡΡ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠ²Π½ΡΡ Π°Π½Π°Π»ΠΈΡΠΈΠΊΡ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ²Π΅ΡΡΠΈ ΠΊ SQL Π·Π°ΠΏΡΠΎΡΠ°ΠΌ ΠΊ Π°Π½Π°Π»ΠΈΡΠΈΡΠ΅ΡΠΊΠΎΠΉ ΡΠ΅ΠΏΠ»ΠΈΠΊΠ΅, ΡΠΎ Π² ΠΌΡΠ»ΡΡΠΈΡΠ΅ΡΠ²ΠΈΡΠ½ΠΎΠΉ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ΅ Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΡΠ΅ΡΠ²ΠΈΡΠ° ΡΠ²ΠΎΡ Π±Π°Π·Π° ΠΈ, ΠΊΠ°ΠΆΠ΅ΡΡΡ, ΡΡΠΎ ΠΎΠ΄Π½ΠΈΠΌ Π·Π°ΠΏΡΠΎΡΠΎΠΌ Π½Π΅ ΠΎΠ±ΠΎΠΉΡΠΈΡΡ (Π° ΠΌΠΎΠΆΠ΅Ρ ΠΎΠ±ΠΎΠΉΡΠΈΡΡ?). ΠΠ»Ρ ΡΠ΅Ρ , ΠΊΠΎΠΌΡ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ½ΠΎ, ΠΊΠ°ΠΊ ΠΌΡ ΡΠ΅ΡΠΈΠ»ΠΈ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠ²Π½ΠΎΠΉ Π°Π½Π°Π»ΠΈΡΠΈΠΊΠΈ Ρ ΡΠ΅Π±Ρ Π² ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ ΠΈ ΠΊΠ°ΠΊ Π½Π°ΡΡΠΈΠ»ΠΈΡΡ ΠΆΠΈΡΡ Ρ ΡΡΠΈΠΌ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ΠΌ β welcome.
ΠΠ΅Π½Ρ Π·ΠΎΠ²ΡΡ ΠΠ°Π²Π΅Π» Π‘ΠΈΠ²Π°Ρ, Π² ΠΠΎΠΌΠΠ»ΠΈΠΊΠ΅ Ρ ΡΠ°Π±ΠΎΡΠ°Ρ Π² ΠΊΠΎΠΌΠ°Π½Π΄Π΅, ΠΊΠΎΡΠΎΡΠ°Ρ ΠΎΡΠ²Π΅ΡΠ°Π΅Ρ Π·Π° ΡΠΎΠΏΡΠΎΠ²ΠΎΠΆΠ΄Π΅Π½ΠΈΠ΅ Π°Π½Π°Π»ΠΈΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ Ρ
ΡΠ°Π½ΠΈΠ»ΠΈΡΠ° Π΄Π°Π½Π½ΡΡ
. Π£ΡΠ»ΠΎΠ²Π½ΠΎ Π½Π°ΡΡ Π΄Π΅ΡΡΠ΅Π»ΡΠ½ΠΎΡΡΡ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΡΠ½Π΅ΡΡΠΈ ΠΊ Π΄Π°ΡΠ° ΠΈΠ½ΠΆΠ΅Π½Π΅ΡΠΈΠΈ, Π½ΠΎ, Π½Π° ΡΠ°ΠΌΠΎΠΌ Π΄Π΅Π»Π΅, ΡΠΏΠ΅ΠΊΡΡ Π·Π°Π΄Π°Ρ Π³ΠΎΡΠ°Π·Π΄ΠΎ ΡΠΈΡΠ΅. ΠΡΡΡ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΡΠ΅ Π΄Π»Ρ Π΄Π°ΡΠ° ΠΈΠ½ΠΆΠ΅Π½Π΅ΡΠΈΠΈ ETL/ELT, ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠ° ΠΈ Π°Π΄Π°ΠΏΡΠ°ΡΠΈΡ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠΎΠ² Π΄Π»Ρ Π°Π½Π°Π»ΠΈΠ·Π° Π΄Π°Π½Π½ΡΡ
ΠΈ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠ° ΡΠ²ΠΎΠΈΡ
ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠΎΠ². Π ΡΠ°ΡΡΠ½ΠΎΡΡΠΈ, Π΄Π»Ρ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠ²Π½ΠΎΠΉ ΠΎΡΡΠ΅ΡΠ½ΠΎΡΡΠΈ ΠΌΡ ΡΠ΅ΡΠΈΠ»ΠΈ Β«ΠΏΡΠΈΡΠ²ΠΎΡΠΈΡΡΡΡΒ», ΡΡΠΎ Ρ Π½Π°Ρ ΠΌΠΎΠ½ΠΎΠ»ΠΈΡ ΠΈ Π΄Π°ΡΡ Π°Π½Π°Π»ΠΈΡΠΈΠΊΠ°ΠΌ ΠΎΠ΄Π½Ρ Π±Π°Π·Ρ, Π² ΠΊΠΎΡΠΎΡΠΎΠΉ Π±ΡΠ΄ΡΡ Π²ΡΠ΅ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΡΠ΅ ΠΈΠΌ Π΄Π°Π½Π½ΡΠ΅.
ΠΠΎΠΎΠ±ΡΠ΅, ΠΌΡ ΡΠ°ΡΡΠΌΠ°ΡΡΠΈΠ²Π°Π»ΠΈ ΡΠ°Π·Π½ΡΠ΅ Π²Π°ΡΠΈΠ°Π½ΡΡ. ΠΠΎΠΆΠ½ΠΎ Π±ΡΠ»ΠΎ ΠΏΠΎΡΡΡΠΎΠΈΡΡ ΠΏΠΎΠ»Π½ΠΎΡΠ΅Π½Π½ΠΎΠ΅ Ρ ΡΠ°Π½ΠΈΠ»ΠΈΡΠ΅ β ΠΌΡ Π΄Π°ΠΆΠ΅ ΠΏΡΠΎΠ±ΠΎΠ²Π°Π»ΠΈ, Π½ΠΎ, Π΅ΡΠ»ΠΈ ΡΠ΅ΡΡΠ½ΠΎ, ΡΠ°ΠΊ ΠΈ Π½Π΅ ΡΠ΄Π°Π»ΠΎΡΡ ΠΏΠΎΠ΄ΡΡΠΆΠΈΡΡ Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎ ΡΠ°ΡΡΡΠ΅ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ Π² Π»ΠΎΠ³ΠΈΠΊΠ΅ Ρ Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎ ΠΌΠ΅Π΄Π»Π΅Π½Π½ΡΠΌ ΠΏΡΠΎΡΠ΅ΡΡΠΎΠΌ ΠΏΠΎΡΡΡΠΎΠ΅Π½ΠΈΡ Ρ ΡΠ°Π½ΠΈΠ»ΠΈΡΠ° ΠΈ Π²Π½Π΅ΡΠ΅Π½ΠΈΡ Π² Π½Π΅Π³ΠΎ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ (Π΅ΡΠ»ΠΈ Ρ ΠΊΠΎΠ³ΠΎ-ΡΠΎ ΠΏΠΎΠ»ΡΡΠΈΠ»ΠΎΡΡ, Π½Π°ΠΏΠΈΡΠΈΡΠ΅ Π² ΠΊΠΎΠΌΠΌΠ΅Π½ΡΠ°ΡΠΈΡΡ ΠΊΠ°ΠΊ). ΠΠΎΠΆΠ½ΠΎ Π±ΡΠ»ΠΎ ΡΠΊΠ°Π·Π°ΡΡ Π°Π½Π°Π»ΠΈΡΠΈΠΊΠ°ΠΌ: Β«Π Π΅Π±ΡΡΠ°, ΡΡΠΈΡΠ΅ python ΠΈ Ρ ΠΎΠ΄ΠΈΡΠ΅ Π² Π°Π½Π°Π»ΠΈΡΠΈΡΠ΅ΡΠΊΠΈΠ΅ ΡΠ΅ΠΏΠ»ΠΈΠΊΠΈΒ», Π½ΠΎ ΡΡΠΎ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΠΎΠ΅ ΡΡΠ΅Π±ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΊ ΠΏΠΎΠ΄Π±ΠΎΡΡ ΠΏΠ΅ΡΡΠΎΠ½Π°Π»Π°, ΠΈ ΠΊΠ°Π·Π°Π»ΠΎΡΡ, ΡΡΠΎ ΡΡΠΎΠ³ΠΎ ΡΡΠΎΠΈΡ ΠΈΠ·Π±Π΅ΠΆΠ°ΡΡ, Π΅ΡΠ»ΠΈ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ. Π Π΅ΡΠΈΠ»ΠΈ ΠΏΠΎΠΏΡΠΎΠ±ΠΎΠ²Π°ΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΠ΅Ρ Π½ΠΎΠ»ΠΎΠ³ΠΈΡ FDW (Foreign Data Wrapper): ΠΏΠΎ ΡΡΡΠΈ, ΡΡΠΎ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΡΠΉ dblink, ΠΊΠΎΡΠΎΡΡΠΉ Π΅ΡΡΡ Π² ΡΡΠ°Π½Π΄Π°ΡΡΠ΅ SQL, Π½ΠΎ ΡΠΎ ΡΠ²ΠΎΠΈΠΌ Π³ΠΎΡΠ°Π·Π΄ΠΎ Π±ΠΎΠ»Π΅Π΅ ΡΠ΄ΠΎΠ±Π½ΡΠΌ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠΌ. ΠΠ° Π±Π°Π·Π΅ Π½Π΅Π΅ ΠΌΡ ΡΠ΄Π΅Π»Π°Π»ΠΈ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅, ΠΊΠΎΡΠΎΡΠΎΠ΅ Π² ΠΈΡΠΎΠ³Π΅ ΠΈ ΠΏΡΠΈΠΆΠΈΠ»ΠΎΡΡ, Π½Π° Π½Π΅ΠΌ ΠΌΡ ΠΎΡΡΠ°Π½ΠΎΠ²ΠΈΠ»ΠΈΡΡ. ΠΠ³ΠΎ ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎΡΡΠΈ β ΡΠ΅ΠΌΠ° ΠΎΡΠ΄Π΅Π»ΡΠ½ΠΎΠΉ ΡΡΠ°ΡΡΠΈ, Π° ΠΌΠΎΠΆΠ΅Ρ ΠΈ Π½Π΅ ΠΎΠ΄Π½ΠΎΠΉ, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΡΠ°ΡΡΠΊΠ°Π·Π°ΡΡ Ρ ΠΎΡΠ΅ΡΡΡ ΠΎ ΠΌΠ½ΠΎΠ³ΠΎΠΌ: ΠΎΡ ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΠΈ ΡΡ Π΅ΠΌ Π±Π°Π· Π΄ΠΎ ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ Π΄ΠΎΡΡΡΠΏΠΎΠΌ ΠΈ ΠΎΠ±Π΅Π·Π»ΠΈΡΠΈΠ²Π°Π½ΠΈΡ ΠΏΠ΅ΡΡΠΎΠ½Π°Π»ΡΠ½ΡΡ Π΄Π°Π½Π½ΡΡ . Π’Π°ΠΊΠΆΠ΅ Π½ΡΠΆΠ½ΠΎ ΠΎΠ³ΠΎΠ²ΠΎΡΠΈΡΡΡΡ, ΡΡΠΎ ΡΡΠΎ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ Π½Π΅ ΡΠ²Π»ΡΠ΅ΡΡΡ Π·Π°ΠΌΠ΅Π½ΠΎΠΉ ΡΠ΅Π°Π»ΡΠ½ΡΠΌ Π°Π½Π°Π»ΠΈΡΠΈΡΠ΅ΡΠΊΠΈΠΌ Π±Π°Π·Π°ΠΌ ΠΈ Ρ ΡΠ°Π½ΠΈΠ»ΠΈΡΠ°ΠΌ, ΠΎΠ½ΠΎ ΡΠ΅ΡΠ°Π΅Ρ Π»ΠΈΡΡ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΡΡ Π·Π°Π΄Π°ΡΡ.
ΠΠ΅ΡΡ Π½Π΅ΡΡΠΎΠ²Π½Π΅Π²ΠΎ ΡΡΠΎ Π²ΡΠ³Π»ΡΠ΄ΠΈΡ ΡΠ°ΠΊ:
ΠΡΡΡ Π±Π°Π·Π° PostgreSQL, ΡΠ°ΠΌ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΠΈ ΠΌΠΎΠ³ΡΡ Ρ
ΡΠ°Π½ΠΈΡΡ ΡΠ²ΠΎΠΈ ΡΠ°Π±ΠΎΡΠΈΠ΅ Π΄Π°Π½Π½ΡΠ΅, Π° ΡΠ°ΠΌΠΎΠ΅ Π²Π°ΠΆΠ½ΠΎΠ΅ β ΠΊ ΡΡΠΎΠΉ Π±Π°Π·Π΅ ΡΠ΅ΡΠ΅Π· FDW ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½Ρ Π°Π½Π°Π»ΠΈΡΠΈΡΠ΅ΡΠΊΠΈΠ΅ ΡΠ΅ΠΏΠ»ΠΈΠΊΠΈ Π²ΡΠ΅Ρ
ΡΠ΅ΡΠ²ΠΈΡΠΎΠ². ΠΡΠΎ Π΄Π°Π΅Ρ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ Π½Π°ΠΏΠΈΡΠ°ΡΡ Π·Π°ΠΏΡΠΎΡ ΠΊ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΠΌ Π±Π°Π·Π°ΠΌ, ΠΏΡΠΈΡΠ΅ΠΌ Π½Π΅Π²Π°ΠΆΠ½ΠΎ, ΡΡΠΎ ΡΡΠΎ: PostgreSQL, MySQL, MongoDB ΠΈΠ»ΠΈ Π΅ΡΠ΅ ΡΡΠΎ-ΡΠΎ (ΡΠ°ΠΉΠ», API, Π΅ΡΠ»ΠΈ Π²Π΄ΡΡΠ³ Π½Π΅Ρ ΠΏΠΎΠ΄Ρ
ΠΎΠ΄ΡΡΠ΅Π³ΠΎ Π²ΡΠ°ΠΏΠΏΠ΅ΡΠ°, ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΏΠΈΡΠ°ΡΡ ΡΠ²ΠΎΠΉ). ΠΡ Π²ΡΠΎΠ΄Π΅ Π²ΡΠ΅, ΡΡΠΏΠ΅Ρ! Π Π°ΡΡ
ΠΎΠ΄ΠΈΠΌΡΡ?
ΠΡΠ»ΠΈ Π±Ρ Π²ΡΠ΅ Π·Π°ΠΊΠ°Π½ΡΠΈΠ²Π°Π»ΠΎΡΡ ΡΠ°ΠΊ Π±ΡΡΡΡΠΎ ΠΈ ΠΏΡΠΎΡΡΠΎ, ΡΠΎ, Π½Π°Π²Π΅ΡΠ½ΠΎΠ΅, ΡΡΠ°ΡΡΠΈ Π±Ρ ΠΈ Π½Π΅ Π±ΡΠ»ΠΎ.
ΠΠ°ΠΆΠ½ΠΎ ΡΠ΅ΡΠΊΠΎ ΠΎΡΠΎΠ·Π½Π°Π²Π°ΡΡ, ΠΊΠ°ΠΊ ΠΏΠΎΡΡΠ³ΡΠ΅Ρ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ Π·Π°ΠΏΡΠΎΡΡ ΠΊ ΡΠ΄Π°Π»Π΅Π½Π½ΡΠΌ ΡΠ΅ΡΠ²Π΅ΡΠ°ΠΌ. ΠΡΠΎ ΠΊΠ°ΠΆΠ΅ΡΡΡ Π»ΠΎΠ³ΠΈΡΠ½ΡΠΌ, ΠΎΠ΄Π½Π°ΠΊΠΎ Π·Π°ΡΠ°ΡΡΡΡ Π½Π° ΡΡΠΎ Π½Π΅ ΠΎΠ±ΡΠ°ΡΠ°ΡΡ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅: ΠΏΠΎΡΡΠ³ΡΠ΅Ρ Π΄Π΅Π»ΠΈΡ Π·Π°ΠΏΡΠΎΡ Π½Π° ΡΠ°ΡΡΠΈ, ΠΊΠΎΡΠΎΡΡΠ΅ Π²ΡΠΏΠΎΠ»Π½ΡΡΡΡΡ Π½Π° ΡΠ΄Π°Π»Π΅Π½Π½ΡΡ ΡΠ΅ΡΠ²Π΅ΡΠ°Ρ Π½Π΅Π·Π°Π²ΠΈΡΠΈΠΌΠΎ, ΡΠΎΠ±ΠΈΡΠ°Π΅Ρ ΡΡΠΈ Π΄Π°Π½Π½ΡΠ΅, Π° ΡΠΈΠ½Π°Π»ΡΠ½ΡΠ΅ Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΡ ΠΏΡΠΎΠ²ΠΎΠ΄ΠΈΡ ΡΠΆΠ΅ ΡΠ°ΠΌ, ΠΏΠΎΡΡΠΎΠΌΡ ΡΠΊΠΎΡΠΎΡΡΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Π·Π°ΠΏΡΠΎΡΠ° Π±ΡΠ΄Π΅Ρ ΡΠΈΠ»ΡΠ½ΠΎ Π·Π°Π²ΠΈΡΠ΅ΡΡ ΠΎΡ ΡΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΎΠ½ Π½Π°ΠΏΠΈΡΠ°Π½. Π‘Π»Π΅Π΄ΡΠ΅Ρ ΡΠ°ΠΊ ΠΆΠ΅ ΠΎΡΠΌΠ΅ΡΠΈΡΡ: ΠΊΠΎΠ³Π΄Π° Π΄Π°Π½Π½ΡΠ΅ ΠΏΠΎΡΡΡΠΏΠ°ΡΡ Ρ ΡΠ΄Π°Π»Π΅Π½Π½ΠΎΠ³ΠΎ ΡΠ΅ΡΠ²Π΅ΡΠ° Ρ Π½ΠΈΡ ΡΠΆΠ΅ Π½Π΅Ρ ΠΈΠ½Π΄Π΅ΠΊΡΠΎΠ², Π½Π΅Ρ Π½ΠΈΡΠ΅Π³ΠΎ, ΡΡΠΎ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ ΠΏΠ»Π°Π½ΠΈΡΠΎΠ²ΡΠΈΠΊΡ, ΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»ΡΠ½ΠΎ, ΠΏΠΎΠΌΠΎΡΡ ΠΈ ΠΏΠΎΠ΄ΡΠΊΠ°Π·Π°ΡΡ Π΅ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ ΡΠΎΠ»ΡΠΊΠΎ ΠΌΡ ΡΠ°ΠΌΠΈ. Π ΠΈΠΌΠ΅Π½Π½ΠΎ ΠΎΠ± ΡΡΠΎΠΌ Ρ ΠΎΡΠ΅ΡΡΡ ΡΠ°ΡΡΠΊΠ°Π·Π°ΡΡ ΠΏΠΎΠ΄ΡΠΎΠ±Π½Π΅Π΅.
ΠΡΠΎΡΡΠΎΠΉ Π·Π°ΠΏΡΠΎΡ ΠΈ ΠΏΠ»Π°Π½ Ρ Π½ΠΈΠΌ
Π§ΡΠΎΠ±Ρ ΠΏΠΎΠΊΠ°Π·Π°ΡΡ, ΠΊΠ°ΠΊ ΠΏΠΎΡΡΠ³ΡΠ΅Ρ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅Ρ Π·Π°ΠΏΡΠΎΡ ΠΊ ΡΠ°Π±Π»ΠΈΡΠ΅ Π½Π° 6 ΠΌΠΈΠ»Π»ΠΈΠΎΠ½ΠΎΠ² ΡΡΡΠΎΠΊ Π½Π° ΡΠ΄Π°Π»Π΅Π½Π½ΠΎΠΌ ΡΠ΅ΡΠ²Π΅ΡΠ΅, ΠΏΠΎΡΠΌΠΎΡΡΠΈΠΌ Π½Π° ΠΏΡΠΎΡΡΠΎΠΉ ΠΏΠ»Π°Π½.
explain analyze verbose
SELECT count(1)
FROM fdw_schema.table;
Aggregate (cost=418383.23..418383.24 rows=1 width=8) (actual time=3857.198..3857.198 rows=1 loops=1)
Output: count(1)
-> Foreign Scan on fdw_schema."table" (cost=100.00..402376.14 rows=6402838 width=0) (actual time=4.874..3256.511 rows=6406868 loops=1)
Output: "table".id, "table".is_active, "table".meta, "table".created_dt
Remote SQL: SELECT NULL FROM fdw_schema.table
Planning time: 0.986 ms
Execution time: 3857.436 ms
ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΈΠ½ΡΡΡΡΠΊΡΠΈΠΈ VERBOSE ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΡΠ²ΠΈΠ΄Π΅ΡΡ Π·Π°ΠΏΡΠΎΡ, ΠΊΠΎΡΠΎΡΡΠΉ Π±ΡΠ΄Π΅Ρ ΠΎΡΠΏΡΠ°Π²Π»Π΅Π½ Π½Π° ΡΠ΄Π°Π»Π΅Π½Π½ΡΠΉ ΡΠ΅ΡΠ²Π΅Ρ ΠΈ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΡ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ ΠΌΡ ΠΏΠΎΠ»ΡΡΠΈΠΌ Π΄Π»Ρ Π΄Π°Π»ΡΠ½Π΅ΠΉΡΠ΅ΠΉ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ (ΡΡΡΠΎΠΊΠ° RemoteSQL).
ΠΠΎΠΉΠ΄Π΅ΠΌ ΡΡΡΡ Π΄Π°Π»ΡΡΠ΅ ΠΈ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π² Π½Π°Ρ Π·Π°ΠΏΡΠΎΡ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΠΈΠ»ΡΡΡΠΎΠ²: ΠΎΠ΄ΠΈΠ½ ΠΏΠΎ boolean ΠΏΠΎΠ»Ρ, ΠΎΠ΄ΠΈΠ½ ΠΏΠΎ Π²Ρ ΠΎΠΆΠ΄Π΅Π½ΠΈΡ timestamp Π² ΠΈΠ½ΡΠ΅ΡΠ²Π°Π» ΠΈ ΠΎΠ΄ΠΈΠ½ ΠΏΠΎ jsonb.
explain analyze verbose
SELECT count(1)
FROM fdw_schema.table
WHERE is_active is True
AND created_dt BETWEEN CURRENT_DATE - INTERVAL '7 month'
AND CURRENT_DATE - INTERVAL '6 month'
AND meta->>'source' = 'test';
Aggregate (cost=577487.69..577487.70 rows=1 width=8) (actual time=27473.818..25473.819 rows=1 loops=1)
Output: count(1)
-> Foreign Scan on fdw_schema."table" (cost=100.00..577469.21 rows=7390 width=0) (actual time=31.369..25372.466 rows=1360025 loops=1)
Output: "table".id, "table".is_active, "table".meta, "table".created_dt
Filter: (("table".is_active IS TRUE) AND (("table".meta ->> 'source'::text) = 'test'::text) AND ("table".created_dt >= (('now'::cstring)::date - '7 mons'::interval)) AND ("table".created_dt <= ((('now'::cstring)::date)::timestamp with time zone - '6 mons'::interval)))
Rows Removed by Filter: 5046843
Remote SQL: SELECT created_dt, is_active, meta FROM fdw_schema.table
Planning time: 0.665 ms
Execution time: 27474.118 ms
ΠΠΎΡ ΠΈΠΌΠ΅Π½Π½ΠΎ Π·Π΄Π΅ΡΡ ΠΈ ΠΊΡΠΎΠ΅ΡΡΡ ΠΌΠΎΠΌΠ΅Π½Ρ, Π½Π° ΠΊΠΎΡΠΎΡΡΠΉ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΠΎΠ±ΡΠ°ΡΠ°ΡΡ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ ΠΏΡΠΈ Π½Π°ΠΏΠΈΡΠ°Π½ΠΈΠΈ Π·Π°ΠΏΡΠΎΡΠΎΠ². Π€ΠΈΠ»ΡΡΡΡ Π½Π΅ ΠΏΠ΅ΡΠ΅Π΄Π°Π»ΠΈΡΡ Π½Π° ΡΠ΄Π°Π»Π΅Π½Π½ΡΠΉ ΡΠ΅ΡΠ²Π΅Ρ, Π° ΡΡΠΎ Π·Π½Π°ΡΠΈΡ, ΡΡΠΎ Π΄Π»Ρ Π΅Π³ΠΎ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΏΠΎΡΡΠ³ΡΠ΅Ρ Π²ΡΡΡΠ³ΠΈΠ²Π°Π΅Ρ Π²ΡΠ΅ 6 ΠΌΠΈΠ»Π»ΠΈΠΎΠ½ΠΎΠ² ΡΡΡΠΎΠΊ, ΡΡΠΎΠ±Ρ ΡΠΆΠ΅ ΠΏΠΎΡΠΎΠΌ Π»ΠΎΠΊΠ°Π»ΡΠ½ΠΎ ΠΎΡΡΠΈΠ»ΡΡΡΠΎΠ²Π°ΡΡ (ΡΡΡΠΎΠΊΠ° Filter) ΠΈ ΠΏΡΠΎΠΈΠ·Π²Π΅ΡΡΠΈ Π°Π³ΡΠ΅Π³Π°ΡΠΈΡ. ΠΠ°Π»ΠΎΠ³ ΡΡΠΏΠ΅Ρ Π° β ΡΡΠΎ Π½Π°ΠΏΠΈΡΠ°ΡΡ Π·Π°ΠΏΡΠΎΡ ΡΠ°ΠΊ, ΡΡΠΎΠ±Ρ ΡΠΈΠ»ΡΡΡΡ ΠΏΠ΅ΡΠ΅Π΄Π°Π²Π°Π»ΠΈΡΡ Π½Π° ΡΠ΄Π°Π»Π΅Π½Π½ΡΡ ΠΌΠ°ΡΠΈΠ½Ρ, Π° ΠΌΡ ΠΏΠΎΠ»ΡΡΠ°Π»ΠΈ ΠΈ Π°Π³ΡΠ΅Π³ΠΈΡΠΎΠ²Π°Π»ΠΈ ΡΠΎΠ»ΡΠΊΠΎ Π½ΡΠΆΠ½ΡΠ΅ ΡΡΡΠΎΠΊΠΈ.
That’s some booleanshit
Π‘ boolean ΠΏΠΎΠ»ΡΠΌΠΈ β Π²ΡΠ΅ ΠΏΡΠΎΡΡΠΎ. Π ΠΈΡΡ ΠΎΠ΄Π½ΠΎΠΌ Π·Π°ΠΏΡΠΎΡΠ΅ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ° Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π»Π° ΠΈΠ·-Π·Π° ΠΎΠΏΠ΅ΡΠ°ΡΠΎΡΠ° is. ΠΡΠ»ΠΈ Π·Π°ΠΌΠ΅Π½ΠΈΡΡ Π΅Π³ΠΎ Π½Π° =, ΡΠΎ ΠΌΡ ΠΏΠΎΠ»ΡΡΠΈΠΌ ΡΠ»Π΅Π΄ΡΡΡΠΈΠΉ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ:
explain analyze verbose
SELECT count(1)
FROM fdw_schema.table
WHERE is_active = True
AND created_dt BETWEEN CURRENT_DATE - INTERVAL '7 month'
AND CURRENT_DATE - INTERVAL '6 month'
AND meta->>'source' = 'test';
Aggregate (cost=508010.14..508010.15 rows=1 width=8) (actual time=19064.314..19064.314 rows=1 loops=1)
Output: count(1)
-> Foreign Scan on fdw_schema."table" (cost=100.00..507988.44 rows=8679 width=0) (actual time=33.035..18951.278 rows=1360025 loops=1)
Output: "table".id, "table".is_active, "table".meta, "table".created_dt
Filter: ((("table".meta ->> 'source'::text) = 'test'::text) AND ("table".created_dt >= (('now'::cstring)::date - '7 mons'::interval)) AND ("table".created_dt <= ((('now'::cstring)::date)::timestamp with time zone - '6 mons'::interval)))
Rows Removed by Filter: 3567989
Remote SQL: SELECT created_dt, meta FROM fdw_schema.table WHERE (is_active)
Planning time: 0.834 ms
Execution time: 19064.534 ms
ΠΠ°ΠΊ Π²ΠΈΠ΄ΠΈΡΠ΅, ΡΠΈΠ»ΡΡΡ ΡΠ»Π΅ΡΠ΅Π» Π½Π° ΡΠ΄Π°Π»Π΅Π½Π½ΡΠΉ ΡΠ΅ΡΠ²Π΅Ρ, Π° Π²ΡΠ΅ΠΌΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΡΠΎΠΊΡΠ°ΡΠΈΠ»ΠΎΡΡ Ρ 27 Π΄ΠΎ 19 ΡΠ΅ΠΊΡΠ½Π΄.
Π‘ΡΠΎΠΈΡ ΠΎΡΠΌΠ΅ΡΠΈΡΡ, ΡΡΠΎ ΠΎΠΏΠ΅ΡΠ°ΡΠΎΡ is ΠΎΡΠ»ΠΈΡΠ°Π΅ΡΡΡ ΠΎΡ ΠΎΠΏΠ΅ΡΠ°ΡΠΎΡΠ° = ΡΠ΅ΠΌ, ΡΡΠΎ ΡΠΌΠ΅Π΅Ρ ΡΠ°Π±ΠΎΡΠ°ΡΡ ΡΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ΠΌ Null. ΠΡΠΎ ΠΎΠ·Π½Π°ΡΠ°Π΅Ρ, ΡΡΠΎ is not True Π² ΡΠΈΠ»ΡΡΡΠ΅ ΠΎΡΡΠ°Π²ΠΈΡ Π·Π½Π°ΡΠ΅Π½ΠΈΡ False ΠΈ Null, ΡΠΎΠ³Π΄Π° ΠΊΠ°ΠΊ != True ΠΎΡΡΠ°Π²ΠΈΡ ΡΠΎΠ»ΡΠΊΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΡ False. ΠΠΎΡΡΠΎΠΌΡ ΠΏΡΠΈ Π·Π°ΠΌΠ΅Π½Π΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΎΡΠ° is not ΡΠ»Π΅Π΄ΡΠ΅Ρ ΠΏΠ΅ΡΠ΅Π΄Π°Π²Π°ΡΡ Π² ΡΠΈΠ»ΡΡΡ Π΄Π²Π° ΡΡΠ»ΠΎΠ²ΠΈΡ Ρ ΠΎΠΏΠ΅ΡΠ°ΡΠΎΡΠΎΠΌ OR, ΠΊ ΠΏΡΠΈΠΌΠ΅ΡΡ, WHERE (col != True) OR (col is null).
Π‘ boolean ΡΠ°Π·ΠΎΠ±ΡΠ°Π»ΠΈΡΡ, Π΄Π²ΠΈΠ³Π°Π΅ΠΌΡΡ Π΄Π°Π»ΡΡΠ΅. Π ΠΏΠΎΠΊΠ° Π²Π΅ΡΠ½Π΅ΠΌ ΡΠΈΠ»ΡΡΡ ΠΏΠΎ Π±ΡΠ»Π΅Π²Ρ Π·Π½Π°ΡΠ΅Π½ΠΈΡ Π² ΠΈΠ·Π½Π°ΡΠ°Π»ΡΠ½ΡΠΉ Π²ΠΈΠ΄, ΡΡΠΎΠ±Ρ Π½Π΅Π·Π°Π²ΠΈΡΠΈΠΌΠΎ ΡΠ°ΡΡΠΌΠΎΡΡΠ΅ΡΡ ΡΡΡΠ΅ΠΊΡ ΠΎΡ Π΄ΡΡΠ³ΠΈΡ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ.
timestamptz? hz
ΠΠΎΠΎΠ±ΡΠ΅, ΡΠ°ΡΡΠΎ ΠΏΡΠΈΡ ΠΎΠ΄ΠΈΡΡΡ ΡΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½ΡΠΈΡΠΎΠ²Π°ΡΡ Ρ ΡΠ΅ΠΌ, ΠΊΠ°ΠΊ ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎ Π½Π°ΠΏΠΈΡΠ°ΡΡ Π·Π°ΠΏΡΠΎΡ, Π² ΠΊΠΎΡΠΎΡΠΎΠΌ ΡΡΠ°ΡΡΠ²ΡΡΡ ΡΠ΄Π°Π»Π΅Π½Π½ΡΠ΅ ΡΠ΅ΡΠ²Π΅ΡΠ°, Π° ΡΠΆΠ΅ ΠΏΠΎΡΠΎΠΌ ΠΈΡΠΊΠ°ΡΡ ΠΎΠ±ΡΡΡΠ½Π΅Π½ΠΈΠ΅, ΠΏΠΎΡΠ΅ΠΌΡ ΠΏΡΠΎΠΈΡΡ ΠΎΠ΄ΠΈΡ ΠΈΠΌΠ΅Π½Π½ΠΎ ΡΠ°ΠΊ. ΠΡΠ΅Π½Ρ ΠΌΠ°Π»ΠΎ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΈ ΠΏΠΎ ΡΡΠΎΠΌΡ ΠΏΠΎΠ²ΠΎΠ΄Ρ ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡΠΈ Π² ΠΠ½ΡΠ΅ΡΠ½Π΅ΡΠ΅. Π’Π°ΠΊ, Π² ΡΠΊΡΠΏΠ΅ΡΠΈΠΌΠ΅Π½ΡΠ°Ρ ΠΌΡ ΠΎΠ±Π½Π°ΡΡΠΆΠΈΠ»ΠΈ, ΡΡΠΎ ΡΠΈΠ»ΡΡΡ ΠΏΠΎ ΡΠΈΠΊΡΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠΉ Π΄Π°ΡΠ΅ ΡΠ»Π΅ΡΠ°Π΅Ρ Π½Π° ΡΠ΄Π°Π»Π΅Π½Π½ΡΠΉ ΡΠ΅ΡΠ²Π΅Ρ Π½Π° ΡΡΠ°, Π° Π²ΠΎΡ ΠΊΠΎΠ³Π΄Π° ΠΌΡ Ρ ΠΎΡΠΈΠΌ Π·Π°Π΄Π°ΡΡ Π΄Π°ΡΡ Π΄ΠΈΠ½Π°ΠΌΠΈΡΠ΅ΡΠΊΠΈ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, now() ΠΈΠ»ΠΈ CURRENT_DATE, ΡΠ°ΠΊΠΎΠ³ΠΎ Π½Π΅ ΠΏΡΠΎΠΈΡΡ ΠΎΠ΄ΠΈΡ. Π Π½Π°ΡΠ΅ΠΌ ΠΏΡΠΈΠΌΠ΅ΡΠ΅, ΠΌΡ Π΄ΠΎΠ±Π°Π²ΠΈΠ»ΠΈ ΡΠ°ΠΊΠΎΠΉ ΡΠΈΠ»ΡΡΡ, ΡΡΠΎΠ±Ρ ΡΡΠΎΠ»Π±Π΅Ρ created_at ΡΠΎΠ΄Π΅ΡΠΆΠ°Π» Π² ΡΠ΅Π±Π΅ Π΄Π°Π½Π½ΡΠ΅ ΡΠΎΠ²Π½ΠΎ Π·Π° 1 ΠΌΠ΅ΡΡΡ Π² ΠΏΡΠΎΡΠ»ΠΎΠΌ (BETWEEN CURRENT_DATE β INTERVAL ‘7 month’ AND CURRENT_DATE β INTERVAL ‘6 month’). Π§ΡΠΎ ΠΆΠ΅ ΠΌΡ ΠΏΡΠ΅Π΄ΠΏΡΠΈΠ½ΡΠ»ΠΈ Π² Π΄Π°Π½Π½ΠΎΠΌ ΡΠ»ΡΡΠ°Π΅?
explain analyze verbose
SELECT count(1)
FROM fdw_schema.table
WHERE is_active is True
AND created_dt >= (SELECT CURRENT_DATE::timestamptz - INTERVAL '7 month')
AND created_dt <(SELECT CURRENT_DATE::timestamptz - INTERVAL '6 month')
AND meta->>'source' = 'test';
Aggregate (cost=306875.17..306875.18 rows=1 width=8) (actual time=4789.114..4789.115 rows=1 loops=1)
Output: count(1)
InitPlan 1 (returns $0)
-> Result (cost=0.00..0.02 rows=1 width=8) (actual time=0.007..0.008 rows=1 loops=1)
Output: ((('now'::cstring)::date)::timestamp with time zone - '7 mons'::interval)
InitPlan 2 (returns $1)
-> Result (cost=0.00..0.02 rows=1 width=8) (actual time=0.002..0.002 rows=1 loops=1)
Output: ((('now'::cstring)::date)::timestamp with time zone - '6 mons'::interval)
-> Foreign Scan on fdw_schema."table" (cost=100.02..306874.86 rows=105 width=0) (actual time=23.475..4681.419 rows=1360025 loops=1)
Output: "table".id, "table".is_active, "table".meta, "table".created_dt
Filter: (("table".is_active IS TRUE) AND (("table".meta ->> 'source'::text) = 'test'::text))
Rows Removed by Filter: 76934
Remote SQL: SELECT is_active, meta FROM fdw_schema.table WHERE ((created_dt >= $1::timestamp with time zone)) AND ((created_dt < $2::timestamp with time zone))
Planning time: 0.703 ms
Execution time: 4789.379 ms
ΠΡ ΠΏΠΎΠ΄ΡΠΊΠ°Π·Π°Π»ΠΈ ΠΏΠ»Π°Π½ΠΈΡΠΎΠ²ΡΠΈΠΊΡ Π·Π°ΡΠ°Π½Π΅Π΅ Π²ΡΡΠΈΡΠ»ΠΈΡΡ Π΄Π°ΡΡ Π² ΠΏΠΎΠ΄Π·Π°ΠΏΡΠΎΡΠ΅ ΠΈ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ ΡΠΆΠ΅ Π³ΠΎΡΠΎΠ²ΡΡ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ Π² ΡΠΈΠ»ΡΡΡ. Π ΡΡΠ° ΠΏΠΎΠ΄ΡΠΊΠ°Π·ΠΊΠ° Π΄Π°Π»Π° Π½Π°ΠΌ ΠΏΡΠ΅ΠΊΡΠ°ΡΠ½ΡΠΉ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ, Π·Π°ΠΏΡΠΎΡ ΡΡΠ°Π» Π±ΡΡΡΡΠ΅Π΅ ΠΏΠΎΡΡΠΈ Π² 6 ΡΠ°Π·!
ΠΠΏΡΡΡ ΠΆΠ΅, Π·Π΄Π΅ΡΡ Π²Π°ΠΆΠ½ΠΎ Π±ΡΡΡ Π²Π½ΠΈΠΌΠ°ΡΠ΅Π»ΡΠ½ΡΠΌ: ΡΠΈΠΏ Π΄Π°Π½Π½ΡΡ Π² ΠΏΠΎΠ΄Π·Π°ΠΏΡΠΎΡΠ΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±ΡΡΡ ΡΠ°ΠΊΠΈΠΌ ΠΆΠ΅, ΡΡΠΎ ΠΈ Ρ ΠΏΠΎΠ»Ρ, ΠΏΠΎ ΠΊΠΎΡΠΎΡΠΎΠΌΡ ΡΠΈΠ»ΡΡΡΡΠ΅ΠΌ, ΠΈΠ½Π°ΡΠ΅ ΠΏΠ»Π°Π½ΠΈΡΠΎΠ²ΡΠΈΠΊ ΡΠ΅ΡΠΈΡ, ΡΡΠΎ ΡΠ°Π· ΡΠΈΠΏΡ ΡΠ°Π·Π½ΡΠ΅ ΠΈ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΡΠ½Π°ΡΠ°Π»Π° Π΄ΠΎΡΡΠ°ΡΡ Π²ΡΠ΅ Π΄Π°Π½Π½ΡΠ΅ ΠΈ ΡΠΆΠ΅ Π»ΠΎΠΊΠ°Π»ΡΠ½ΠΎ ΠΎΡΡΠΈΠ»ΡΡΡΠΎΠ²Π°ΡΡ.
ΠΠ΅ΡΠ½Π΅ΠΌ ΡΠΈΠ»ΡΡΡ ΠΏΠΎ Π΄Π°ΡΠ΅ Π² ΠΈΡΡ ΠΎΠ΄Π½ΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅.
Freddy vs. Jsonb
Π ΠΎΠ±ΡΠ΅ΠΌ-ΡΠΎ Π±ΡΠ»Π΅Π²Ρ ΠΏΠΎΠ»Ρ ΠΈ Π΄Π°ΡΡ ΡΠΆΠ΅ Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎ ΡΡΠΊΠΎΡΠΈΠ»ΠΈ Π½Π°Ρ Π·Π°ΠΏΡΠΎΡ, ΠΎΠ΄Π½Π°ΠΊΠΎ ΠΎΡΡΠ°Π²Π°Π»ΡΡ Π΅ΡΠ΅ ΠΎΠ΄ΠΈΠ½ ΡΠΈΠΏ Π΄Π°Π½Π½ΡΡ . ΠΠΈΡΠ²Π° Ρ ΡΠΈΠ»ΡΡΡΠ°ΡΠΈΠ΅ΠΉ ΠΏΠΎ Π½Π΅ΠΌΡ, ΡΠ΅ΡΡΠ½ΠΎ Π³ΠΎΠ²ΠΎΡΡ, Π΄ΠΎ ΡΠΈΡ ΠΏΠΎΡ Π½Π΅ ΠΎΠΊΠΎΠ½ΡΠ΅Π½Π°, Ρ ΠΎΡΡ ΠΈ Π·Π΄Π΅ΡΡ Π΅ΡΡΡ ΡΡΠΏΠ΅Ρ ΠΈ. ΠΡΠ°ΠΊ, Π²ΠΎΡ ΠΊΠ°ΠΊ Ρ Π½Π°Ρ ΠΏΠΎΠ»ΡΡΠΈΠ»ΠΎΡΡ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ ΡΠΈΠ»ΡΡΡ ΠΏΠΎ jsonb ΠΏΠΎΠ»Ρ Π½Π° ΡΠ΄Π°Π»Π΅Π½Π½ΡΠΉ ΡΠ΅ΡΠ²Π΅Ρ.
explain analyze verbose
SELECT count(1)
FROM fdw_schema.table
WHERE is_active is True
AND created_dt BETWEEN CURRENT_DATE - INTERVAL '7 month'
AND CURRENT_DATE - INTERVAL '6 month'
AND meta @> '{"source":"test"}'::jsonb;
Aggregate (cost=245463.60..245463.61 rows=1 width=8) (actual time=6727.589..6727.590 rows=1 loops=1)
Output: count(1)
-> Foreign Scan on fdw_schema."table" (cost=1100.00..245459.90 rows=1478 width=0) (actual time=16.213..6634.794 rows=1360025 loops=1)
Output: "table".id, "table".is_active, "table".meta, "table".created_dt
Filter: (("table".is_active IS TRUE) AND ("table".created_dt >= (('now'::cstring)::date - '7 mons'::interval)) AND ("table".created_dt <= ((('now'::cstring)::date)::timestamp with time zone - '6 mons'::interval)))
Rows Removed by Filter: 619961
Remote SQL: SELECT created_dt, is_active FROM fdw_schema.table WHERE ((meta @> '{"source": "test"}'::jsonb))
Planning time: 0.747 ms
Execution time: 6727.815 ms
ΠΠΌΠ΅ΡΡΠΎ ΠΎΠΏΠ΅ΡΠ°ΡΠΎΡΠΎΠ² ΡΠΈΠ»ΡΡΡΠ°ΡΠΈΠΈ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΎΠΏΠ΅ΡΠ°ΡΠΎΡ Π½Π°Π»ΠΈΡΠΈΡ ΠΎΠ΄Π½ΠΎΠ³ΠΎ jsonb Π² Π΄ΡΡΠ³ΠΎΠΌ. 7 ΡΠ΅ΠΊΡΠ½Π΄ Π²ΠΌΠ΅ΡΡΠΎ ΠΈΡΡ ΠΎΠ΄Π½ΡΡ 29. ΠΠΎΠΊΠ° ΡΡΠΎ Π΅Π΄ΠΈΠ½ΡΡΠ²Π΅Π½Π½ΡΠΉ ΡΡΠΏΠ΅ΡΠ½ΡΠΉ Π²Π°ΡΠΈΠ°Π½Ρ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ ΡΠΈΠ»ΡΡΡΠΎΠ² ΠΏΠΎ jsonb Π½Π° ΡΠ΄Π°Π»Π΅Π½Π½ΡΠΉ ΡΠ΅ΡΠ²Π΅Ρ, Π½ΠΎ Π·Π΄Π΅ΡΡ Π²Π°ΠΆΠ½ΠΎ ΡΡΠ΅ΡΡΡ ΠΎΠ΄Π½ΠΎ ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΈΠ΅: ΠΌΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ Π²Π΅ΡΡΠΈΡ Π±Π°Π·Ρ 9.6, ΠΎΠ΄Π½Π°ΠΊΠΎ Π΄ΠΎ ΠΊΠΎΠ½ΡΠ° Π°ΠΏΡΠ΅Π»Ρ ΠΏΠ»Π°Π½ΠΈΡΡΠ΅ΠΌ Π·Π°Π²Π΅ΡΡΠΈΡΡ ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΠ΅ ΡΠ΅ΡΡΡ ΠΈ ΠΏΠ΅ΡΠ΅Π΅Ρ Π°ΡΡ Π½Π° 12 Π²Π΅ΡΡΠΈΡ. ΠΠ°ΠΊ ΠΎΠ±Π½ΠΎΠ²ΠΈΠΌΡΡ, Π½Π°ΠΏΠΈΡΠ΅ΠΌ, ΠΊΠ°ΠΊ ΡΡΠΎ ΠΏΠΎΠ²Π»ΠΈΡΠ»ΠΎ, Π²Π΅Π΄Ρ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ, Π½Π° ΠΊΠΎΡΠΎΡΡΠ΅ ΠΌΠ½ΠΎΠ³ΠΎ Π½Π°Π΄Π΅ΠΆΠ΄, Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎ ΠΌΠ½ΠΎΠ³ΠΎ: json_path, Π½ΠΎΠ²ΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ CTE, push down (ΡΡΡΠ΅ΡΡΠ²ΡΡΡΠΈΠΉ Ρ 10 Π²Π΅ΡΡΠΈΠΈ). ΠΡΠ΅Π½Ρ Ρ ΠΎΡΠ΅ΡΡΡ ΡΠΊΠΎΡΠ΅Π΅ ΠΏΠΎΠΏΡΠΎΠ±ΠΎΠ²Π°ΡΡ.
Finish him
ΠΡ ΠΏΡΠΎΠ²Π΅ΡΠΈΠ»ΠΈ, ΠΊΠ°ΠΊ ΠΊΠ°ΠΆΠ΄ΠΎΠ΅ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ Π²Π»ΠΈΡΠ΅Ρ Π½Π° ΡΠΊΠΎΡΠΎΡΡΡ Π·Π°ΠΏΡΠΎΡΠ° ΠΏΠΎ ΠΎΡΠ΄Π΅Π»ΡΠ½ΠΎΡΡΠΈ. ΠΠ°Π²Π°ΠΉΡΠ΅ ΡΠ΅ΠΏΠ΅ΡΡ ΠΏΠΎΡΠΌΠΎΡΡΠΈΠΌ, ΡΡΠΎ Π±ΡΠ΄Π΅Ρ, ΠΊΠΎΠ³Π΄Π° Π²ΡΠ΅ ΡΡΠΈ ΡΠΈΠ»ΡΡΡΠ° Π±ΡΠ΄ΡΡ Π½Π°ΠΏΠΈΡΠ°Π½Ρ ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎ.
explain analyze verbose
SELECT count(1)
FROM fdw_schema.table
WHERE is_active = True
AND created_dt >= (SELECT CURRENT_DATE::timestamptz - INTERVAL '7 month')
AND created_dt <(SELECT CURRENT_DATE::timestamptz - INTERVAL '6 month')
AND meta @> '{"source":"test"}'::jsonb;
Aggregate (cost=322041.51..322041.52 rows=1 width=8) (actual time=2278.867..2278.867 rows=1 loops=1)
Output: count(1)
InitPlan 1 (returns $0)
-> Result (cost=0.00..0.02 rows=1 width=8) (actual time=0.010..0.010 rows=1 loops=1)
Output: ((('now'::cstring)::date)::timestamp with time zone - '7 mons'::interval)
InitPlan 2 (returns $1)
-> Result (cost=0.00..0.02 rows=1 width=8) (actual time=0.003..0.003 rows=1 loops=1)
Output: ((('now'::cstring)::date)::timestamp with time zone - '6 mons'::interval)
-> Foreign Scan on fdw_schema."table" (cost=100.02..322041.41 rows=25 width=0) (actual time=8.597..2153.809 rows=1360025 loops=1)
Output: "table".id, "table".is_active, "table".meta, "table".created_dt
Remote SQL: SELECT NULL FROM fdw_schema.table WHERE (is_active) AND ((created_dt >= $1::timestamp with time zone)) AND ((created_dt < $2::timestamp with time zone)) AND ((meta @> '{"source": "test"}'::jsonb))
Planning time: 0.820 ms
Execution time: 2279.087 ms
ΠΠ°, Π·Π°ΠΏΡΠΎΡ Π²ΡΠ³Π»ΡΠ΄ΠΈΡ ΡΠ»ΠΎΠΆΠ½Π΅Π΅, ΡΡΠΎ Π²ΡΠ½ΡΠΆΠ΄Π΅Π½Π½Π°Ρ ΠΏΠ»Π°ΡΠ°, Π½ΠΎ ΡΠΊΠΎΡΠΎΡΡΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΡΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ 2 ΡΠ΅ΠΊΡΠ½Π΄Ρ, ΡΡΠΎ Π±ΠΎΠ»Π΅Π΅ ΡΠ΅ΠΌ Π² 10 ΡΠ°Π· Π±ΡΡΡΡΠ΅Π΅! Π ΡΡΠΎ ΠΌΡ Π³ΠΎΠ²ΠΎΡΠΈΠΌ ΠΎ ΠΏΡΠΎΡΡΠΎΠΌ Π·Π°ΠΏΡΠΎΡΠ΅ ΠΊ ΠΎΡΠ½ΠΎΡΠΈΡΠ΅Π»ΡΠ½ΠΎ Π½Π΅Π±ΠΎΠ»ΡΡΠΎΠΌΡ Π½Π°Π±ΠΎΡΡ Π΄Π°Π½Π½ΡΡ . ΠΠ° ΡΠ΅Π°Π»ΡΠ½ΡΡ Π·Π°ΠΏΡΠΎΡΠ°Ρ ΠΌΡ ΠΏΠΎΠ»ΡΡΠ°Π»ΠΈ ΠΏΡΠΈΡΠΎΡΡ Π΄ΠΎ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΡ ΡΠΎΡΠ΅Π½ ΡΠ°Π·.
ΠΠΎΠ΄Π²Π΅Π΄Π΅ΠΌ ΠΈΡΠΎΠ³ΠΈ: Π΅ΡΠ»ΠΈ Π²Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΠ΅ PostgreSQL Ρ FDW, Π²ΡΠ΅Π³Π΄Π° ΠΏΡΠΎΠ²Π΅ΡΡΠΉΡΠ΅, Π²ΡΠ΅ Π»ΠΈ ΡΠΈΠ»ΡΡΡΡ ΠΎΡΠΏΡΠ°Π²Π»ΡΡΡΡΡ Π½Π° ΡΠ΄Π°Π»Π΅Π½Π½ΡΠΉ ΡΠ΅ΡΠ²Π΅Ρ, ΠΈ Π±ΡΠ΄Π΅Ρ Π²Π°ΠΌ ΡΡΠ°ΡΡΡΠ΅β¦ ΠΠΎ ΠΊΡΠ°ΠΉΠ½Π΅ΠΉ ΠΌΠ΅ΡΠ΅, ΠΏΠΎΠΊΠ° Π²Ρ Π½Π΅ Π΄ΠΎΠΉΠ΄Π΅ΡΠ΅ Π΄ΠΎ Π΄ΠΆΠΎΠΉΠ½ΠΎΠ² ΠΌΠ΅ΠΆΠ΄Ρ ΡΠ°Π±Π»ΠΈΡΠ°ΠΌΠΈ Ρ ΡΠ°Π·Π½ΡΡ ΡΠ΅ΡΠ²Π΅ΡΠΎΠ². ΠΠΎ ΡΡΠΎ ΡΠΆΠ΅ ΠΈΡΡΠΎΡΠΈΡ Π΄Π»Ρ Π΅ΡΠ΅ ΠΎΠ΄Π½ΠΎΠΉ ΡΡΠ°ΡΡΠΈ.
Π‘ΠΏΠ°ΡΠΈΠ±ΠΎ Π·Π° Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅! ΠΡΠ΄Ρ ΡΠ°Π΄ ΡΡΠ»ΡΡΠ°ΡΡ Π²ΠΎΠΏΡΠΎΡΡ, ΠΊΠΎΠΌΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ, Π° ΡΠ°ΠΊΠΆΠ΅ ΠΈΡΡΠΎΡΠΈΠΈ ΠΎ Π²Π°ΡΠ΅ΠΌ ΠΎΠΏΡΡΠ΅ Π² ΠΊΠΎΠΌΠΌΠ΅Π½ΡΠ°ΡΠΈΡΡ
.
ΠΡΡΠΎΡΠ½ΠΈΠΊ: habr.com