{"id":457934,"date":"2025-04-29T09:21:42","date_gmt":"2025-04-29T09:21:42","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=457934"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=457934","title":{"rendered":"<span>Apache Spark Catalyst: \u0441\u0435\u043a\u0440\u0435\u0442\u044b \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0437\u043d\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 Data Engineer<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2b9\/4a7\/16a\/2b94a716abdc9824031f351fa507084c.png\" width=\"1200\" height=\"675\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/2b9\/4a7\/16a\/2b94a716abdc9824031f351fa507084c.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2b9\/4a7\/16a\/2b94a716abdc9824031f351fa507084c.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u041a\u0443\u0447\u0435\u0440\u043e\u0432 \u0410\u043d\u0434\u0440\u0435\u0439 \u0438 \u044f Lead Data Engineer \u0441 \u0431\u043e\u043b\u0435\u0435 \u0447\u0435\u043c 7-\u043b\u0435\u0442\u043d\u0438\u043c \u043e\u043f\u044b\u0442\u043e\u043c \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 BigData. \u042f \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043d\u0430\u0434 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432\u044b\u0441\u043e\u043a\u043e\u043d\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0445 Spark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0432 X5 Retail Group, Beeline, RaiffeisenBank, \u0433\u0434\u0435 \u043c\u044b \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043b\u0438 \u043f\u0435\u0442\u0430\u0431\u0430\u0439\u0442\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043c\u044b \u0434\u0430\u043d\u043d\u044b\u0445.  \u0420\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u044f\u0441\u044c \u0441 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u044f \u0443\u0431\u0435\u0434\u0438\u043b\u0441\u044f, \u0447\u0442\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u044b Catalyst \u2014 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u043d\u0430\u0432\u044b\u043a \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e Data Engineer, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0435\u0433\u043e \u0441\u043e Spark.  <\/p>\n<h3>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435: \u043f\u043e\u0447\u0435\u043c\u0443 Catalyst \u0442\u0430\u043a \u0432\u0430\u0436\u0435\u043d?<\/h3>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435, \u0447\u0442\u043e \u0432\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u0441\u043b\u043e\u0436\u043d\u044b\u0439 SQL-\u0437\u0430\u043f\u0440\u043e\u0441 \u0441 \u043f\u044f\u0442\u044c\u044e JOIN-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c\u0438 \u0438 \u0434\u0435\u0441\u044f\u0442\u043a\u0430\u043c\u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432. \u041a\u0430\u043a Apache Spark \u0440\u0435\u0448\u0430\u0435\u0442, \u0432 \u043a\u0430\u043a\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u044d\u0442\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438? \u041a\u0430\u043a\u0438\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043f\u0435\u0440\u0432\u044b\u043c\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0442\u044c? \u041a\u0430\u043a\u0438\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0440\u0430\u043d\u044c\u0448\u0435? \u0412\u0441\u0435\u043c\u0438 \u044d\u0442\u0438\u043c\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f\u043c\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u00a0<strong>Catalyst<\/strong>\u00a0\u2014 \u043c\u043e\u0437\u0433\u043e\u0432\u043e\u0439 \u0446\u0435\u043d\u0442\u0440 Apache Spark.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0435\u0433\u043e Data Engineer \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 Catalyst \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0430\u0436\u043d\u043e \u043f\u043e \u0442\u0440\u0435\u043c \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c:<\/p>\n<ol>\n<li>\n<p><strong>\u041e\u0442\u043b\u0430\u0434\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432<\/strong>: \u041a\u043e\u0433\u0434\u0430 \u0432\u0430\u0448 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u043e\u0432 \u0432\u043c\u0435\u0441\u0442\u043e \u043c\u0438\u043d\u0443\u0442, \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043b\u043e\u0433\u0438\u043a\u0438 Catalyst \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u0439\u0442\u0438 \u043f\u0440\u0438\u0447\u0438\u043d\u0443.<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438<\/strong>: \u0417\u043d\u0430\u044f, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440, \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u0434.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439<\/strong>: Spark \u043d\u0435 \u0432\u0441\u0435\u0441\u0438\u043b\u0435\u043d \u2014 \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u0432\u0430\u043c \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043f\u043e\u043c\u043e\u0433\u0430\u0442\u044c Catalyst \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u0432\u044b\u0431\u043e\u0440.<\/p>\n<\/li>\n<\/ol>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e Catalyst \u0438 \u043f\u043e\u043a\u0430\u0436\u0435\u043c, \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<h3>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 Catalyst?<\/h3>\n<p>Catalyst \u2014 \u044d\u0442\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 Apache Spark, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0432\u044b\u0441\u043e\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 (SQL, DataFrame API) \u0432 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u043f\u043b\u0430\u043d\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. \u041e\u043d \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u0432 Spark SQL \u0438 \u0441\u0442\u0430\u043b \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0449\u0438\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432\u0441\u0435\u0439 \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u044b Spark.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7b0\/27f\/512\/7b027f5126d247a1c142975e984e2f3f.png\" width=\"620\" height=\"278\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/7b0\/27f\/512\/7b027f5126d247a1c142975e984e2f3f.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7b0\/27f\/512\/7b027f5126d247a1c142975e984e2f3f.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u043e\u0432 SQL, Catalyst:<\/p>\n<ul>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 (Parquet, CSV, JDBC \u0438 \u0442.\u0434.)<\/p>\n<\/li>\n<li>\n<p>\u0410\u0434\u0430\u043f\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u044f\u0437\u044b\u043a\u043e\u0432\u044b\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 Scala \u0434\u043b\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u043e\u0441\u0442\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0435\u043c\u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443 \u0432\u0430\u0436\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c:\u00a0<strong>Catalyst \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044e, \u043d\u043e \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0441\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0432\u0430\u0448\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445<\/strong>. \u0412\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0441\u043b\u043e\u0435\u043c \u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440 \u0432 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f\u0445.<\/p>\n<h3>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 Catalyst: \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b<\/h3>\n<p>Catalyst \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u043d \u043a\u0430\u043a \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u0438\u0437 \u0447\u0435\u0442\u044b\u0440\u0435\u0445 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u044d\u0442\u0430\u043f\u043e\u0432, \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u043d\u043e\u0441\u0438\u0442 \u0441\u0432\u043e\u0439 \u0432\u043a\u043b\u0430\u0434 \u0432 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.  <\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1fa\/ef0\/7c1\/1faef07c1b0c9c31f3b92705ed14171e.png\" alt=\"\u041f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 Catalyst\" title=\"\u041f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 Catalyst\" width=\"581\" height=\"72\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/1fa\/ef0\/7c1\/1faef07c1b0c9c31f3b92705ed14171e.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1fa\/ef0\/7c1\/1faef07c1b0c9c31f3b92705ed14171e.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 Catalyst<\/figcaption><\/div>\n<\/figure>\n<h4>1. \u0410\u043d\u0430\u043b\u0438\u0437 \u0438 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043f\u043b\u0430\u043d\u0430<\/h4>\n<p>\u041d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0430\u043d\u0430\u043b\u0438\u0437\u0430 Catalyst \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 SQL-\u0437\u0430\u043f\u0440\u043e\u0441 \u0438\u043b\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 DataFrame \u0432\u00a0<strong>\u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0435 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0434\u0435\u0440\u0435\u0432\u043e (AST)<\/strong>, \u0433\u0434\u0435 \u043a\u0430\u0436\u0434\u044b\u0439 \u0443\u0437\u0435\u043b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e (SELECT, JOIN, WHERE) \u0438\u043b\u0438 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430:<\/p>\n<pre><code class=\"sql\">SELECT name FROM users WHERE age &gt; 30<\/code><\/pre>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f\u00a0<strong>\u043d\u0435\u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043d\u044b\u0439 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043b\u0430\u043d<\/strong>:<\/p>\n<pre><code class=\"scala\">Project ['name] +- Filter ['age &gt; 30]    +- UnresolvedRelation [users]<\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c Catalyst \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u00a0<strong>\u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0441\u0441\u044b\u043b\u043e\u043a<\/strong>:<\/p>\n<ol>\n<li>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b\u00a0<code>users<\/code>\u00a0\u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0445\u043e\u0434\u0438\u0442 \u043a\u043e\u043b\u043e\u043d\u043a\u0438\u00a0<code>name<\/code>\u00a0\u0438\u00a0<code>age<\/code>\u00a0\u0432 \u0441\u0445\u0435\u043c\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b<\/p>\n<\/li>\n<li>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0442\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f\u00a0<strong>\u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043d\u044b\u0439 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043b\u0430\u043d<\/strong>:<\/p>\n<pre><code class=\"scala\">Project [name#12] +- Filter (age#13 &gt; 30)    +- Relation[name#12, age#13, ...] parquet<\/code><\/pre>\n<p>\u0414\u043b\u044f Data Engineer \u0432\u0430\u0436\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c:\u00a0<strong>\u0438\u043c\u0435\u043d\u043d\u043e \u043d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u043e\u0448\u0438\u0431\u043a\u0438 \u0442\u0438\u043f\u0430\u00a0<\/strong><code><strong>AnalysisException<\/strong><\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043d\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0442\u0430\u0431\u043b\u0438\u0446 \u0438\u043b\u0438 \u043a\u043e\u043b\u043e\u043d\u043e\u043a.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5d4\/4e6\/7b8\/5d44e67b881b871b5af1d047d6c1e356.png\" alt=\"\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u0434\u0435\u0440\u0435\u0432\u043e AST\" title=\"\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u0434\u0435\u0440\u0435\u0432\u043e AST\" width=\"511\" height=\"521\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/5d4\/4e6\/7b8\/5d44e67b881b871b5af1d047d6c1e356.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5d4\/4e6\/7b8\/5d44e67b881b871b5af1d047d6c1e356.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u0434\u0435\u0440\u0435\u0432\u043e AST<\/figcaption><\/div>\n<\/figure>\n<h4>2. \u041b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f: \u043f\u0440\u0430\u0432\u0438\u043b\u0430 (RBO)<\/h4>\n<p>\u041d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 Catalyst \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442 \u0431\u043e\u043b\u0435\u0435 50 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0445 \u043f\u0440\u0430\u0432\u0438\u043b \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u044f \u043f\u043b\u0430\u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u042d\u0442\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u044b \u043d\u0430 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u0445 \u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0430\u043b\u0433\u0435\u0431\u0440\u044b.<\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u043f\u0440\u0430\u0432\u0438\u043b:<\/p>\n<h3>\u0423\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439<\/h3>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0430\u0432\u0438\u043b\u043e\u00a0<strong>Constant Folding<\/strong>\u00a0\u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430\u043c\u0438:<\/p>\n<pre><code class=\"scala\">Filter (age &gt; 25 + 5) \u2192 Filter (age &gt; 30)<\/code><\/pre>\n<h3>\u041f\u0435\u0440\u0435\u043d\u043e\u0441 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432<\/h3>\n<p>\u041f\u0440\u0430\u0432\u0438\u043b\u043e\u00a0<strong>Predicate Pushdown<\/strong>\u00a0\u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0435\u0442 \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0431\u043b\u0438\u0436\u0435 \u043a \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u043c \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code class=\"scala\">\/\/ \u0414\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 Project [name] +- Filter (country = 'US')    +- Join (users.id = orders.user_id)       +- Relation [users]       +- Relation [orders]  \/\/ \u041f\u043e\u0441\u043b\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 Project [name] +- Join (users.id = orders.user_id)    +- Filter (country = 'US')       +- Relation [users]    +- Relation [orders]<\/code><\/pre>\n<p>\u042d\u0442\u043e \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0430\u0436\u043d\u0430\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f: \u0444\u0438\u043b\u044c\u0442\u0440\u044b, \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0435 \u0434\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439, \u043c\u043e\u0433\u0443\u0442 \u0440\u0430\u0434\u0438\u043a\u0430\u043b\u044c\u043d\u043e \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<h3>\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439<\/h3>\n<p>\u041f\u0440\u0430\u0432\u0438\u043b\u043e\u00a0<strong>ProjectionElimination<\/strong>\u00a0\u0443\u0431\u0438\u0440\u0430\u0435\u0442 \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435 \u043f\u0440\u043e\u0435\u043a\u0446\u0438\u0438:<\/p>\n<pre><code class=\"scala\">Project (columns) (Project (same_columns) (child)) \u2192 Project (columns) (child)<\/code><\/pre>\n<p>\u0414\u043b\u044f Data Engineer:\u00a0<strong>\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u2014 \u044d\u0442\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0431\u0435\u0437 \u0443\u0447\u0435\u0442\u0430 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0435\u0439 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445<\/strong>. \u041e\u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442 \u043e\u0431\u0449\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0442 \u043a \u0431\u043e\u043b\u0435\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u043c\u0443 \u043f\u043b\u0430\u043d\u0443.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u0434\u0430 Catalyst, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0435\u0433\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u043e:<\/p>\n<pre><code class=\"scala\">\/\/ \u041f\u0440\u0430\u0432\u0438\u043b\u043e \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432 object CombineFilters extends Rule[LogicalPlan] {   def apply(plan: LogicalPlan): LogicalPlan = plan transform {     case Filter(cond1, Filter(cond2, child)) =&gt;       Filter(And(cond1, cond2), child)   } }<\/code><\/pre>\n<h4>3. \u0424\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u043d\u0430\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f (CBO)<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 Catalyst \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f JOIN \u0443 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432:<\/p>\n<ul>\n<li>\n<p><strong>BroadcastHashJoin<\/strong>: \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u043d\u0430 \u0432\u0441\u0435 \u0443\u0437\u043b\u044b (\u0431\u044b\u0441\u0442\u0440\u044b\u0439, \u043d\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442 RAM = \u043e\u0431\u044a\u0435\u043c \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c\u043e\u0433\u043e DataFrame \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c executor \u0438 driver)<\/p>\n<\/li>\n<li>\n<p><strong>SortMergeJoin<\/strong>: \u0441\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u043e\u0431\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0438 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 (\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0446)<\/p>\n<\/li>\n<li>\n<p><strong>ShuffleHashJoin<\/strong>: \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0445\u0435\u0448-\u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0434\u043b\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f (\u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442)<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1c8\/f26\/a6f\/1c8f26a6fd359bec949ee0978dcc6504.png\" width=\"961\" height=\"432\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/1c8\/f26\/a6f\/1c8f26a6fd359bec949ee0978dcc6504.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1c8\/f26\/a6f\/1c8f26a6fd359bec949ee0978dcc6504.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0417\u0434\u0435\u0441\u044c Catalyst \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u00a0<strong>Cost-Based Optimizer (CBO)<\/strong>\u00a0\u2014 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u0435\u0442 \u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043f\u043b\u0430\u043d\u043e\u0432 \u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439. CBO \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442:<\/p>\n<ol>\n<li>\n<p><strong>\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0434\u0430\u043d\u043d\u044b\u0445<\/strong>\u00a0(\u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u0442\u0440\u043e\u043a, \u0440\u0430\u0437\u043c\u0435\u0440\u044b \u0442\u0430\u0431\u043b\u0438\u0446)<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u0430\u0440\u0434\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u043b\u043e\u043d\u043e\u043a<\/strong>\u00a0(\u0447\u0438\u0441\u043b\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439)<\/p>\n<\/li>\n<li>\n<p><strong>\u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445<\/strong>\u00a0(\u0447\u0435\u0440\u0435\u0437 \u0433\u0438\u0441\u0442\u043e\u0433\u0440\u0430\u043c\u043c\u044b)<\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u043b\u044f \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b CBO\u00a0<strong>\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443<\/strong>:<\/p>\n<pre><code class=\"sql\">-- \u0421\u0431\u043e\u0440 \u043e\u0431\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u044b ANALYZE TABLE orders COMPUTE STATISTICS;  -- \u0421\u0431\u043e\u0440 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u043f\u043e \u043a\u043e\u043b\u043e\u043d\u043a\u0430\u043c ANALYZE TABLE orders COMPUTE STATISTICS FOR COLUMNS order_id, customer_id;<\/code><\/pre>\n<p>\u0414\u043b\u044f Data Engineer \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c:\u00a0<strong>\u0431\u0435\u0437 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 CBO \u0434\u0435\u043b\u0430\u0435\u0442 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043e\u0446\u0435\u043d\u043e\u043a<\/strong>, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u043a \u043d\u0435\u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u043b\u0430\u043d\u0430\u043c.<\/p>\n<p>\u0424\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043b\u0430\u043d \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0442\u043e\u0434\u00a0<code>explain()<\/code>:<\/p>\n<pre><code class=\"scala\">df.explain() \/\/ \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442: \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043b\u0430\u043d \u0441 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u043c\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430\u043c\u0438  == Physical Plan == AdaptiveSparkPlan isFinalPlan=false +- HashAggregate(keys=[title#18], functions=[sum(cast(label#17 as double))])    +- Exchange hashpartitioning(title#18, 200), ENSURE_REQUIREMENTS, [plan_id=120]       +- HashAggregate(keys=[title#18], functions=[partial_sum(cast(label#17 as double))])          +- Filter (isnotnull(label#17) AND (cast(label#17 as int) = 1))             +- FileScan csv [label#17,title#18] Batched: false, DataFilters: [isnotnull(label#17), (cast(label#17 as int) = 1)], Format: CSV, Location: InMemoryFileIndex(1 paths)[file:\/home\/seidzi\/habr\/csv\/part-00000-2a2f079d-0edc-43aa-aec2-e3b10e69..., PartitionFilters: [], PushedFilters: [IsNotNull(label)], ReadSchema: struct&lt;label:string,title:string&gt;  <\/code><\/pre>\n<h4>4. \u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043a\u043e\u0434\u0430: \u0434\u0432\u0438\u0436\u043e\u043a Tungsten<\/h4>\n<p>\u041d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c \u044d\u0442\u0430\u043f\u0435 Catalyst \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043b\u0430\u043d \u0432 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0439 \u043a\u043e\u0434 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0434\u0432\u0438\u0436\u043a\u0430\u00a0<strong>Tungsten<\/strong>. \u042d\u0442\u043e\u0442 \u0434\u0432\u0438\u0436\u043e\u043a \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0431\u0430\u0439\u0442-\u043a\u043e\u0434 Java \u0434\u043b\u044f \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439, \u043c\u0438\u043d\u0443\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438 Spark.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u00a0<code>age &gt; 30<\/code>\u00a0Catalyst \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"java\">public boolean filter(InternalRow row) {   return row.getInt(1) &gt; 30; \/\/ \u0414\u043e\u0441\u0442\u0443\u043f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043a \u043a\u043e\u043b\u043e\u043d\u043a\u0435 age }<\/code><\/pre>\n<p>Tungsten \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442:<\/p>\n<ol>\n<li>\n<p><strong>\u0412\u0435\u043a\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443<\/strong>: \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u0430\u043c\u0438, \u0430 \u043d\u0435 \u043f\u043e \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0435<\/p>\n<\/li>\n<li>\n<p><strong>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u044c\u044e<\/strong>: \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0441\u0431\u043e\u0440\u043a\u0438 \u043c\u0443\u0441\u043e\u0440\u0430<\/p>\n<\/li>\n<li>\n<p><strong>SIMD-\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438<\/strong>: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430<\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u043b\u044f Data Engineer \u0432\u0430\u0436\u043d\u043e \u0437\u043d\u0430\u0442\u044c:\u00a0<strong>\u044d\u0442\u043e\u0442 \u044d\u0442\u0430\u043f \u0432 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0435\u043f\u0435\u043d\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d<\/strong>, \u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438 \u043e\u0442\u043b\u0430\u0434\u043a\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438.<\/p>\n<h3>\u0424\u0430\u043a\u0442\u043e\u0440\u044b, \u0432\u043b\u0438\u044f\u044e\u0449\u0438\u0435 \u043d\u0430 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c Catalyst<\/h3>\n<p>\u0427\u0442\u043e\u0431\u044b \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 Catalyst, \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u0444\u0430\u043a\u0442\u043e\u0440\u044b \u0432\u043b\u0438\u044f\u044e\u0442 \u043d\u0430 \u0435\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0438\u0437 \u043d\u0438\u0445.<\/p>\n<h4>1. \u0422\u0438\u043f \u0438 \u0444\u043e\u0440\u043c\u0430\u0442 \u0434\u0430\u043d\u043d\u044b\u0445<\/h4>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d96\/764\/c06\/d96764c06d6296227ee94091834e1e6a.png\" width=\"837\" height=\"386\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/d96\/764\/c06\/d96764c06d6296227ee94091834e1e6a.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d96\/764\/c06\/d96764c06d6296227ee94091834e1e6a.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h3>\u041a\u043e\u043b\u043e\u043d\u043e\u0447\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b (Parquet, ORC)<\/h3>\n<p>\u042d\u0442\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u044b \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 Catalyst \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<ul>\n<li>\n<p><strong>\u041f\u0440\u0435\u0434\u0438\u043a\u0430\u0442\u043d\u044b\u0439 \u043f\u0443\u0448\u0434\u0430\u0443\u043d<\/strong>: \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0431\u043b\u043e\u043a\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0440\u043e\u0435\u043a\u0446\u0438\u044f \u043a\u043e\u043b\u043e\u043d\u043e\u043a<\/strong>: \u0447\u0442\u0435\u043d\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0443\u0436\u043d\u044b\u0445 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432<\/p>\n<\/li>\n<li>\n<p><strong>\u0412\u0435\u043a\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f<\/strong>: \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u0430\u043c\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 (\u043d\u0438\u0436\u0435 csv):<\/p>\n<pre><code class=\"python\">parquet_df.where('label=1').groupby('title').agg({\"label\": \"sum\"}).count() # 168190  # CPU times: user 1.67 ms, sys: 7.3 ms, total: 8.97 ms # Wall time: 1.22 s<\/code><\/pre>\n<h3>\u0421\u0442\u0440\u043e\u0447\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b (CSV, JSON)<\/h3>\n<p>\u0414\u043b\u044f \u044d\u0442\u0438\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u044b:<\/p>\n<ul>\n<li>\n<p>CSV \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0447\u0442\u0435\u043d\u0438\u044f \u0438 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 \u0432\u0441\u0435\u0433\u043e \u0444\u0430\u0439\u043b\u0430<\/p>\n<\/li>\n<li>\n<p>JSON \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e\u0435 \u0447\u0442\u0435\u043d\u0438\u0435 \u043a\u043e\u043b\u043e\u043d\u043e\u043a, \u043d\u043e \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435 \u043a\u043e\u043b\u043e\u043d\u043e\u0447\u043d\u044b\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"python\">csv_df.where('label=1').groupby('title').agg({\"label\": \"sum\"}).count() # 168190  # CPU times: user 4.7 ms, sys: 3.09 ms, total: 7.78 ms # Wall time: 2.05 s<\/code><\/pre>\n<p>\u0414\u043b\u044f Data Engineer \u043f\u0440\u044f\u043c\u0430\u044f \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u044f:\u00a0<strong>\u0432\u0441\u0435\u0433\u0434\u0430 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0439\u0442\u0435 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 Parquet \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0437\u0430\u0434\u0430\u0447<\/strong>. \u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u0441\u044f.<\/p>\n<h4>2. \u0420\u0430\u0437\u043c\u0435\u0440 \u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0444\u0430\u0439\u043b\u043e\u0432<\/h4>\n<p>Catalyst \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435\u043c \u0437\u0430\u0434\u0430\u0447 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 \u0438 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439:<\/p>\n<h3>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043c\u0435\u043b\u043a\u0438\u0445 \u0444\u0430\u0439\u043b\u043e\u0432<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 10,000 \u0444\u0430\u0439\u043b\u043e\u0432 \u043f\u043e 1 \u041c\u0411:<\/p>\n<ul>\n<li>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u0444\u0430\u0439\u043b \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b \u043d\u0430 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447 \u0441\u043e\u0441\u0442\u0430\u0432\u044f\u0442 \u0434\u043e 40% \u0432\u0440\u0435\u043c\u0435\u043d\u0438<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435\u0440\u0430\u0432\u043d\u043e\u043c\u0435\u0440\u043d\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0435\u0439<\/p>\n<\/li>\n<\/ul>\n<h3>\u041e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 128-256 \u041c\u0411 \u043d\u0430 \u0444\u0430\u0439\u043b. \u0415\u0441\u043b\u0438 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f HDFS, \u0442\u043e \u0440\u0430\u0437\u043c\u0435\u0440 \u0444\u0430\u0439\u043b\u0430 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0430\u0432\u0435\u043d \u0440\u0430\u0437\u043c\u0435\u0440\u0443 \u0431\u043b\u043e\u043a\u0430.<\/h3>\n<p>\u0414\u043b\u044f Data Engineer \u0432\u0430\u0436\u043d\u043e \u043f\u043e\u043c\u043d\u0438\u0442\u044c:\u00a0<strong>Spark \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0444\u0430\u0439\u043b\u043e\u0432, \u0430 \u043d\u0435 \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u0444\u0430\u0439\u043b\u043e\u0432<\/strong>.<\/p>\n<h4>3. \u0422\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 JOIN-\u043a\u043b\u044e\u0447\u0430\u0445<\/h4>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0432\u044b \u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u0442\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0442\u0438\u043f\u0430\u043c\u0438 \u043a\u043b\u044e\u0447\u0435\u0439, Catalyst \u0432\u044b\u043d\u0443\u0436\u0434\u0435\u043d \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u042d\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a:<\/p>\n<ul>\n<li>\n<p>\u041d\u0435\u044f\u0432\u043d\u044b\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c\u00a0<code>CAST<\/code>\u00a0\u0432 \u043f\u043b\u0430\u043d\u0435<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0439 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Broadcast Join)<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043c\u0435\u0434\u043b\u0435\u043d\u0438\u044e \u0434\u043e 40% \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435\u043c \u043f\u043e \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c \u0442\u0438\u043f\u0430\u043c<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0439\u0442\u0435 \u043f\u043b\u0430\u043d \u0447\u0435\u0440\u0435\u0437\u00a0<code>explain()<\/code>\u00a0\u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439\u00a0<code>cast<\/code>:<\/p>\n<pre><code class=\"scala\">SortMergeJoin [cast(customer_id_int#10 as string)], [customer_id_string#20]<\/code><\/pre>\n<p>\u0414\u043b\u044f Data Engineer:\u00a0<strong>\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0435 \u0442\u0438\u043f\u044b \u0434\u043b\u044f JOIN-\u043a\u043b\u044e\u0447\u0435\u0439<\/strong>\u00a0\u0432\u043e \u0432\u0441\u0435\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u0445. \u0415\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435, \u0434\u0435\u043b\u0430\u0439\u0442\u0435 \u0435\u0433\u043e \u044f\u0432\u043d\u043e:<\/p>\n<pre><code class=\"scala\">val df1Fixed = df1.withColumn(\"customer_id_string\", $\"customer_id_int\".cast(\"string\"))<\/code><\/pre>\n<h4>4. \u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0438 CBO<\/h4>\n<p>CBO \u0432 Catalyst \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u0442\u043e\u0447\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u043e \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<h3>\u041f\u043e\u0447\u0435\u043c\u0443 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u0430<\/h3>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0437\u0430\u043f\u0440\u043e\u0441:<\/p>\n<pre><code class=\"sql\">SELECT * FROM orders o JOIN customers c ON o.customer_id = c.id WHERE c.country = 'US' <\/code><\/pre>\n<p>\u0411\u0435\u0437 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 Catalyst \u043d\u0435 \u0437\u043d\u0430\u0435\u0442:<\/p>\n<ul>\n<li>\n<p>\u0421\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u043e\u043a \u0432\u0435\u0440\u043d\u0435\u0442 \u0444\u0438\u043b\u044c\u0442\u0440\u00a0<code>country = 'US'<\/code><\/p>\n<\/li>\n<li>\n<p>\u0421\u0442\u043e\u0438\u0442 \u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Broadcast \u0434\u043b\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b\u00a0<code>customers<\/code><\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u043a\u043e\u0439 \u043f\u043e\u0440\u044f\u0434\u043e\u043a JOIN \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c<\/p>\n<\/li>\n<\/ul>\n<h4>\u041a\u0430\u043a \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443?<\/h4>\n<p>\u0414\u043b\u044f \u0442\u0430\u0431\u043b\u0438\u0446 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435:<\/p>\n<pre><code class=\"sql\">-- \u0411\u0430\u0437\u043e\u0432\u0430\u044f \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 (\u0440\u0430\u0437\u043c\u0435\u0440, \u0447\u0438\u0441\u043b\u043e \u0441\u0442\u0440\u043e\u043a) ANALYZE TABLE customers COMPUTE STATISTICS;  -- \u0414\u0435\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u043f\u043e \u043a\u043e\u043b\u043e\u043d\u043a\u0430\u043c ANALYZE TABLE customers COMPUTE STATISTICS FOR COLUMNS id, country; <\/code><\/pre>\n<p>\u0414\u043b\u044f DataFrames (\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b):<\/p>\n<pre><code class=\"scala\">\/\/ \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0441\u043e \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u043e\u0439 df.createOrReplaceTempView(\"customers_temp\") spark.sql(\"ANALYZE TABLE customers_temp COMPUTE STATISTICS FOR ALL COLUMNS\") <\/code><\/pre>\n<h4>\u0412\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 CBO<\/h4>\n<p>\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e Catalyst \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 CBO. \u0414\u043b\u044f \u043f\u043e\u043b\u043d\u043e\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"scala\">spark.conf.set(\"spark.sql.cbo.enabled\", true) spark.conf.set(\"spark.sql.cbo.joinReorder.enabled\", true) <\/code><\/pre>\n<p>\u0414\u043b\u044f Data Engineer:\u00a0<strong>\u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u2014 \u043e\u0434\u043d\u0430 \u0438\u0437 \u0433\u043b\u0430\u0432\u043d\u044b\u0445 \u043f\u0440\u0438\u0447\u0438\u043d \u043d\u0435\u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u043b\u0430\u043d\u043e\u0432<\/strong>. \u0412\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0439\u0442\u0435 \u0435\u0451 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0434\u043b\u044f \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u044b\u0445 \u0442\u0430\u0431\u043b\u0438\u0446.<\/p>\n<h4>5. \u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 (Skew)<\/h4>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d36\/e1e\/ed9\/d36e1eed9b3a2a064017eb5ca4a16d55.png\" alt=\"\u041f\u0435\u0440\u0435\u043a\u043e\u0441 \u0434\u0430\u043d\u043d\u044b\u0445\" title=\"\u041f\u0435\u0440\u0435\u043a\u043e\u0441 \u0434\u0430\u043d\u043d\u044b\u0445\" width=\"843\" height=\"244\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/d36\/e1e\/ed9\/d36e1eed9b3a2a064017eb5ca4a16d55.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d36\/e1e\/ed9\/d36e1eed9b3a2a064017eb5ca4a16d55.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption><strong>\u041f\u0435\u0440\u0435\u043a\u043e\u0441 \u0434\u0430\u043d\u043d\u044b\u0445<\/strong><\/figcaption><\/div>\n<\/figure>\n<p>\u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0439 \u0434\u043b\u044f Catalyst \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f\u00a0<strong>\u043f\u0435\u0440\u0435\u043a\u043e\u0441 \u0434\u0430\u043d\u043d\u044b\u0445<\/strong>\u00a0(skew) \u2014 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f, \u043a\u043e\u0433\u0434\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043a\u043b\u044e\u0447\u0435\u0439 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044e\u0442\u0441\u044f \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0447\u0430\u0449\u0435 \u0434\u0440\u0443\u0433\u0438\u0445.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0435\u0442\u0438 \u0443 10% \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c 90% \u0432\u0441\u0435\u0445 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u043e\u0432. \u041f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 JOIN \u044d\u0442\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u043c:<\/p>\n<h3>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b skew-\u0434\u0430\u043d\u043d\u044b\u0445<\/h3>\n<ol>\n<li>\n<p><strong>\u041d\u0435\u0440\u0430\u0432\u043d\u043e\u043c\u0435\u0440\u043d\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0435\u0439<\/strong>: \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0432 10-100 \u0440\u0430\u0437 \u0434\u043e\u043b\u044c\u0448\u0435 \u0434\u0440\u0443\u0433\u0438\u0445<\/p>\n<\/li>\n<li>\n<p><strong>\u0420\u0438\u0441\u043a OOM<\/strong>: \u0443\u0437\u0435\u043b \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u0447\u0435\u0440\u043f\u0430\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c \u043f\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u0431\u0449\u0435\u0435 \u0437\u0430\u043c\u0435\u0434\u043b\u0435\u043d\u0438\u0435<\/strong>: \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043e \u0441\u0430\u043c\u043e\u0439 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439<\/p>\n<\/li>\n<\/ol>\n<h3>\u041c\u0435\u0442\u043e\u0434\u044b \u0431\u043e\u0440\u044c\u0431\u044b \u0441 \u043f\u0435\u0440\u0435\u043a\u043e\u0441\u043e\u043c<\/h3>\n<p>\u0415\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432 \u043a \u0440\u0435\u0448\u0435\u043d\u0438\u044e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b:<\/p>\n<ol>\n<li>\n<p><strong>\u0410\u0434\u0430\u043f\u0442\u0438\u0432\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 (AQE)<\/strong>\u00a0(\u0441 Spark 3.0):<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"scala\">\/\/ \u0412\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 AQE \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0441\u0430 spark.conf.set(\"spark.sql.adaptive.enabled\", true) spark.conf.set(\"spark.sql.adaptive.skewJoin.enabled\", true) <\/code><\/pre>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/889\/7c6\/ae5\/8897c6ae50644cd8a094e87da5559af5.png\" width=\"1080\" height=\"438\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/889\/7c6\/ae5\/8897c6ae50644cd8a094e87da5559af5.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/889\/7c6\/ae5\/8897c6ae50644cd8a094e87da5559af5.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p><strong>  2. \u0422\u0435\u0445\u043d\u0438\u043a\u0430 &#171;\u0441\u043e\u043b\u0438&#187; (salting)<\/strong>\u00a0\u2014 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u0430 \u043a \u043a\u043b\u044e\u0447\u0430\u043c:<\/p>\n<pre><code class=\"scala\">\/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u0430 \u043a \u043a\u043b\u044e\u0447\u0443 \u0441 \u043f\u0435\u0440\u0435\u043a\u043e\u0441\u043e\u043c val saltedDF = df.withColumn(\"salt\", (rand() * 10).cast(\"int\"))   .withColumn(\"salted_key\", concat($\"skewed_key\", lit(\"_\"), $\"salt\"))    \/\/ JOIN \u043f\u043e \"\u0441\u043e\u043b\u0435\u043d\u043e\u043c\u0443\" \u043a\u043b\u044e\u0447\u0443 saltedDF.join(otherDF, \"salted_key\") <\/code><\/pre>\n<p>\u0412\u0430\u0436\u043d\u043e \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0447\u0442\u043e &#171;\u0442\u0435\u0445\u043d\u0438\u043a\u0430 \u0441\u043e\u043b\u0438&#187; \u043d\u0435 \u0434\u0430\u0435\u0442 100% \u043f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u0435 \u043a\u043b\u044e\u0447\u0435\u0439, \u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u044f.<\/p>\n<p>\u0414\u043b\u044f Data Engineer:\u00a0<strong>\u043f\u0435\u0440\u0435\u043a\u043e\u0441 \u0434\u0430\u043d\u043d\u044b\u0445 \u2014 \u0441\u0430\u043c\u0430\u044f \u043a\u043e\u0432\u0430\u0440\u043d\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0434\u043b\u044f Spark<\/strong>, \u0442\u0430\u043a \u043a\u0430\u043a \u0435\u0451 \u0447\u0430\u0441\u0442\u043e \u0441\u043b\u043e\u0436\u043d\u043e \u0432\u044b\u044f\u0432\u0438\u0442\u044c \u0434\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433 \u0437\u0430\u0434\u0430\u0447 \u0432 Spark UI \u0434\u043b\u044f \u0432\u044b\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043d\u044b\u0445 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439.<\/p>\n<p>\u041a\u0430\u043a \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043a\u043e\u0441? <\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a3c\/d11\/455\/a3cd114552e485eb5ad201911637c5f3.png\" width=\"1887\" height=\"252\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/a3c\/d11\/455\/a3cd114552e485eb5ad201911637c5f3.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a3c\/d11\/455\/a3cd114552e485eb5ad201911637c5f3.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0437\u0430\u0439\u0442\u0438 \u0432 stage \u0433\u0434\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 Join, \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u043f\u043e \u0441\u0442\u0435\u0439\u0434\u0436\u0443, \u0432 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435 min, avg \u0438 max \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0430\u0432\u043d\u044b, \u043e\u0434\u043d\u0430\u043a\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 \u043f\u0435\u0440\u0435\u043a\u043e\u0441\u043e\u043c(\u043a\u0430\u043a \u043d\u0430 \u0441\u043a\u0440\u0438\u043d\u0435 \u0432\u044b\u0448\u0435) \u0432\u0438\u0434\u0438\u043c \u0447\u0442\u043e max \u0441\u0438\u043b\u044c\u043d\u043e \u0432\u044b\u0448\u0435 \u0447\u0435\u043c \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0435\u0440\u0441\u0435\u043d\u0442\u0438\u043b\u0438.<\/p>\n<h3>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440: \u043f\u043e\u043b\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438<\/h3>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u0430\u043a Catalyst \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0442 SQL \u0434\u043e \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u043e\u0433\u043e \u043a\u043e\u0434\u0430.<\/p>\n<p>\u041f\u0443\u0441\u0442\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441:<\/p>\n<pre><code class=\"sql\">SELECT o.order_id, c.name, SUM(o.amount) AS total_amount FROM orders o JOIN customers c ON o.customer_id = c.id WHERE c.country = 'US' AND o.date BETWEEN '2023-01-01' AND '2023-12-31' GROUP BY o.order_id, c.name; <\/code><\/pre>\n<h4>\u0428\u0430\u0433 1: \u041d\u0435\u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043d\u044b\u0439 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043b\u0430\u043d<\/h4>\n<p>Catalyst \u0441\u0442\u0440\u043e\u0438\u0442 \u043f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0434\u0435\u0440\u0435\u0432\u043e:<\/p>\n<pre><code class=\"scala\">Aggregate ['o.order_id, 'c.name], ['o.order_id, 'c.name, sum('o.amount) AS total_amount] +- Filter ('c.country = 'US' AND 'o.date BETWEEN '2023-01-01' AND '2023-12-31')    +- Join Inner, ('o.customer_id = 'c.id)       :- SubqueryAlias o       :  +- UnresolvedRelation [orders]       +- SubqueryAlias c          +- UnresolvedRelation [customers] <\/code><\/pre>\n<p>\u041c\u0435\u0436\u0434\u0443 1 \u0438 2 \u0448\u0430\u0433\u043e\u043c Catalist \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u044c \u043c\u0435\u0442\u0430\u0441\u0442\u043e\u0440\u0438\u0434\u0436, \u0447\u0442\u043e \u0431\u044b \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u043e \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u043c(\u0435\u0441\u043b\u0438 \u043e\u043d\u0430 \u0435\u0441\u0442\u044c), \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0430\u0431\u043b\u0438\u0446, \u043a\u043e\u043b\u043e\u043d\u043e\u043a, \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439, \u0442\u0438\u043f\u0430 \u043a\u043e\u043b\u043e\u043d\u043e\u043a \u0438 \u0442.\u0434.<\/p>\n<h4>\u0428\u0430\u0433 2: \u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043d\u044b\u0439 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043b\u0430\u043d<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0441\u0441\u044b\u043b\u043e\u043a \u043f\u043b\u0430\u043d \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f:<\/p>\n<pre><code class=\"scala\">Aggregate [order_id#10, name#21], [order_id#10, name#21, sum(amount#12) AS total_amount] +- Filter ((country#22 = US) AND (date#13 &gt;= 2023-01-01) AND (date#13 &lt;= 2023-12-31))    +- Join Inner, (customer_id#11 = id#20)       :- SubqueryAlias o       :  +- Relation[order_id#10,customer_id#11,amount#12,date#13] parquet       +- SubqueryAlias c          +- Relation[id#20,name#21,country#22] parquet <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043a\u0430\u0436\u0434\u0430\u044f \u043a\u043e\u043b\u043e\u043d\u043a\u0430 \u0438\u043c\u0435\u0435\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 (#10, #11 \u0438 \u0442.\u0434.) \u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0442\u0438\u043f.<\/p>\n<h4>\u0428\u0430\u0433 3: \u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043b\u0430\u043d<\/h4>\n<p>Catalyst \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442 \u0433\u043b\u0430\u0432\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<ol>\n<li>\n<p><strong>Predicate Pushdown<\/strong>: \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432 \u043a \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u043c \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<li>\n<p><strong>Column Pruning<\/strong>: \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043d\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u043a\u043e\u043b\u043e\u043d\u043e\u043a<\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u0430\u043a \u0436\u0435 \u0432 Rule-Based System \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0431\u043e\u043b\u0435\u0435 40 \u043f\u0440\u0430\u0432\u0438\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0430\u043a \u0436\u0435 \u043f\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f.<\/p>\n<pre><code class=\"scala\">Aggregate [order_id#10, name#21], [order_id#10, name#21, sum(amount#12) AS total_amount] +- Join Inner, (customer_id#11 = id#20)    :- Filter (date#13 &gt;= 2023-01-01 AND date#13 &lt;= 2023-12-31)    :  +- Relation[order_id#10,customer_id#11,amount#12,date#13] parquet    +- Filter (country#22 = US)       +- Relation[id#20,name#21,country#22] parquet <\/code><\/pre>\n<p>\u0417\u0430\u043c\u0435\u0442\u044c\u0442\u0435, \u0447\u0442\u043e \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u043d\u0430\u0434 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043e JOIN.<\/p>\n<h4>\u0428\u0430\u0433 4: \u0424\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043b\u0430\u043d<\/h4>\n<p>CBO \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u0435\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e:<\/p>\n<pre><code class=\"scala\">== Physical Plan == HashAggregate(keys=[order_id#10, name#21], functions=[sum(amount#12)]) +- Exchange hashpartitioning(order_id#10, name#21, 200)    +- HashAggregate(keys=[order_id#10, name#21], functions=[partial_sum(amount#12)])       +- BroadcastHashJoin [customer_id#11], [id#20], Inner, BuildRight          :- Filter (date#13 &gt;= 2023-01-01 AND date#13 &lt;= 2023-12-31)          :  +- FileScan parquet [order_id#10,customer_id#11,amount#12,date#13]          +- BroadcastExchange HashedRelationBroadcastMode             +- Filter (country#22 = US)                +- FileScan parquet [id#20,name#21,country#22] <\/code><\/pre>\n<p>\u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0432 \u043f\u043b\u0430\u043d\u0435:<\/p>\n<ol>\n<li>\n<p><strong>BroadcastHashJoin<\/strong>: CBO, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u0440\u0435\u0448\u0438\u043b, \u0447\u0442\u043e \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u00a0<code>customers<\/code>\u00a0\u043f\u043e\u0441\u043b\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u00a0<code>country='US'<\/code>\u00a0\u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u043e\u0439 \u0434\u043b\u044f \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0432\u0441\u0435 \u0443\u0437\u043b\u044b<\/p>\n<\/li>\n<li>\n<p><strong>HashAggregate<\/strong>: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0441\u0447\u0435\u0442\u0430 \u0441\u0443\u043c\u043c\u044b<\/p>\n<\/li>\n<li>\n<p><strong>Exchange<\/strong>: \u043e\u0431\u043c\u0435\u043d \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043c\u0435\u0436\u0434\u0443 \u0443\u0437\u043b\u0430\u043c\u0438 \u0434\u043b\u044f \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<\/ol>\n<h4>\u0428\u0430\u0433 5: \u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043a\u043e\u0434\u0430<\/h4>\n<p>\u0414\u043b\u044f \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 Tungsten \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 JVM-\u0431\u0430\u0439\u0442\u043a\u043e\u0434:<\/p>\n<pre><code class=\"sql\">\/\/ \u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u0434\u043b\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430 \u043f\u043e \u0434\u0430\u0442\u0435 public boolean filter(InternalRow row) {   long date = row.getLong(3);   return date &gt;= 20230101L &amp;&amp; date &lt;= 20231231L; }  \/\/ \u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u0434\u043b\u044f \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u0438 public void update(InternalRow row) {   double amount = row.getDouble(2);   sum += amount; } <\/code><\/pre>\n<h4>\u0428\u0430\u0433 6: \u041d\u0430\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438<\/h4>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/36e\/76b\/716\/36e76b71690ae7efe32f93b44cb41399.png\" width=\"445\" height=\"315\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/36e\/76b\/716\/36e76b71690ae7efe32f93b44cb41399.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/36e\/76b\/716\/36e76b71690ae7efe32f93b44cb41399.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412 Spark UI \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u044c:<\/p>\n<ol>\n<li>\n<p>\u0412\u0440\u0435\u043c\u044f, \u0437\u0430\u0442\u0440\u0430\u0447\u0435\u043d\u043d\u043e\u0435 \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u0442\u0430\u043f<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u043b\u0438\u0447\u0438\u0435 \u043f\u0435\u0440\u0435\u043a\u043e\u0441\u0430<\/p>\n<\/li>\n<li>\n<p>\u042d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438\/\u0434\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<\/ol>\n<h3>\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0438 Catalyst<\/h3>\n<p>\u0414\u043b\u044f \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Catalyst Data Engineer \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u043b\u0430\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438:<\/p>\n<h4>1. \u0410\u043d\u0430\u043b\u0438\u0437 \u043f\u043b\u0430\u043d\u043e\u0432 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f<\/h4>\n<pre><code class=\"scala\">\/\/ \u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043f\u043b\u0430\u043d df.explain()  \/\/ \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0441 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u0438 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u043f\u043b\u0430\u043d\u0430\u043c\u0438 df.explain(\"extended\")  \/\/ \u0414\u0435\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0441 \u043c\u0435\u0442\u0440\u0438\u043a\u0430\u043c\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f df.explain(\"formatted\") <\/code><\/pre>\n<h4>2. \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0430<\/h4>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>spark.sql.adaptive.enabled<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0430\u0434\u0430\u043f\u0442\u0438\u0432\u043d\u0443\u044e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 (AQE).<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>true<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0448\u0435\u043d\u043d\u044b\u043c\u0438 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f\u043c\u0438.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>spark.sql.adaptive.coalescePartitions.enabled<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f.<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>true<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 DataFrame.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>spark.sql.adaptive.skewJoin.enabled<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u0435\u0440\u0435\u043a\u043e\u0448\u0435\u043d\u043d\u044b\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439.<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>true<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u043a\u043e\u0441\u0430 \u0432 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>spark.sql.execution.arrow.pyspark.enabled<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 Apache Arrow \u0434\u043b\u044f \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u0435\u0436\u0434\u0443 JVM \u0438 Python.<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>true<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0414\u043b\u044f \u043f\u043e\u0432\u044b\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 PySpark.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>spark.sql.shuffle.partitions<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439 \u0434\u043b\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 shuffle.<\/p>\n<\/td>\n<td>\n<p align=\"left\">200 (\u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043e\u0431\u044a\u0435\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0414\u043b\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u043d\u0430\u0431\u043e\u0440\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>spark.sql.autoBroadcastJoinThreshold<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f Broadcast Join.<\/p>\n<\/td>\n<td>\n<p align=\"left\">10MB (\u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c)<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0414\u043b\u044f \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u043c\u0435\u0436\u0434\u0443 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u043c\u0438 \u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u043c\u0438.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>spark.sql.parquet.enableVectorizedReader<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432\u0435\u043a\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0447\u0442\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u0430\u0442\u0430 Parquet.<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>true<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0414\u043b\u044f \u043f\u043e\u0432\u044b\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0447\u0442\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 Parquet.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>spark.sql.orc.filterPushdown<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044e \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0444\u043e\u0440\u043c\u0430\u0442\u0430 ORC.<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>true<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0414\u043b\u044f \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043c\u0430 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0438 \u0447\u0442\u0435\u043d\u0438\u0438.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<h4>3. SQL-\u0445\u0438\u043d\u0442\u044b \u0434\u043b\u044f \u0440\u0443\u0447\u043d\u043e\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438<\/h4>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u044b, \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0445\u0438\u043d\u0442\u044b \u0434\u043b\u044f \u044f\u0432\u043d\u043e\u0433\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0439:<\/p>\n<pre><code class=\"sql\">-- \u041f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 broadcast \u0442\u0430\u0431\u043b\u0438\u0446\u044b customers SELECT \/*+ BROADCAST(c) *\/ * FROM orders o JOIN customers c ON o.customer_id = c.id  -- \u041f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 sort-merge join SELECT \/*+ MERGE(o, c) *\/ * FROM orders o JOIN customers c ON o.customer_id = c.id  -- \u0417\u0430\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0442\u0430\u0431\u043b\u0438\u0446 SELECT \/*+ LEADING(o, c, p) *\/ * FROM orders o JOIN customers c ON o.customer_id = c.id JOIN products p ON o.product_id = p.id <\/code><\/pre>\n<h4>4. Spark UI \u0434\u043b\u044f \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430<\/h4>\n<p>\u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u044b Spark UI \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u0440\u0430\u0431\u043e\u0442\u044b Catalyst:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/80a\/62f\/42e\/80a62f42e868f0243bea6ce1df1bbcac.png\" width=\"875\" height=\"86\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/80a\/62f\/42e\/80a62f42e868f0243bea6ce1df1bbcac.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/80a\/62f\/42e\/80a62f42e868f0243bea6ce1df1bbcac.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<ol>\n<li>\n<p><strong>Stages<\/strong>: \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0434\u0435\u0442\u0430\u043b\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u044d\u0442\u0430\u043f\u0430<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/98d\/edd\/130\/98dedd130e5777378e91e96051ef271e.png\" width=\"1889\" height=\"427\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/98d\/edd\/130\/98dedd130e5777378e91e96051ef271e.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/98d\/edd\/130\/98dedd130e5777378e91e96051ef271e.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<\/li>\n<li>\n<p><strong>Storage<\/strong>: \u0414\u0430\u043d\u043d\u044b\u0435 \u043e \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043f\u0430\u043c\u044f\u0442\u0438<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ac0\/2d1\/e56\/ac02d1e563ef8375c52c87487540a702.png\" width=\"1908\" height=\"454\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/ac0\/2d1\/e56\/ac02d1e563ef8375c52c87487540a702.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ac0\/2d1\/e56\/ac02d1e563ef8375c52c87487540a702.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<\/li>\n<li>\n<p><strong>Executors<\/strong>: \u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0431 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044f\u043c\u0438<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/531\/2ca\/65c\/5312ca65cad7680011645d4060550141.png\" width=\"1909\" height=\"584\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/531\/2ca\/65c\/5312ca65cad7680011645d4060550141.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/531\/2ca\/65c\/5312ca65cad7680011645d4060550141.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<\/li>\n<li>\n<p><strong>SQL<\/strong>: \u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0438 \u0438\u0445 \u043f\u043b\u0430\u043d\u044b<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/113\/bfd\/463\/113bfd4635479b465dbf9af4b46b1d67.png\" width=\"1184\" height=\"769\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/113\/bfd\/463\/113bfd4635479b465dbf9af4b46b1d67.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/113\/bfd\/463\/113bfd4635479b465dbf9af4b46b1d67.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<\/li>\n<\/ol>\n<h3>\u0427\u0442\u043e \u043d\u043e\u0432\u043e\u0433\u043e \u0432 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 PySpark \u0441 \u0432\u044b\u0445\u043e\u0434\u043e\u043c Spark 3+<\/h3>\n<p>Apache Spark 3.0 \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u0440\u0438\u043d\u0435\u0441\u043b\u0438 \u0440\u0435\u0432\u043e\u043b\u044e\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u0432 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u043d\u044b \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 PySpark. \u042d\u0442\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0434\u0435\u043b\u0430\u044e\u0442 Python-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Spark \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c.<\/p>\n<h4>1. \u0410\u0434\u0430\u043f\u0442\u0438\u0432\u043d\u043e\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 (AQE)<\/h4>\n<p>Adaptive Query Execution (AQE) \u2014 \u044d\u0442\u043e \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u043f\u0440\u043e\u0440\u044b\u0432 \u0432 Spark 3.0, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043b\u0430\u043d\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f\u00a0<strong>\u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b<\/strong>, \u0430 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438.<\/p>\n<h3>\u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 AQE:<\/h3>\n<ol>\n<li>\n<p><strong>\u0414\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439<\/strong>:<\/p>\n<pre><code class=\"python\"># \u0414\u043e Spark 3.0: \u043c\u043d\u043e\u0433\u043e \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439 # \u0421 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439 10 \u041c\u0411 \u0438 1000 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u044f\u043c\u0438 # \u041f\u043e\u0441\u043b\u0435 aggregate \u043c\u043d\u043e\u0433\u0438\u0435 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438 &lt; 1 \u041c\u0411  # \u041f\u043e\u0441\u043b\u0435 Spark 3.0: \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439 spark.conf.set(\"spark.sql.adaptive.enabled\", True) spark.conf.set(\"spark.sql.adaptive.coalescePartitions.enabled\", True) spark.conf.set(\"spark.sql.adaptive.coalescePartitions.minPartitionSize\", \"64m\") <\/code><\/pre>\n<\/li>\n<li>\n<p><strong>\u0414\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f<\/strong>:<\/p>\n<ul>\n<li>\n<p>AQE \u043c\u043e\u0436\u0435\u0442 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c\u00a0<code>SortMergeJoin<\/code>\u00a0\u043d\u0430\u00a0<code>BroadcastHashJoin<\/code>, \u0435\u0441\u043b\u0438 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0442, \u0447\u0442\u043e \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u043f\u043e\u0441\u043b\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u0441\u0442\u0430\u043b\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u043e\u0439.<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"python\"># \u042d\u0442\u043e\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0441 AQE df1.join(df2, \"key\").filter(f.col(\"value\") &gt; 1000).show()  # \u0411\u0435\u0437 AQE: SortMergeJoin (\u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 df2 \u043f\u043e\u0441\u043b\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u0430 &lt; 10 \u041c\u0411) # \u0421 AQE: \u0414\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 BroadcastHashJoin <\/code><\/pre>\n<\/li>\n<li>\n<p><strong>\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u043a\u043e\u0448\u0435\u043d\u043d\u044b\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043a\u043e\u0448\u0435\u043d\u043d\u044b\u0445 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"python\"># \u0412\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0441\u0430 spark.conf.set(\"spark.sql.adaptive.skewJoin.enabled\", True) spark.conf.set(\"spark.sql.adaptive.skewJoin.skewedPartitionFactor\", 5) spark.conf.set(\"spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes\", \"256m\") <\/code><\/pre>\n<\/li>\n<\/ol>\n<h4>2. \u0423\u043b\u0443\u0447\u0448\u0435\u043d\u043d\u0430\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c Pandas UDF<\/h4>\n<p>Pandas UDF (User Defined Functions) \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 Spark 3.x:<\/p>\n<h3>\u041d\u043e\u0432\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438:<\/h3>\n<ol>\n<li>\n<p><strong>\u0423\u043b\u0443\u0447\u0448\u0435\u043d\u043d\u0430\u044f \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 Arrow \u0434\u043b\u044f \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u0435\u0436\u0434\u0443 JVM \u0438 Python<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0445 \u0440\u0430\u0441\u0445\u043e\u0434\u043e\u0432 \u043d\u0430 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043d\u0430 40-60%<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>\u0422\u0438\u043f\u044b PandasUDF \u0441 \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440\u0430\u043c\u0438<\/strong>:<\/p>\n<pre><code class=\"python\"># Spark 2.4: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u0430 @pandas_udf(returnType=DoubleType(), functionType=PandasUDFType.SCALAR)  # Spark 3.0+: \u0447\u0438\u0441\u0442\u044b\u0435 \u0438 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0435 \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440\u044b @pandas_udf(DoubleType())  # \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e SCALAR def multiply(s: pd.Series) -&gt; pd.Series:     return s * 2 <\/code><\/pre>\n<\/li>\n<li>\n<p><strong>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0438\u0442\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0431\u0430\u0442\u0447\u0435\u0439<\/strong>:<\/p>\n<pre><code class=\"python\"># \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0434\u0430\u0442\u0430\u0444\u0440\u0435\u0439\u043c\u043e\u0432 \u0431\u0435\u0437 OOM @pandas_udf(DoubleType()) def process_batch(batch_iter: Iterator[pd.Series]) -&gt; Iterator[pd.Series]:     for batch in batch_iter:         yield batch * 2 <\/code><\/pre>\n<\/li>\n<li>\n<p><strong>\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435 \u0442\u0438\u043f\u044b \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u044b\u0445 \u0438 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0438 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c DataFrames \u0446\u0435\u043b\u0438\u043a\u043e\u043c<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<h3>\u0411\u0435\u043d\u0447\u043c\u0430\u0440\u043a \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 Pandas UDF:<\/h3>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">from pyspark.sql import SparkSession from pyspark.sql.functions import col, expr, pandas_udf, udf from pyspark.sql.types import StringType import timeit import pandas as pd import uuid import matplotlib.pyplot as plt  # \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f Spark def create_spark_session():     return SparkSession.builder \\         .appName(\"UUID Benchmark\") \\         .master(\"local[*]\") \\         .config(\"spark.driver.memory\", \"8g\") \\         .config(\"spark.executor.memory\", \"8g\") \\         .config(\"spark.sql.execution.arrow.pyspark.enabled\", \"true\") \\         .config(\"spark.sql.shuffle.partitions\", \"8\") \\         .getOrCreate()  spark = create_spark_session()  # \u0413\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 def generate_data(num_records):     return spark.range(num_records).cache()  # \u0424\u0443\u043d\u043a\u0446\u0438\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 UUID def uuid4_str():     return str(uuid.uuid4())  @udf(StringType()) def python_udf(_):     return uuid4_str()  @pandas_udf(StringType()) def pandas_vectorized_udf(_: pd.Series) -&gt; pd.Series:     return pd.Series([uuid4_str() for _ in range(len(_))])  # \u0422\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b def test_native(df):     return df.withColumn(\"uuid\", expr(\"uuid()\"))  # \u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f Spark  def test_udf(df, udf_func):     return df.withColumn(\"uuid\", udf_func(col(\"id\")))  # \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f sizes = [100_000, 200_000, 300_000, 400_000, 500_000, 600_000, 700_000, 800_000, 900_000, 1_000_000] trials = 50 results = []  # \u041f\u0440\u043e\u0433\u0440\u0435\u0432 JVM generate_data(10).transform(test_native).count()  for size in sizes:     print(f\"\\n=== \u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0430 {size:,} \u0437\u0430\u043f\u0438\u0441\u044f\u0445 ===\")     df = generate_data(size)          # \u041d\u0430\u0442\u0438\u0432\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f Spark     native_time = timeit.timeit(         lambda: test_native(df).count(),         number=trials     ) \/ trials          # \u041e\u0431\u044b\u0447\u043d\u0430\u044f UDF     udf_time = timeit.timeit(         lambda: test_udf(df, python_udf).count(),         number=trials     ) \/ trials          # Pandas UDF     pandas_udf_time = timeit.timeit(         lambda: test_udf(df, pandas_vectorized_udf).count(),         number=trials     ) \/ trials          results.append((size, native_time, udf_time, pandas_udf_time))     df.unpersist()  # \u0412\u044b\u0432\u043e\u0434 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 print(\"\\n=== \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 UUID ===\") print(f\"{'\u0420\u0430\u0437\u043c\u0435\u0440':&lt;12} {'Spark UUID()':&lt;12} {'Python UDF':&lt;12} {'Pandas UDF':&lt;12} {'UDF\/Spark':&lt;12} {'Pandas\/Spark':&lt;12}\") for size, nt, ut, pt in results:     print(f\"{size:&lt;12,} {nt:.6f}   {ut:.6f}   {pt:.6f}    {ut\/nt:&gt;8.1f}x    {pt\/nt:&gt;8.1f}x\")  # \u0412\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f df_result = pd.DataFrame(results, columns=['Size', 'Spark Native', 'Python UDF', 'Pandas UDF']) df_result.set_index('Size').plot(     kind='bar',     figsize=(12, 6),     logy=True,     title='\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 UUID' ) plt.ylabel('\u0412\u0440\u0435\u043c\u044f (\u0441\u0435\u043a\u0443\u043d\u0434\u044b, log scale)') plt.xlabel('\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439') plt.xticks(rotation=0) plt.tight_layout() plt.savefig('uuid_benchmark.png', dpi=300) plt.show()  spark.stop() <\/code><\/pre>\n<\/div>\n<\/details>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5ff\/1b1\/63e\/5ff1b163e4a3d3b2cc20f537950f1b3e.png\" width=\"1336\" height=\"646\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/5ff\/1b1\/63e\/5ff1b163e4a3d3b2cc20f537950f1b3e.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5ff\/1b1\/63e\/5ff1b163e4a3d3b2cc20f537950f1b3e.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h3>\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432: \u043f\u043e\u0448\u0430\u0433\u043e\u0432\u043e\u0435 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e<\/h3>\n<h4>\u0428\u0430\u0433 1: \u0410\u043d\u0430\u043b\u0438\u0437 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430<\/h4>\n<p>\u041d\u0430\u0447\u043d\u0438\u0442\u0435 \u0441 \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u043f\u043b\u0430\u043d\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"scala\">df.explain(true)  \/\/ \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0432\u0441\u0435 \u043f\u043b\u0430\u043d\u044b: \u043d\u0435\u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043d\u044b\u0439, \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439, \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439, \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0439 <\/code><\/pre>\n<p>\u0418\u0449\u0438\u0442\u0435:<\/p>\n<ul>\n<li>\n<p>\u041d\u0435\u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0435 JOIN-\u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 (SortMergeJoin \u0434\u043b\u044f \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0446)<\/p>\n<\/li>\n<li>\n<p>\u0411\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e Exchange-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 (Shuffle)<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 Predicate Pushdown<\/p>\n<\/li>\n<li>\n<p>\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 CAST \u0432 \u043f\u043b\u0430\u043d\u0435<\/p>\n<\/li>\n<\/ul>\n<h4>\u0428\u0430\u0433 2: \u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445<\/h4>\n<ol>\n<li>\n<p><strong>\u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u044f \u0432 Parquet<\/strong>\u00a0(\u0435\u0441\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 CSV\/JSON):<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"scala\">df.write.parquet(\"optimized_data\") <\/code><\/pre>\n<ol start=\"2\">\n<li>\n<p><strong>\u041f\u0430\u0440\u0442\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u043c \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u043c<\/strong>:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"scala\">df.write.partitionBy(\"date\", \"country\").parquet(\"partitioned_data\") <\/code><\/pre>\n<ol start=\"3\">\n<li>\n<p><strong>\u0421\u0431\u043e\u0440 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438<\/strong>:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"scala\">ANALYZE TABLE orders COMPUTE STATISTICS FOR COLUMNS customer_id, amount; <\/code><\/pre>\n<h4>\u0428\u0430\u0433 3: \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0430<\/h4>\n<pre><code class=\"scala\">\/\/ \u0412\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0439 Catalyst spark.conf.set(\"spark.sql.cbo.enabled\", true) spark.conf.set(\"spark.sql.cbo.joinReorder.enabled\", true) spark.conf.set(\"spark.sql.adaptive.enabled\", true) spark.conf.set(\"spark.sql.adaptive.skewJoin.enabled\", true) <\/code><\/pre>\n<h4>\u0428\u0430\u0433 4: \u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f JOIN-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439<\/h4>\n<ol>\n<li>\n<p><strong>\u0412\u044b\u0431\u043e\u0440 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0430 JOIN<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u041c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0439\u0442\u0435 \u043f\u0435\u0440\u0432\u044b\u043c\u0438<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 JOIN-\u0445\u0438\u043d\u0442\u044b \u0434\u043b\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>Broadcast \u0434\u043b\u044f \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0446<\/strong>:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"scala\">\/\/ \u042f\u0432\u043d\u044b\u0439 broadcast import org.apache.spark.sql.functions.broadcast df1.join(broadcast(df2), \"key\") <\/code><\/pre>\n<ol start=\"3\">\n<li>\n<p><strong>\u0421\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0438\u043f\u043e\u0432 \u043a\u043b\u044e\u0447\u0435\u0439<\/strong>:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"scala\">\/\/ \u042f\u0432\u043d\u043e\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u043e\u0432 val df2WithIntKey = df2.withColumn(\"key_int\", $\"key\".cast(\"int\")) df1.join(df2WithIntKey, df1(\"key\") === df2WithIntKey(\"key_int\")) <\/code><\/pre>\n<h4>\u0428\u0430\u0433 5: \u0411\u043e\u0440\u044c\u0431\u0430 \u0441 \u043f\u0435\u0440\u0435\u043a\u043e\u0441\u043e\u043c \u0434\u0430\u043d\u043d\u044b\u0445<\/h4>\n<ol>\n<li>\n<p><strong>\u041c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433 \u043f\u0435\u0440\u0435\u043a\u043e\u0441\u0430<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 Spark UI \u0434\u043b\u044f \u0432\u044b\u044f\u0432\u043b\u0435\u043d\u0438\u044f &#171;\u0437\u0430\u0434\u0430\u0447-\u0434\u043e\u043b\u0433\u043e\u0436\u0438\u0442\u0435\u043b\u0435\u0439&#187;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0439\u0434\u0438\u0442\u0435 \u043a\u043b\u044e\u0447\u0438 \u0441 \u043d\u0435\u0440\u0430\u0432\u043d\u043e\u043c\u0435\u0440\u043d\u044b\u043c \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435\u043c<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0442\u0435\u0445\u043d\u0438\u043a\u0438 &#171;\u0441\u043e\u043b\u0438&#187;<\/strong><\/p>\n<\/li>\n<\/ol>\n<h4>\u0428\u0430\u0433 6: \u0424\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438<\/h4>\n<ol>\n<li>\n<p><strong>\u041a\u044d\u0448\u0438\u0440\u0443\u0439\u0442\u0435 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b<\/strong>:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"scala\">val intermediateDF = df.filter(complexCondition).cache() <\/code><\/pre>\n<p><strong>    2. \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439<\/strong>:<\/p>\n<pre><code class=\"scala\">\/\/ \u0414\u043b\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0439\u0442\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439 spark.conf.set(\"spark.sql.shuffle.partitions\", 50)  \/\/ \u0414\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0439\u0442\u0435 \u0438\u0445 spark.conf.set(\"spark.sql.shuffle.partitions\", 2000) <\/code><\/pre>\n<p><strong>    3. \u0418\u0437\u0431\u0435\u0433\u0430\u0439\u0442\u0435 UDF, \u0433\u0434\u0435 \u044d\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e<\/strong>:<\/p>\n<pre><code class=\"scala\">\/\/ \u0417\u0430\u043c\u0435\u043d\u044f\u0439\u0442\u0435 UDF \u043d\u0430 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \/\/ \u0412\u043c\u0435\u0441\u0442\u043e: df.filter(myUdf($\"col\")) df.filter(expr(\"array_contains(col, 'value')\")) <\/code><\/pre>\n<h4>\u0428\u0430\u0433 7: \u0418\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432<\/h4>\n<p>\u0421\u0440\u0430\u0432\u043d\u0438\u0442\u0435 \u043f\u043b\u0430\u043d \u0438 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u043e \u0438 \u043f\u043e\u0441\u043b\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<ul>\n<li>\n<p>\u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u044a\u0435\u043c Shuffle-\u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<li>\n<p>\u0427\u0438\u0441\u043b\u043e \u0438 \u0440\u0430\u0437\u043c\u0435\u0440 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u0438<\/p>\n<\/li>\n<\/ul>\n<h3>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/07f\/ae8\/3c4\/07fae83c4d5858db6da76eabf4ee4e70.png\" width=\"1536\" height=\"1024\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/07f\/ae8\/3c4\/07fae83c4d5858db6da76eabf4ee4e70.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/07f\/ae8\/3c4\/07fae83c4d5858db6da76eabf4ee4e70.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>Catalyst \u2014 \u044d\u0442\u043e \u043c\u043e\u0449\u043d\u044b\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u043e\u0432\u044b\u0448\u0430\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 Spark. \u041e\u0434\u043d\u0430\u043a\u043e, \u043a\u0430\u043a \u0438 \u043b\u044e\u0431\u043e\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043e\u043d \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0438 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0440\u0430\u0431\u043e\u0442\u044b.<\/p>\n<h4>\u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0432\u044b\u0432\u043e\u0434\u044b:<\/h4>\n<ol>\n<li>\n<p><strong>\u041f\u043e\u043d\u0438\u043c\u0430\u0439\u0442\u0435, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 Catalyst<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0417\u043d\u0430\u0439\u0442\u0435 \u044d\u0442\u0430\u043f\u044b \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u0418\u0437\u0443\u0447\u0438\u0442\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u0431\u0435\u0440\u0438\u0442\u0435\u0441\u044c \u0432 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044f\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>\u041f\u043e\u043c\u043e\u0433\u0430\u0439\u0442\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0443<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u044b\u0432\u0430\u0439\u0442\u0435 \u0442\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0445\u0438\u043d\u0442\u044b \u0434\u043b\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>\u0411\u0443\u0434\u044c\u0442\u0435 \u0433\u043e\u0442\u043e\u0432\u044b \u043a \u0440\u0443\u0447\u043d\u043e\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0411\u043e\u0440\u044c\u0431\u0430 \u0441 \u043f\u0435\u0440\u0435\u043a\u043e\u0441\u043e\u043c \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u0422\u043e\u043d\u043a\u0430\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0410\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0439\u0442\u0435 \u043f\u043b\u0430\u043d\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u043d\u0438\u0442\u043e\u0440\u044c\u0442\u0435 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u0432 Spark UI<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0431\u0438\u0440\u0430\u0439\u0442\u0435 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>Catalyst \u043d\u0435 \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u0442 \u043e\u043f\u044b\u0442\u043d\u043e\u0433\u043e Data Engineer, \u043d\u043e \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0443, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u0443\u044f \u043c\u043d\u043e\u0433\u0438\u0435 \u0430\u0441\u043f\u0435\u043a\u0442\u044b \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438. \u041f\u043e \u043c\u0435\u0440\u0435 \u0440\u043e\u0441\u0442\u0430 \u0432\u0430\u0448\u0438\u0445 \u0437\u043d\u0430\u043d\u0438\u0439 \u043e Catalyst, \u0440\u0430\u0441\u0442\u0435\u0442 \u0438 \u0432\u0430\u0448\u0430 \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u044b\u0441\u043e\u043a\u043e\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/901078\/\"> https:\/\/habr.com\/ru\/articles\/901078\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><\/figure>\n<p>\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u041a\u0443\u0447\u0435\u0440\u043e\u0432 \u0410\u043d\u0434\u0440\u0435\u0439 \u0438 \u044f Lead Data Engineer \u0441 \u0431\u043e\u043b\u0435\u0435 \u0447\u0435\u043c 7-\u043b\u0435\u0442\u043d\u0438\u043c \u043e\u043f\u044b\u0442\u043e\u043c \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 BigData. \u042f \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043d\u0430\u0434 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432\u044b\u0441\u043e\u043a\u043e\u043d\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0445 Spark-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0432 X5 Retail Group, Beeline, RaiffeisenBank, \u0433\u0434\u0435 \u043c\u044b \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043b\u0438 \u043f\u0435\u0442\u0430\u0431\u0430\u0439\u0442\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043c\u044b \u0434\u0430\u043d\u043d\u044b\u0445.  \u0420\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u044f\u0441\u044c \u0441 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u044f \u0443\u0431\u0435\u0434\u0438\u043b\u0441\u044f, \u0447\u0442\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u044b Catalyst \u2014 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u043d\u0430\u0432\u044b\u043a \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e Data Engineer, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0435\u0433\u043e \u0441\u043e Spark.  <\/p>\n<h3>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435: \u043f\u043e\u0447\u0435\u043c\u0443 Catalyst \u0442\u0430\u043a \u0432\u0430\u0436\u0435\u043d?<\/h3>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435, \u0447\u0442\u043e \u0432\u044b \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u0441\u043b\u043e\u0436\u043d\u044b\u0439 SQL-\u0437\u0430\u043f\u0440\u043e\u0441 \u0441 \u043f\u044f\u0442\u044c\u044e JOIN-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c\u0438 \u0438 \u0434\u0435\u0441\u044f\u0442\u043a\u0430\u043c\u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432. \u041a\u0430\u043a Apache Spark \u0440\u0435\u0448\u0430\u0435\u0442, \u0432 \u043a\u0430\u043a\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u044d\u0442\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438? \u041a\u0430\u043a\u0438\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043f\u0435\u0440\u0432\u044b\u043c\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0442\u044c? \u041a\u0430\u043a\u0438\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0440\u0430\u043d\u044c\u0448\u0435? \u0412\u0441\u0435\u043c\u0438 \u044d\u0442\u0438\u043c\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f\u043c\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u00a0<strong>Catalyst<\/strong>\u00a0\u2014 \u043c\u043e\u0437\u0433\u043e\u0432\u043e\u0439 \u0446\u0435\u043d\u0442\u0440 Apache Spark.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0435\u0433\u043e Data Engineer \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 Catalyst \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0430\u0436\u043d\u043e \u043f\u043e \u0442\u0440\u0435\u043c \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c:<\/p>\n<ol>\n<li>\n<p><strong>\u041e\u0442\u043b\u0430\u0434\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432<\/strong>: \u041a\u043e\u0433\u0434\u0430 \u0432\u0430\u0448 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0447\u0430\u0441\u043e\u0432 \u0432\u043c\u0435\u0441\u0442\u043e \u043c\u0438\u043d\u0443\u0442, \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043b\u043e\u0433\u0438\u043a\u0438 Catalyst \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u0439\u0442\u0438 \u043f\u0440\u0438\u0447\u0438\u043d\u0443.<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438<\/strong>: \u0417\u043d\u0430\u044f, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440, \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u0434.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439<\/strong>: Spark \u043d\u0435 \u0432\u0441\u0435\u0441\u0438\u043b\u0435\u043d \u2014 \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u0432\u0430\u043c \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043f\u043e\u043c\u043e\u0433\u0430\u0442\u044c Catalyst \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u0432\u044b\u0431\u043e\u0440.<\/p>\n<\/li>\n<\/ol>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e Catalyst \u0438 \u043f\u043e\u043a\u0430\u0436\u0435\u043c, \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<h3>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 Catalyst?<\/h3>\n<p>Catalyst \u2014 \u044d\u0442\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 Apache Spark, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0432\u044b\u0441\u043e\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 (SQL, DataFrame API) \u0432 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u043f\u043b\u0430\u043d\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. \u041e\u043d \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u0432 Spark SQL \u0438 \u0441\u0442\u0430\u043b \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0449\u0438\u043c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432\u0441\u0435\u0439 \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u044b Spark.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u043e\u0432 SQL, Catalyst:<\/p>\n<ul>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 (Parquet, CSV, JDBC \u0438 \u0442.\u0434.)<\/p>\n<\/li>\n<li>\n<p>\u0410\u0434\u0430\u043f\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u044f\u0437\u044b\u043a\u043e\u0432\u044b\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 Scala \u0434\u043b\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u043e\u0441\u0442\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0435\u043c\u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443 \u0432\u0430\u0436\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c:\u00a0<strong>Catalyst \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044e, \u043d\u043e \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0441\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0432\u0430\u0448\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445<\/strong>. \u0412\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0441\u043b\u043e\u0435\u043c \u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440 \u0432 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f\u0445.<\/p>\n<h3>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 Catalyst: \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b<\/h3>\n<p>Catalyst \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u043d \u043a\u0430\u043a \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u0438\u0437 \u0447\u0435\u0442\u044b\u0440\u0435\u0445 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u044d\u0442\u0430\u043f\u043e\u0432, \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u043d\u043e\u0441\u0438\u0442 \u0441\u0432\u043e\u0439 \u0432\u043a\u043b\u0430\u0434 \u0432 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.  <\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u041f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 Catalyst<\/figcaption><\/div>\n<\/figure>\n<h4>1. \u0410\u043d\u0430\u043b\u0438\u0437 \u0438 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043f\u043b\u0430\u043d\u0430<\/h4>\n<p>\u041d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0430\u043d\u0430\u043b\u0438\u0437\u0430 Catalyst \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 SQL-\u0437\u0430\u043f\u0440\u043e\u0441 \u0438\u043b\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 DataFrame \u0432\u00a0<strong>\u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0435 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0434\u0435\u0440\u0435\u0432\u043e (AST)<\/strong>, \u0433\u0434\u0435 \u043a\u0430\u0436\u0434\u044b\u0439 \u0443\u0437\u0435\u043b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e (SELECT, JOIN, WHERE) \u0438\u043b\u0438 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430:<\/p>\n<pre><code class=\"sql\">SELECT name FROM users WHERE age &gt; 30<\/code><\/pre>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f\u00a0<strong>\u043d\u0435\u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043d\u044b\u0439 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043b\u0430\u043d<\/strong>:<\/p>\n<pre><code class=\"scala\">Project ['name] +- Filter ['age &gt; 30]    +- UnresolvedRelation [users]<\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c Catalyst \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u00a0<strong>\u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0441\u0441\u044b\u043b\u043e\u043a<\/strong>:<\/p>\n<ol>\n<li>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b\u00a0<code>users<\/code>\u00a0\u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u0445\u043e\u0434\u0438\u0442 \u043a\u043e\u043b\u043e\u043d\u043a\u0438\u00a0<code>name<\/code>\u00a0\u0438\u00a0<code>age<\/code>\u00a0\u0432 \u0441\u0445\u0435\u043c\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b<\/p>\n<\/li>\n<li>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0442\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<\/ol>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f\u00a0<strong>\u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043d\u044b\u0439 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043b\u0430\u043d<\/strong>:<\/p>\n<pre><code class=\"scala\">Project [name#12] +- Filter (age#13 &gt; 30)    +- Relation[name#12, age#13, ...] parquet<\/code><\/pre>\n<p>\u0414\u043b\u044f Data Engineer \u0432\u0430\u0436\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c:\u00a0<strong>\u0438\u043c\u0435\u043d\u043d\u043e \u043d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u043e\u0448\u0438\u0431\u043a\u0438 \u0442\u0438\u043f\u0430\u00a0<\/strong><code><strong>AnalysisException<\/strong><\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043d\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0442\u0430\u0431\u043b\u0438\u0446 \u0438\u043b\u0438 \u043a\u043e\u043b\u043e\u043d\u043e\u043a.<\/p>\n<figure class=\"\">\n<div><figcaption>\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u0434\u0435\u0440\u0435\u0432\u043e AST<\/figcaption><\/div>\n<\/figure>\n<h4>2. \u041b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f: \u043f\u0440\u0430\u0432\u0438\u043b\u0430 (RBO)<\/h4>\n<p>\u041d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 Catalyst \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442 \u0431\u043e\u043b\u0435\u0435 50 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0445 \u043f\u0440\u0430\u0432\u0438\u043b \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u044f \u043f\u043b\u0430\u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u042d\u0442\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u044b \u043d\u0430 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u0445 \u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0430\u043b\u0433\u0435\u0431\u0440\u044b.<\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438 \u043f\u0440\u0430\u0432\u0438\u043b:<\/p>\n<h3>\u0423\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439<\/h3>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0430\u0432\u0438\u043b\u043e\u00a0<strong>Constant Folding<\/strong>\u00a0\u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0430\u043c\u0438:<\/p>\n<pre><code class=\"scala\">Filter (age &gt; 25 + 5) \u2192 Filter (age &gt; 30)<\/code><\/pre>\n<h3>\u041f\u0435\u0440\u0435\u043d\u043e\u0441 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432<\/h3>\n<p>\u041f\u0440\u0430\u0432\u0438\u043b\u043e\u00a0<strong>Predicate Pushdown<\/strong>\u00a0\u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0435\u0442 \u0444\u0438\u043b\u044c\u0442\u0440\u044b \u0431\u043b\u0438\u0436\u0435 \u043a \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u043c \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<pre><code class=\"scala\">\/\/ \u0414\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 Project [name] +- Filter (country = 'US')    +- Join (users.id = orders.user_id)       +- Relation [users]       +- Relation [orders]  \/\/ \u041f\u043e\u0441\u043b\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 Project [name] +- Join (users.id = orders.user_id)    +- Filter (country = 'US')       +- Relation [users]    +- Relation [orders]<\/code><\/pre>\n<p>\u042d\u0442\u043e \u043a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0430\u0436\u043d\u0430\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f: \u0444\u0438\u043b\u044c\u0442\u0440\u044b, \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0435 \u0434\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439, \u043c\u043e\u0433\u0443\u0442 \u0440\u0430\u0434\u0438\u043a\u0430\u043b\u044c\u043d\u043e \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<h3>\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439<\/h3>\n<p>\u041f\u0440\u0430\u0432\u0438\u043b\u043e\u00a0<strong>ProjectionElimination<\/strong>\u00a0\u0443\u0431\u0438\u0440\u0430\u0435\u0442 \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435 \u043f\u0440\u043e\u0435\u043a\u0446\u0438\u0438:<\/p>\n<pre><code class=\"scala\">Project (columns) (Project (same_columns) (child)) \u2192 Project (columns) (child)<\/code><\/pre>\n<p>\u0414\u043b\u044f Data Engineer:\u00a0<strong>\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u2014 \u044d\u0442\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0431\u0435\u0437 \u0443\u0447\u0435\u0442\u0430 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0435\u0439 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445<\/strong>. \u041e\u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442 \u043e\u0431\u0449\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0442 \u043a \u0431\u043e\u043b\u0435\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u043c\u0443 \u043f\u043b\u0430\u043d\u0443.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043e\u0434\u0430 Catalyst, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0435\u0433\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u043e:<\/p>\n<pre><code class=\"scala\">\/\/ \u041f\u0440\u0430\u0432\u0438\u043b\u043e \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432 object CombineFilters extends Rule[LogicalPlan] {   def apply(plan: LogicalPlan): LogicalPlan = plan transform {     case Filter(cond1, Filter(cond2, child)) =&gt;       Filter(And(cond1, cond2), child)   } }<\/code><\/pre>\n<h4>3. \u0424\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u043d\u0430\u044f \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f (CBO)<\/h4>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 Catalyst \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f JOIN \u0443 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432:<\/p>\n<ul>\n<li>\n<p><strong>BroadcastHashJoin<\/strong>: \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u043d\u0430 \u0432\u0441\u0435 \u0443\u0437\u043b\u044b (\u0431\u044b\u0441\u0442\u0440\u044b\u0439, \u043d\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442 RAM = \u043e\u0431\u044a\u0435\u043c \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c\u043e\u0433\u043e DataFrame \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c executor \u0438 driver)<\/p>\n<\/li>\n<li>\n<p><strong>SortMergeJoin<\/strong>: \u0441\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u043e\u0431\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0438 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 (\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0446)<\/p>\n<\/li>\n<li>\n<p><strong>ShuffleHashJoin<\/strong>: \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0445\u0435\u0448-\u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0434\u043b\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f (\u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442)<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><\/figure>\n<p>\u0417\u0434\u0435\u0441\u044c Catalyst \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u00a0<strong>Cost-Based Optimizer (CBO)<\/strong>\u00a0\u2014 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u0435\u0442 \u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043f\u043b\u0430\u043d\u043e\u0432 \u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439. CBO \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442:<\/p>\n<ol>\n<li>\n<p><strong>\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0434\u0430\u043d\u043d\u044b\u0445<\/strong>\u00a0(\u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u0442\u0440\u043e\u043a, \u0440\u0430\u0437\u043c\u0435\u0440\u044b \u0442\u0430\u0431\u043b\u0438\u0446)<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u0430\u0440\u0434\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u043b\u043e\u043d\u043e\u043a<\/strong>\u00a0(\u0447\u0438\u0441\u043b\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439)<\/p>\n<\/li>\n<li>\n<p><strong>\u0420\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445<\/strong>\u00a0(\u0447\u0435\u0440\u0435\u0437 \u0433\u0438\u0441\u0442\u043e\u0433\u0440\u0430\u043c\u043c\u044b)<\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u043b\u044f \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b CBO\u00a0<strong>\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443<\/strong>:<\/p>\n<pre><code class=\"sql\">-- \u0421\u0431\u043e\u0440 \u043e\u0431\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u044b ANALYZE TABLE orders COMPUTE STATISTICS;  -- \u0421\u0431\u043e\u0440 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u043f\u043e \u043a\u043e\u043b\u043e\u043d\u043a\u0430\u043c ANALYZE TABLE orders COMPUTE STATISTICS FOR COLUMNS order_id, customer_id;<\/code><\/pre>\n<p>\u0414\u043b\u044f Data Engineer \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c:\u00a0<strong>\u0431\u0435\u0437 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 CBO \u0434\u0435\u043b\u0430\u0435\u0442 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043e\u0446\u0435\u043d\u043e\u043a<\/strong>, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u043a \u043d\u0435\u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u043b\u0430\u043d\u0430\u043c.<\/p>\n<p>\u0424\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043b\u0430\u043d \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0442\u043e\u0434\u00a0<code>explain()<\/code>:<\/p>\n<pre><code class=\"scala\">df.explain() \/\/ \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442: \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043b\u0430\u043d \u0441 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u043c\u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430\u043c\u0438  == Physical Plan == AdaptiveSparkPlan isFinalPlan=false +- HashAggregate(keys=[title#18], functions=[sum(cast(label#17 as double))])    +- Exchange hashpartitioning(title#18, 200), ENSURE_REQUIREMENTS, [plan_id=120]       +- HashAggregate(keys=[title#18], functions=[partial_sum(cast(label#17 as double))])          +- Filter (isnotnull(label#17) AND (cast(label#17 as int) = 1))             +- FileScan csv [label#17,title#18] Batched: false, DataFilters: [isnotnull(label#17), (cast(label#17 as int) = 1)], Format: CSV, Location: InMemoryFileIndex(1 paths)[file:\/home\/seidzi\/habr\/csv\/part-00000-2a2f079d-0edc-43aa-aec2-e3b10e69..., PartitionFilters: [], PushedFilters: [IsNotNull(label)], ReadSchema: struct&lt;label:string,title:string&gt;  <\/code><\/pre>\n<h4>4. \u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043a\u043e\u0434\u0430: \u0434\u0432\u0438\u0436\u043e\u043a Tungsten<\/h4>\n<p>\u041d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c \u044d\u0442\u0430\u043f\u0435 Catalyst \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043b\u0430\u043d \u0432 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0439 \u043a\u043e\u0434 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0434\u0432\u0438\u0436\u043a\u0430\u00a0<strong>Tungsten<\/strong>. \u042d\u0442\u043e\u0442 \u0434\u0432\u0438\u0436\u043e\u043a \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0431\u0430\u0439\u0442-\u043a\u043e\u0434 Java \u0434\u043b\u044f \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439, \u043c\u0438\u043d\u0443\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438 Spark.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u00a0<code>age &gt; 30<\/code>\u00a0Catalyst \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"java\">public boolean filter(InternalRow row) {   return row.getInt(1) &gt; 30; \/\/ \u0414\u043e\u0441\u0442\u0443\u043f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043a \u043a\u043e\u043b\u043e\u043d\u043a\u0435 age }<\/code><\/pre>\n<p>Tungsten \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442:<\/p>\n<ol>\n<li>\n<p><strong>\u0412\u0435\u043a\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443<\/strong>: \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u0430\u043c\u0438, \u0430 \u043d\u0435 \u043f\u043e \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0435<\/p>\n<\/li>\n<li>\n<p><strong>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u044c\u044e<\/strong>: \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0441\u0431\u043e\u0440\u043a\u0438 \u043c\u0443\u0441\u043e\u0440\u0430<\/p>\n<\/li>\n<li>\n<p><strong>SIMD-\u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438<\/strong>: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430<\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u043b\u044f Data Engineer \u0432\u0430\u0436\u043d\u043e \u0437\u043d\u0430\u0442\u044c:\u00a0<strong>\u044d\u0442\u043e\u0442 \u044d\u0442\u0430\u043f \u0432 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0435\u043f\u0435\u043d\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d<\/strong>, \u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438 \u043e\u0442\u043b\u0430\u0434\u043a\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438.<\/p>\n<h3>\u0424\u0430\u043a\u0442\u043e\u0440\u044b, \u0432\u043b\u0438\u044f\u044e\u0449\u0438\u0435 \u043d\u0430 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c Catalyst<\/h3>\n<p>\u0427\u0442\u043e\u0431\u044b \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 Catalyst, \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u0444\u0430\u043a\u0442\u043e\u0440\u044b \u0432\u043b\u0438\u044f\u044e\u0442 \u043d\u0430 \u0435\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0438\u0437 \u043d\u0438\u0445.<\/p>\n<h4>1. \u0422\u0438\u043f \u0438 \u0444\u043e\u0440\u043c\u0430\u0442 \u0434\u0430\u043d\u043d\u044b\u0445<\/h4>\n<figure class=\"full-width\"><\/figure>\n<h3>\u041a\u043e\u043b\u043e\u043d\u043e\u0447\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b (Parquet, ORC)<\/h3>\n<p>\u042d\u0442\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u044b \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 Catalyst \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<ul>\n<li>\n<p><strong>\u041f\u0440\u0435\u0434\u0438\u043a\u0430\u0442\u043d\u044b\u0439 \u043f\u0443\u0448\u0434\u0430\u0443\u043d<\/strong>: \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0431\u043b\u043e\u043a\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0440\u043e\u0435\u043a\u0446\u0438\u044f \u043a\u043e\u043b\u043e\u043d\u043e\u043a<\/strong>: \u0447\u0442\u0435\u043d\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0443\u0436\u043d\u044b\u0445 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432<\/p>\n<\/li>\n<li>\n<p><strong>\u0412\u0435\u043a\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f<\/strong>: \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u0430\u043c\u0438<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 (\u043d\u0438\u0436\u0435 csv):<\/p>\n<pre><code class=\"python\">parquet_df.where('label=1').groupby('title').agg({\"label\": \"sum\"}).count() # 168190  # CPU times: user 1.67 ms, sys: 7.3 ms, total: 8.97 ms # Wall time: 1.22 s<\/code><\/pre>\n<h3>\u0421\u0442\u0440\u043e\u0447\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b (CSV, JSON)<\/h3>\n<p>\u0414\u043b\u044f \u044d\u0442\u0438\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u044b:<\/p>\n<ul>\n<li>\n<p>CSV \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0447\u0442\u0435\u043d\u0438\u044f \u0438 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 \u0432\u0441\u0435\u0433\u043e \u0444\u0430\u0439\u043b\u0430<\/p>\n<\/li>\n<li>\n<p>JSON \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e\u0435 \u0447\u0442\u0435\u043d\u0438\u0435 \u043a\u043e\u043b\u043e\u043d\u043e\u043a, \u043d\u043e \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435 \u043a\u043e\u043b\u043e\u043d\u043e\u0447\u043d\u044b\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"python\">csv_df.where('label=1').groupby('title').agg({\"label\": \"sum\"}).count() # 168190  # CPU times: user 4.7 ms, sys: 3.09 ms, total: 7.78 ms # Wall time: 2.05 s<\/code><\/pre>\n<p>\u0414\u043b\u044f Data Engineer \u043f\u0440\u044f\u043c\u0430\u044f \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u044f:\u00a0<strong>\u0432\u0441\u0435\u0433\u0434\u0430 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0439\u0442\u0435 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 Parquet \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0437\u0430\u0434\u0430\u0447<\/strong>. \u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u0441\u044f.<\/p>\n<h4>2. \u0420\u0430\u0437\u043c\u0435\u0440 \u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0444\u0430\u0439\u043b\u043e\u0432<\/h4>\n<p>Catalyst \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435\u043c \u0437\u0430\u0434\u0430\u0447 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 \u0438 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439:<\/p>\n<h3>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043c\u0435\u043b\u043a\u0438\u0445 \u0444\u0430\u0439\u043b\u043e\u0432<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 10,000 \u0444\u0430\u0439\u043b\u043e\u0432 \u043f\u043e 1 \u041c\u0411:<\/p>\n<ul>\n<li>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u0444\u0430\u0439\u043b \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u043a\u043b\u0430\u0434\u043d\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u044b \u043d\u0430 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0447 \u0441\u043e\u0441\u0442\u0430\u0432\u044f\u0442 \u0434\u043e 40% \u0432\u0440\u0435\u043c\u0435\u043d\u0438<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435\u0440\u0430\u0432\u043d\u043e\u043c\u0435\u0440\u043d\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0435\u0439<\/p>\n<\/li>\n<\/ul>\n<h3>\u041e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 128-256 \u041c\u0411 \u043d\u0430 \u0444\u0430\u0439\u043b. \u0415\u0441\u043b\u0438 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f HDFS, \u0442\u043e \u0440\u0430\u0437\u043c\u0435\u0440 \u0444\u0430\u0439\u043b\u0430 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0440\u0430\u0432\u0435\u043d \u0440\u0430\u0437\u043c\u0435\u0440\u0443 \u0431\u043b\u043e\u043a\u0430.<\/h3>\n<p>\u0414\u043b\u044f Data Engineer \u0432\u0430\u0436\u043d\u043e \u043f\u043e\u043c\u043d\u0438\u0442\u044c:\u00a0<strong>Spark \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0444\u0430\u0439\u043b\u043e\u0432, \u0430 \u043d\u0435 \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u0444\u0430\u0439\u043b\u043e\u0432<\/strong>.<\/p>\n<h4>3. \u0422\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 JOIN-\u043a\u043b\u044e\u0447\u0430\u0445<\/h4>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0432\u044b \u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u0442\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0442\u0438\u043f\u0430\u043c\u0438 \u043a\u043b\u044e\u0447\u0435\u0439, Catalyst \u0432\u044b\u043d\u0443\u0436\u0434\u0435\u043d \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u042d\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a:<\/p>\n<ul>\n<li>\n<p>\u041d\u0435\u044f\u0432\u043d\u044b\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c\u00a0<code>CAST<\/code>\u00a0\u0432 \u043f\u043b\u0430\u043d\u0435<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0439 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Broadcast Join)<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043c\u0435\u0434\u043b\u0435\u043d\u0438\u044e \u0434\u043e 40% \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435\u043c \u043f\u043e \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c \u0442\u0438\u043f\u0430\u043c<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0439\u0442\u0435 \u043f\u043b\u0430\u043d \u0447\u0435\u0440\u0435\u0437\u00a0<code>explain()<\/code>\u00a0\u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439\u00a0<code>cast<\/code>:<\/p>\n<pre><code class=\"scala\">SortMergeJoin [cast(customer_id_int#10 as string)], [customer_id_string#20]<\/code><\/pre>\n<p>\u0414\u043b\u044f Data Engineer:\u00a0<strong>\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0435 \u0442\u0438\u043f\u044b \u0434\u043b\u044f JOIN-\u043a\u043b\u044e\u0447\u0435\u0439<\/strong>\u00a0\u0432\u043e \u0432\u0441\u0435\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u0445. \u0415\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435, \u0434\u0435\u043b\u0430\u0439\u0442\u0435 \u0435\u0433\u043e \u044f\u0432\u043d\u043e:<\/p>\n<pre><code class=\"scala\">val df1Fixed = df1.withColumn(\"customer_id_string\", $\"customer_id_int\".cast(\"string\"))<\/code><\/pre>\n<h4>4. \u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0438 CBO<\/h4>\n<p>CBO \u0432 Catalyst \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-457934","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/457934","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=457934"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/457934\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=457934"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=457934"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=457934"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}