{"id":346742,"date":"2023-03-14T21:00:55","date_gmt":"2023-03-14T21:00:55","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=346742"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=346742","title":{"rendered":"<span>\u0413\u0435\u043e\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f DuckDB<\/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<p>\u0411\u043e\u043b\u044c\u0448\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0440\u043e\u0448\u043b\u043e\u0433\u043e \u0433\u043e\u0434\u0430 \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0441 Hexvarium. \u0411\u0430\u0437\u0438\u0440\u0443\u044e\u0449\u0430\u044f\u0441\u044f \u0432 \u0410\u0442\u0435\u0440\u0442\u043e\u043d\u0435, \u0448\u0442\u0430\u0442 \u041a\u0430\u043b\u0438\u0444\u043e\u0440\u043d\u0438\u044f, \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f \u0441\u0442\u0440\u043e\u0438\u0442 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u043f\u0442\u043e\u0432\u043e\u043b\u043e\u043a\u043e\u043d\u043d\u044b\u043c\u0438 \u0441\u0435\u0442\u044f\u043c\u0438. \u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0443 \u043d\u0438\u0445 \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u0442\u0435\u0439 \u0432 \u0440\u0430\u0439\u043e\u043d\u0435 \u0437\u0430\u043b\u0438\u0432\u0430, \u043d\u043e \u0443 \u043d\u0438\u0445 \u0435\u0441\u0442\u044c \u043f\u043b\u0430\u043d\u044b \u043f\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044e \u0432 \u0421\u0428\u0410.<\/p>\n<p>\u041c\u043e\u044f \u0440\u043e\u043b\u044c \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 30 \u043c\u0438\u043b\u043b\u0438\u0430\u0440\u0434\u043e\u0432 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0438\u0437 70 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438. \u042d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0430\u043c\u0438, \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0449\u0438\u043c\u0438 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u043b\u0430\u043d\u044b \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u043e\u043f\u0442\u043e\u0432\u043e\u043b\u043e\u043a\u043e\u043d\u043d\u043e\u0439 \u0441\u0435\u0442\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e LocalSolver. \u0414\u0430\u043b\u0435\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043f\u0440\u0438\u043c\u0435\u0440 \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0437 \u0442\u0430\u043a\u0438\u0445 \u043f\u043b\u0430\u043d\u043e\u0432.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6eb\/607\/229\/6eb607229028794c100c1d02ad78fa62.gif\" width=\"1650\" height=\"1104\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6eb\/607\/229\/6eb607229028794c100c1d02ad78fa62.gif\"\/><\/figure>\n<p>\u041d\u0430\u0448\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 PostGIS, ClickHouse \u0438 BigQuery. \u0414\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0442 \u0432 \u0441\u0430\u043c\u044b\u0445 \u0440\u0430\u0437\u043d\u044b\u0445, \u043d\u043e \u0447\u0430\u0449\u0435 \u043d\u0435 \u0432 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u0430\u0445. \u0417\u0430\u0442\u0435\u043c \u043c\u044b \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0438 \u043e\u0431\u043e\u0433\u0430\u0449\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435, \u0447\u0430\u0441\u0442\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e PostGIS \u0438\u043b\u0438 ClickHouse, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u0445 \u0432 BigQuery. \u0417\u0430\u0442\u0435\u043c \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u044b, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0435 \u0441 LocalSolver, \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u043e\u0447\u0438\u0449\u0435\u043d\u043d\u043e\u0439 \u0438 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0432 BigQuery.<\/p>\n<p>\u0410\u043d\u0430\u043b\u0438\u0437 \u043f\u043e\u0434\u043f\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u0432\u043e\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043e\u0432, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0447\u0430\u0441\u0442\u043e \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Unfolded. \u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0434\u043b\u044f Speedtest \u043e\u0442 Ookla \u043f\u0440\u043e\u0448\u043b\u044b\u043c \u043b\u0435\u0442\u043e\u043c. \u041c\u044b \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u043e \u0443\u0440\u043e\u0432\u043d\u044e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f H3 9 \u0438 \u0432\u0437\u044f\u043b\u0438 \u0441\u0430\u043c\u0443\u044e \u0432\u044b\u0441\u043e\u043a\u0443\u044e \u0441\u0440\u0435\u0434\u043d\u044e\u044e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438\u0437 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0448\u0435\u0441\u0442\u0438\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430, \u043d\u0430\u043d\u0435\u0441\u044f \u0438\u0445 \u043d\u0430 \u043a\u0430\u0440\u0442\u0443.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/464\/a4e\/5e5\/464a4e5e52203bc32c490709dabb8082.png\" alt=\"\" title=\"\" width=\"700\" height=\"438\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/464\/a4e\/5e5\/464a4e5e52203bc32c490709dabb8082.png\"\/><\/figure>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0430 \u0435\u0449\u0435 \u043e\u0434\u043d\u0430 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u0440\u0430\u0437\u043d\u0438\u0446\u0443 \u0432 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0448\u0438\u0440\u043e\u043a\u043e\u043f\u043e\u043b\u043e\u0441\u043d\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0432 \u043f\u0435\u0440\u0438\u043e\u0434 \u0441 \u0438\u044e\u043d\u044f \u043f\u043e \u043d\u043e\u044f\u0431\u0440\u044c \u043f\u0440\u043e\u0448\u043b\u043e\u0433\u043e \u0433\u043e\u0434\u0430. \u0414\u0430\u043d\u043d\u044b\u0435 \u0432 FCC \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u044b \u0448\u0438\u0440\u043e\u043a\u043e\u043f\u043e\u043b\u043e\u0441\u043d\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0438\u0437 \u0421\u0428\u0410.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0b1\/309\/fea\/0b1309fea8d6e9ae1c0c54abc6f938a5.png\" width=\"3554\" height=\"1942\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/0b1\/309\/fea\/0b1309fea8d6e9ae1c0c54abc6f938a5.png\"\/><\/figure>\n<h2>\u0418\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 DuckDB<\/h2>\n<p>DuckDB \u2014 \u044d\u0442\u043e \u043f\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0430 \u041c\u0430\u0440\u043a\u0430 \u0420\u0430\u0430\u0441\u0432\u0435\u043b\u044c\u0434\u0442\u0430 \u0438 \u0425\u0430\u043d\u043d\u0435\u0441\u0430 \u041c\u044e\u043b\u0435\u0439\u0437\u0435\u043d\u0430. \u041e\u043d \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u0430 \u0441\u0442\u0440\u043e\u043a C++ \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0434\u0432\u043e\u0438\u0447\u043d\u044b\u0439 \u0444\u0430\u0439\u043b. \u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0438\u0434\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u0430\u043a\u0442\u0438\u0432\u043d\u043e: \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u043e\u043c\u043c\u0438\u0442\u043e\u0432 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 GitHub \u0443\u0434\u0432\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0447\u0442\u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u0433\u043e\u0434 \u0441 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u0435\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0432 2018 \u0433\u043e\u0434\u0443. DuckDB \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 SQL PostgreSQL, \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 RE2 \u043e\u0442 Google \u0438 \u043e\u0431\u043e\u043b\u043e\u0447\u043a\u0443 SQLite.<\/p>\n<p>SQLite \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u044f\u0442\u044c \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445: NULL, INTEGER, REAL, TEXT \u0438 BLOB. \u041c\u0435\u043d\u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u044d\u0442\u043e \u0440\u0430\u0441\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u043b\u043e, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u0430 \u0441\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u0430 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0439 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0435 SELECT, \u0430 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e\u043b\u0435 \u043a\u0430\u043a \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u043d\u0435 \u043c\u043e\u0433\u043b\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u0442\u044c \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0438 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u044d\u0442\u0438\u0445 \u043f\u043e\u043b\u0435\u0439.<\/p>\n<p>\u041a \u0441\u0447\u0430\u0441\u0442\u044c\u044e, DuckDB \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 25 \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438, \u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439. \u0412\u0435\u0434\u0435\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u043d\u0430\u0434 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u0442 \u0433\u0435\u043e\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 PostGIS \u041f\u043e\u043b\u0430 \u0420\u044d\u043c\u0441\u0438 \u0432 DuckDB. \u0418\u0441\u0430\u0430\u043a \u0411\u0440\u043e\u0434\u0441\u043a\u0438\u0439, \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u0438\u043d\u0436\u0435\u043d\u0435\u0440 Foursquare, \u043c\u0430\u0442\u0435\u0440\u0438\u043d\u0441\u043a\u043e\u0439 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 Unfolded, \u0442\u0430\u043a\u0436\u0435 \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043b \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 H3 \u0434\u043b\u044f DuckDB. \u0418 \u0445\u043e\u0442\u044f \u0435\u0449\u0435 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043e, \u043f\u0440\u0435\u0434\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f \u043f\u043e\u043f\u044b\u0442\u043a\u0438 \u0432\u0441\u0442\u0440\u043e\u0438\u0442\u044c GDAL \u0447\u0435\u0440\u0435\u0437 \u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 Arrow \u0432 DuckDB.<\/p>\n<p>Min\/Max \u0438\u043d\u0434\u0435\u043a\u0441 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u0430 \u0441\u0442\u043e\u043b\u0431\u0446\u0430 \u0432 DuckDB. \u0418\u043c\u0435\u043d\u043d\u043e \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u044d\u0442\u043e\u043c\u0443 \u0442\u0438\u043f\u0443 \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445 OLAP \u0442\u0430\u043a \u0431\u044b\u0441\u0442\u0440\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f Parquet \u0438 JSON \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0435, \u0438 \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0445\u043e\u0440\u043e\u0448\u043e \u0437\u0430\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043e. \u0414\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432 Parquet \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0441\u0436\u0430\u0442\u0438\u0435 Snappy \u0438 ZStandard.<\/p>\n<p>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f DuckDB \u0445\u043e\u0440\u043e\u0448\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u0438 \u043e\u0447\u0435\u043d\u044c \u043b\u0430\u043a\u043e\u043d\u0438\u0447\u043d\u0430, \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438 \u0440\u044f\u0434\u043e\u043c \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0439.<\/p>\n<h2>\u0417\u0430\u043f\u0443\u0441\u043a DuckDB<\/h2>\n<p>\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f DuckDB \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 Geospatial \u0438 H3, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0432 \u044d\u0442\u043e\u043c \u043f\u043e\u0441\u0442\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u044e DuckDB \u0441 \u044d\u0442\u0438\u043c\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f\u043c\u0438.<\/p>\n<p>\u041f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0435 \u043d\u0438\u0436\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0431\u044b\u043b\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u044b \u043d\u0430 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0435 e2-standard-4 \u0432 Google Cloud \u043f\u043e\u0434 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c Ubuntu 20 LTS. \u042d\u0442\u0430 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u043c\u0430\u0448\u0438\u043d\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 4 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u0426\u041f \u0438 16 \u0413\u0411 \u041e\u0417\u0423. \u041e\u043d \u0431\u044b\u043b \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0432 \u041b\u043e\u0441-\u0410\u043d\u0434\u0436\u0435\u043b\u0435\u0441\u0435, \u0432 \u0440\u0435\u0433\u0438\u043e\u043d\u0435 us-west2-b, \u0438 \u0438\u043c\u0435\u0435\u0442 \u0441\u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u0435\u0440\u0441\u0438\u0441\u0442\u0435\u043d\u0442\u043d\u044b\u0439 \u0434\u0438\u0441\u043a \u043e\u0431\u044a\u0435\u043c\u043e\u043c 100 \u0413\u0411. \u0417\u0430\u043f\u0443\u0441\u043a \u0441\u0442\u043e\u0438\u043b 0,18 \u0434\u043e\u043b\u043b\u0430\u0440\u0430 \u0432 \u0447\u0430\u0441.<\/p>\n<p>\u041d\u0438\u0436\u0435 \u0431\u0443\u0434\u0443\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u043f\u0430\u043a\u0435\u0442\u044b \u041f\u041e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0432 \u044d\u0442\u043e\u043c \u043f\u043e\u0441\u0442\u0435.<\/p>\n<pre><code class=\"bash\">$ sudo apt update $ sudo apt install \\     awscli \\     build-essential \\     libssl-dev \\     pigz \\     unzip<\/code><\/pre>\n<p>\u0414\u043b\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f H3 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f CMake \u0432\u0435\u0440\u0441\u0438\u0438 3.20+, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0431\u0435\u0440\u0443 \u0435\u0433\u043e.<\/p>\n<pre><code class=\"bash\">$ cd ~ $ wget -c https:\/\/github.com\/Kitware\/CMake\/releases\/download\/v3.20.0\/cmake-3.20.0.tar.gz $ tar -xzf cmake-3.20.0.tar.gz $ cd cmake-3.20.0 $ .\/bootstrap --parallel=$(nproc) $ make -j$(nproc) $ sudo make install<\/code><\/pre>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u043a\u0430\u043a DuckDB, \u0442\u0430\u043a \u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 H3 \u0434\u043b\u044f \u043d\u0435\u0433\u043e. \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 geo \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u043e \u043a \u043a\u043e\u043c\u043c\u0438\u0442\u0443 DuckDB c817201, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u044e \u043a \u043d\u0435\u043c\u0443 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 H3.<\/p>\n<pre><code class=\"bash\">$ git clone https:\/\/github.com\/isaacbrodsky\/h3-duckdb ~\/duckdb_h3 $ cd ~\/duckdb_h3 $ git submodule update --init  $ cd duckdb $ git checkout c817201 $ cd ..  $ CMAKE_BUILD_PARALLEL_LEVEL=$(nproc) \\     make release<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u0442 \u0447\u0430\u0441\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 PostGIS \u0432 DuckDB.<\/p>\n<pre><code class=\"bash\">$ git clone https:\/\/github.com\/handstuyennn\/geo ~\/duckdb_geo $ cd ~\/duckdb_geo $ git submodule init $ git submodule update --recursive --remote  $ mkdir -p build\/release  $ cmake \\     .\/duckdb\/CMakeLists.txt \\     -DEXTERNAL_EXTENSION_DIRECTORIES=..\/geo \\     -DCMAKE_BUILD_TYPE=RelWithDebInfo \\     -DEXTENSION_STATIC_BUILD=1 \\     -DBUILD_TPCH_EXTENSION=1 \\     -DBUILD_PARQUET_EXTENSION=1 \\     -B build\/release  $ CMAKE_BUILD_PARALLEL_LEVEL=$(nproc) \\     cmake --build build\/release<\/code><\/pre>\n<p>\u0421\u043e\u0437\u0434\u0430\u043c \u0448\u0435\u043b\u043b \u0441\u043a\u0440\u0438\u043f\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442 \u0434\u0432\u043e\u0438\u0447\u043d\u044b\u0439 \u0444\u0430\u0439\u043b DuckDB \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u043d\u0435\u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439.<\/p>\n<pre><code class=\"bash\">$ echo \"$HOME\/duckdb_geo\/build\/release\/duckdb -unsigned \\$@\" \\     | sudo tee \/usr\/sbin\/duckdb $ sudo chmod +x \/usr\/sbin\/duckdb<\/code><\/pre>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u044e \u0444\u0430\u0439\u043b \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 DuckDB \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043e\u0431\u043e\u0438\u0445 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.<\/p>\n<pre><code class=\"bash\">$ vi ~\/.duckdbrc<\/code><\/pre>\n<pre><code class=\"bash\">.timer on LOAD '\/home\/mark\/duckdb_h3\/build\/release\/h3.duckdb_extension'; LOAD '\/home\/mark\/duckdb_geo\/build\/release\/extension\/geo\/geo.duckdb_extension'; <\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0449\u0443 DuckDB \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044e, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043b\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"bash\">$ duckdb<\/code><\/pre>\n<pre><code class=\"sql\">SELECT h3_cell_to_parent(CAST(586265647244115967 AS ubigint), 1) test; \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502        test        \u2502 \u2502       uint64       \u2502 \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524 \u2502 581764796395814911 \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/code><\/pre>\n<pre><code class=\"sql\">SELECT ST_MAKEPOINT(52.347113, 4.869454) test; \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502                    test                    \u2502 \u2502                 geography                  \u2502 \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524 \u2502 01010000001B82E3326E2C4A406B813D26527A1340 \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/code><\/pre>\n<p>\u041c\u043d\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c, \u0447\u0442\u043e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0442\u0438\u043f \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u043a\u0430\u0436\u0434\u044b\u043c \u0438\u043c\u0435\u043d\u0435\u043c \u043f\u043e\u043b\u044f.<\/p>\n<h2>\u041d\u0430\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 Ookla Speedtest<\/h2>\n<p>Ookla \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u0442 \u0441\u0432\u043e\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 Speedtest \u0432 AWS \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 Parquet. \u041d\u0438\u0436\u0435 \u044f \u0441\u043a\u0430\u0447\u0430\u044e \u043d\u0430\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 2022 \u0433\u043e\u0434\u0430 \u0434\u043b\u044f \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432.<\/p>\n<pre><code class=\"bash\">$ aws s3 sync \\     --no-sign-request \\     s3:\/\/ookla-open-data\/parquet\/performance\/type=mobile\/year=2022\/ \\     .\/<\/code><\/pre>\n<p>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0443\u0442\u0435\u0439 \u043a \u043f\u0430\u043f\u043a\u0430\u043c \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0430 \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0441\u0435\u043a\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f Apache Hive. \u042f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0442\u044b\u0440\u0435 \u0444\u0430\u0439\u043b\u0430 Parquet, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0443 \u0438\u0445 \u0432 \u043e\u0434\u043d\u0443 \u043f\u0430\u043f\u043a\u0443.<\/p>\n<pre><code class=\"bash\">$ mv quarter\\=*\/*.parquet .\/<\/code><\/pre>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u0440\u0430\u0437\u043c\u0435\u0440\u044b \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 \u0444\u0430\u0439\u043b\u043e\u0432. \u0412\u0441\u0435\u0433\u043e \u043e\u043d\u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 15 738 442 \u0441\u0442\u0440\u043e\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<pre><code class=\"bash\">$ ls -lht *.parquet  173M  2022-10-01_performance_mobile_tiles.parquet 180M  2022-07-01_performance_mobile_tiles.parquet 179M  2022-04-01_performance_mobile_tiles.parquet 174M  2022-01-01_performance_mobile_tiles.parquet<\/code><\/pre>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0430 \u0441\u0445\u0435\u043c\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0430\u044f \u0432 \u044d\u0442\u0438\u0445 \u0444\u0430\u0439\u043b\u0430\u0445 Parquet.<\/p>\n<pre><code class=\"sql\">$ echo \"SELECT name,                type,                converted_type         FROM parquet_schema('2022-10*.parquet');\" \\     | duckdb  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502    name    \u2502    type    \u2502 converted_type \u2502 \u2502  varchar   \u2502  varchar   \u2502    varchar     \u2502 \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524 \u2502 schema     \u2502 BOOLEAN    \u2502 UTF8           \u2502 \u2502 quadkey    \u2502 BYTE_ARRAY \u2502 UTF8           \u2502 \u2502 tile       \u2502 BYTE_ARRAY \u2502 UTF8           \u2502 \u2502 avg_d_kbps \u2502 INT64      \u2502 INT_64         \u2502 \u2502 avg_u_kbps \u2502 INT64      \u2502 INT_64         \u2502 \u2502 avg_lat_ms \u2502 INT64      \u2502 INT_64         \u2502 \u2502 tests      \u2502 INT64      \u2502 INT_64         \u2502 \u2502 devices    \u2502 INT64      \u2502 INT_64         \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 <\/code><\/pre>\n<p>Ookla \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0430 \u0441\u0436\u0430\u0442\u0438\u0435 Snappy \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u0442\u043e\u043b\u0431\u0446\u0430. DuckDB \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0443 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u044b \u0434\u0430\u043d\u043d\u044b\u0435, \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0441\u0442\u043e\u043b\u0431\u0446\u0443. \u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0441\u0442\u043e\u043b\u0431\u0446\u0435 \u0442\u0430\u0439\u043b\u0430.<\/p>\n<pre><code class=\"sql\">$ echo \".mode line         SELECT *         EXCLUDE (stats_min_value,                  stats_max_value)         FROM parquet_metadata('2022-10-01_*.parquet')         WHERE path_in_schema = 'tile'         AND   row_group_id   = 0;\" \\     | duckdb                 file_name = 2022-10-01_performance_mobile_tiles.parquet            row_group_id = 0      row_group_num_rows = 665938   row_group_num_columns = 7         row_group_bytes = 31596007               column_id = 1             file_offset = 24801937              num_values = 665938          path_in_schema = tile                    type = BYTE_ARRAY               stats_min =               stats_max =        stats_null_count = 0    stats_distinct_count =             compression = SNAPPY               encodings = PLAIN_DICTIONARY, PLAIN, RLE, PLAIN       index_page_offset = 0  dictionary_page_offset = 3332511        data_page_offset = 3549527   total_compressed_size = 21469426 total_uncompressed_size = 124569336<\/code><\/pre>\n<h2>\u0418\u043c\u043f\u043e\u0440\u0442 Parquet \u0434\u0430\u043d\u043d\u044b\u0445<\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0433\u0443 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0447\u0435\u0442\u044b\u0440\u0435 \u0444\u0430\u0439\u043b\u0430 Parquet \u0432 DuckDB \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u0434\u043d\u043e\u0433\u043e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 SQL. \u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0442\u043e\u043b\u0431\u0435\u0446 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u0438\u043c\u0435\u043d\u0438 \u0444\u0430\u0439\u043b\u0430, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043a\u0430\u0436\u0434\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445. \u0418\u0437 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0445 706 \u041c\u0411 Parquet \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043a\u043e\u043b\u043e\u043d\u043a\u0430 \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u043b\u0438\u0441\u044c \u0432 \u0444\u0430\u0439\u043b DuckDB \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c 1,4 \u0413\u0411.<\/p>\n<pre><code class=\"sql\">$ echo \"CREATE TABLE mobile_perf AS         SELECT *         FROM read_parquet('*.parquet',                           filename=true);\" \\       | duckdb ~\/ookla.duckdb<\/code><\/pre>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 DuckDB HTTPFS, \u044f \u043c\u043e\u0433\u0443 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b Parquet \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0438\u0437 S3.<\/p>\n<pre><code class=\"sql\">$ echo \"INSTALL httpfs;         CREATE TABLE mobile_perf AS         SELECT *         FROM parquet_scan('s3:\/\/ookla-open-data\/parquet\/performance\/type=mobile\/year=2022\/*\/*.parquet',                           FILENAME=1);\" \\       | duckdb ~\/ookla.duckdb<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0435\u0433\u043e \u0435\u0449\u0435 \u043d\u0435\u0442, \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 HTTPFS \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043e \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438. \u0418\u043c\u0435\u0439\u0442\u0435 \u0432 \u0432\u0438\u0434\u0443, \u0447\u0442\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u0441\u0431\u043e\u0440\u043a\u0438 \u0435\u0449\u0435 \u043d\u0435 \u0433\u043e\u0442\u043e\u0432\u044b, \u0438 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<pre><code>Error: near line 1: IO Error: Failed to download extension \"httpfs\" at URL \"http:\/\/extensions.duckdb.org\/7813eea926\/linux_amd64\/httpfs.duckdb_extension.gz\" Extension \"httpfs\" is an existing extension.  Are you using a development build? In this case, extensions might not (yet) be uploaded.<\/code><\/pre>\n<h2>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u044b DuckDB<\/h2>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0430 \u0441\u0445\u0435\u043c\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 DuckDB.<\/p>\n<pre><code class=\"bash\">$ echo '.schema --indent' \\     | duckdb ~\/ookla.duckdb<\/code><\/pre>\n<pre><code class=\"sql\">CREATE TABLE mobile_perf(   quadkey VARCHAR,   tile VARCHAR,   avg_d_kbps BIGINT,   avg_u_kbps BIGINT,   avg_lat_ms BIGINT,   tests BIGINT,   devices BIGINT,   filename VARCHAR );<\/code><\/pre>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043f\u0440\u0438\u043c\u0435\u0440 \u0437\u0430\u043f\u0438\u0441\u0438.<\/p>\n<pre><code class=\"bash\">$ echo '.mode line         SELECT *         FROM mobile_perf         LIMIT 1' \\     | duckdb ~\/ookla.duckdb<\/code><\/pre>\n<pre><code class=\"sql\">   quadkey = 0022133222330023       tile = POLYGON((-160.043334960938 70.6363054807905, -160.037841796875 70.6363054807905, -160.037841796875 70.6344840663086, -160.043334960938 70.6344840663086, -160.043334960938 70.6363054807905)) avg_d_kbps = 15600 avg_u_kbps = 14609 avg_lat_ms = 168      tests = 2    devices = 1   filename = 2022-10-01_performance_mobile_tiles.parquet <\/code><\/pre>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u0441\u0445\u0435\u043c\u044b \u0441\u0436\u0430\u0442\u0438\u044f, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0438\u0437 \u043f\u0435\u0440\u0432\u044b\u0445 \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u043e\u0432 \u043f\u043e\u043b\u0435\u0439 \u0432 \u043f\u0435\u0440\u0432\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u0435 \u0441\u0442\u0440\u043e\u043a.<\/p>\n<pre><code class=\"sql\">$ echo \"SELECT column_name,                segment_type,                compression,                stats         FROM pragma_storage_info('mobile_perf')         WHERE row_group_id = 0         AND   segment_id   = 0         AND   segment_type != 'VALIDITY';\" \\     | duckdb ~\/ookla.duckdb  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502 column_name \u2502 segment_type \u2502 compression \u2502               stats               \u2502 \u2502   varchar   \u2502   varchar    \u2502   varchar   \u2502              varchar              \u2502 \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524 \u2502 quadkey     \u2502 VARCHAR      \u2502 FSST        \u2502 [Min: 00221332, Max: 02123303, \u2026  \u2502 \u2502 tile        \u2502 VARCHAR      \u2502 FSST        \u2502 [Min: POLYGON(, Max: POLYGON(, \u2026  \u2502 \u2502 avg_d_kbps  \u2502 BIGINT       \u2502 BitPacking  \u2502 [Min: 1, Max: 3907561][Has Null\u2026  \u2502 \u2502 avg_u_kbps  \u2502 BIGINT       \u2502 BitPacking  \u2502 [Min: 1, Max: 917915][Has Null:\u2026  \u2502 \u2502 avg_lat_ms  \u2502 BIGINT       \u2502 BitPacking  \u2502 [Min: 0, Max: 2692][Has Null: f\u2026  \u2502 \u2502 tests       \u2502 BIGINT       \u2502 BitPacking  \u2502 [Min: 1, Max: 1058][Has Null: f\u2026  \u2502 \u2502 devices     \u2502 BIGINT       \u2502 BitPacking  \u2502 [Min: 1, Max: 186][Has Null: fa\u2026  \u2502 \u2502 filename    \u2502 VARCHAR      \u2502 Dictionary  \u2502 [Min: 2022-10-, Max: 2022-10-, \u2026  \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 <\/code><\/pre>\n<h2>\u041e\u0431\u043e\u0433\u0430\u0449\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445<\/h2>\n<p>\u042f \u0437\u0430\u043f\u0443\u0449\u0443 DuckDB \u0441 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0439 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445, \u0434\u043e\u0431\u0430\u0432\u043b\u044e \u0442\u0440\u0438 \u0441\u0442\u043e\u043b\u0431\u0446\u0430 \u0434\u043b\u044f \u0443\u0440\u043e\u0432\u043d\u0435\u0439 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f 7, 8 \u0438 9, \u0430 \u0437\u0430\u0442\u0435\u043c \u043f\u0440\u0438\u0433\u043e\u0442\u043e\u0432\u043b\u044e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0448\u0435\u0441\u0442\u0438\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432 \u0438\u0437 \u0441\u0442\u043e\u043b\u0431\u0446\u0430 &#171;\u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u044f&#187; \u0442\u0430\u0439\u043b\u0430 .<\/p>\n<pre><code class=\"bash\">$ duckdb ~\/ookla.duckdb<\/code><\/pre>\n<pre><code class=\"sql\">ALTER TABLE mobile_perf ADD COLUMN h3_7 VARCHAR(15); ALTER TABLE mobile_perf ADD COLUMN h3_8 VARCHAR(15); ALTER TABLE mobile_perf ADD COLUMN h3_9 VARCHAR(15);  UPDATE mobile_perf SET h3_7 =         printf('%x',                h3_latlng_to_cell(                    ST_Y(ST_CENTROID(ST_GEOMFROMTEXT(tile))),                    ST_X(ST_CENTROID(ST_GEOMFROMTEXT(tile))),                    7)::bigint),      h3_8 =         printf('%x',                h3_latlng_to_cell(                    ST_Y(ST_CENTROID(ST_GEOMFROMTEXT(tile))),                    ST_X(ST_CENTROID(ST_GEOMFROMTEXT(tile))),                    8)::bigint),      h3_9 =         printf('%x',                h3_latlng_to_cell(                    ST_Y(ST_CENTROID(ST_GEOMFROMTEXT(tile))),                    ST_X(ST_CENTROID(ST_GEOMFROMTEXT(tile))),                    9)::bigint);<\/code><\/pre>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438.<\/p>\n<pre><code class=\"sql\">.mode line SELECT h3_7,        h3_8,        h3_9,        tile FROM mobile_perf LIMIT 1  h3_7 = 8730e0ae9ffffff h3_8 = 8830e0ae9dfffff h3_9 = 8930e0ae9d3ffff tile = POLYGON((126.837158203125 37.5576424267952, 126.842651367188 37.5576424267952, 126.842651367188 37.5532876459577, 126.837158203125 37.5532876459577, 126.837158203125 37.5576424267952)) <\/code><\/pre>\n<p>\u041a\u043e\u0433\u0434\u0430 \u044f \u043f\u043e\u043f\u044b\u0442\u0430\u043b\u0441\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0435 \u0432\u044b\u0448\u0435 \u043d\u0430 4-\u044f\u0434\u0435\u0440\u043d\u043e\u0439 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435 GCP e2-standard-4, \u044f \u043e\u0441\u0442\u0430\u0432\u0438\u043b \u0437\u0430\u0434\u0430\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430 \u043d\u043e\u0447\u044c, \u0438 \u043e\u043d\u043e \u0435\u0449\u0435 \u043d\u0435 \u0431\u044b\u043b\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e, \u043a\u043e\u0433\u0434\u0430  \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043b \u0435\u0433\u043e \u0443\u0442\u0440\u043e\u043c. \u041f\u043e\u0437\u0436\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0435 \u0432\u044b\u0448\u0435 \u043d\u0430 16-\u044f\u0434\u0435\u0440\u043d\u043e\u0439 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435 GCP e2-standard-16, \u0438 15,7 \u043c\u043b\u043d \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0431\u044b\u043b\u0438 \u043e\u0431\u043e\u0433\u0430\u0449\u0435\u043d\u044b \u0437\u0430 2 \u043c\u0438\u043d\u0443\u0442\u044b 21 \u0441\u0435\u043a\u0443\u043d\u0434\u0443. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u041e\u0417\u0423 \u0438\u043c\u0435\u043b\u043e \u0432\u0435\u0440\u0445\u043d\u044e\u044e \u0433\u0440\u0430\u043d\u0438\u0446\u0443 ~ 7 \u0413\u0411. \u042f \u043f\u043e\u0434\u0435\u043b\u0438\u043b\u0441\u044f \u044d\u0442\u0438\u043c \u0441 \u0418\u0441\u0430\u0430\u043a\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u0435\u0441\u0442\u044c \u043b\u0438 \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0435 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c.<\/p>\n<p>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0437 \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0433\u0443\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0447\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435. \u041d\u0435 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b, \u0447\u0442\u043e \u044d\u0442\u043e \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u043a DuckDB. \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u0431\u044b\u043b\u0430 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435, \u0447\u0435\u043c \u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434.<\/p>\n<pre><code class=\"sql\">CREATE TABLE mobile_perf2 AS     SELECT quadkey,            tile,            avg_d_kbps,            avg_u_kbps,            avg_lat_ms,            tests,            devices,            filename,             printf('%x',                   h3_latlng_to_cell(                       ST_Y(ST_CENTROID(ST_GEOMFROMTEXT(tile))),                       ST_X(ST_CENTROID(ST_GEOMFROMTEXT(tile))),                       7)::bigint) h3_7,             printf('%x',                   h3_latlng_to_cell(                       ST_Y(ST_CENTROID(ST_GEOMFROMTEXT(tile))),                       ST_X(ST_CENTROID(ST_GEOMFROMTEXT(tile))),                       8)::bigint) h3_8,             printf('%x',                   h3_latlng_to_cell(                       ST_Y(ST_CENTROID(ST_GEOMFROMTEXT(tile))),                       ST_X(ST_CENTROID(ST_GEOMFROMTEXT(tile))),                       9)::bigint) h3_9     FROM mobile_perf;<\/code><\/pre>\n<h2>\u042d\u043a\u0441\u043f\u043e\u0440\u0442 CSV<\/h2>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f CSV-\u0444\u0430\u0439\u043b \u0441\u0436\u0430\u0442\u044b\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e GZIP \u0434\u043b\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u0442\u0430\u0431\u043b\u0438\u0446\u044b mobile_perf. \u042d\u0442\u043e \u0431\u044b\u043b\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0434\u043b\u044f \u0432\u0435\u0440\u0441\u0438\u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043b\u0430 \u0448\u0435\u0441\u0442\u0438\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432 H3 \u0438\u0437 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u044b\u0448\u0435 \u043e\u0431\u043e\u0433\u0430\u0449\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"bash\">$ echo \"COPY (SELECT *               FROM mobile_perf)         TO 'mobile_perf.csv.gz'         WITH (HEADER 1,               COMPRESSION gzip);\" \\     | duckdb ~\/ookla.duckdb<\/code><\/pre>\n<p>\u0418\u043c\u0435\u0439\u0442\u0435 \u0432 \u0432\u0438\u0434\u0443, \u0447\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043c\u043e\u0436\u0435\u0442 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c DuckDB \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0437\u0430\u043f\u0438\u0441\u0438, \u0430 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u0430\u044f \u0432\u044b\u0448\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0440\u0435\u0436\u0438\u043c\u0430 \u0437\u0430\u043f\u0438\u0441\u0438. \u0415\u0441\u043b\u0438 \u0432\u044b \u0432\u0438\u0434\u0438\u0442\u0435 \u0447\u0442\u043e-\u0442\u043e \u0432\u0440\u043e\u0434\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e, \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u043e\u0436\u0434\u0430\u0442\u044c\u0441\u044f \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0435\u0433\u043e \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<pre><code>Error: unable to open database \"\/home\/mark\/mobile_perf.duckdb\": IO Error: Could not set lock on file \"\/home\/mark\/mobile_perf.duckdb\": Resource temporarily unavailable<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0435 \u0444\u0430\u0439\u043b \u0434\u043b\u044f \u043c\u0430\u0441\u0441\u043e\u0432\u043e\u0433\u043e \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044f, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0441\u0442\u043e\u0438\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0441\u0436\u0430\u0442\u044c \u0432\u044b\u0448\u0435\u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e pigz. \u0415\u0433\u043e \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0441\u0436\u0430\u0442\u0438\u044f \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f, \u043e\u043d \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u044f\u0434\u0435\u0440 \u0438 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u043c\u0435\u043d\u044c\u0448\u0435\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430, \u0447\u0435\u043c GNU GZIP.<\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0430\u0441\u044c \u0432 1,12 \u0440\u0430\u0437\u0430 \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0447\u0435\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0430\u044f, \u0441 \u0444\u0430\u0439\u043b\u043e\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u043d\u0430 2,5 \u041c\u0411 \u043c\u0435\u043d\u044c\u0448\u0435.<\/p>\n<pre><code class=\"sql\">$ echo \".mode csv         SELECT *         FROM mobile_perf;\" \\     | duckdb ~\/ookla.duckdb \\     | pigz -9 \\     > mobile_perf.csv.gz<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0440\u0430\u0437\u043c\u0435\u0440 \u0444\u0430\u0439\u043b\u0430 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435  \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 -1 \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u0444\u0430\u0439\u043b \u0432 1,6 \u0440\u0430\u0437\u0430 \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0442\u043e\u043b\u044c\u043a\u043e \u0432 1,25 \u0440\u0430\u0437\u0430 \u0431\u043e\u043b\u044c\u0448\u0435.<\/p>\n<p>\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u043f\u043e\u043b\u0435\u0439 \u0438 \u043a\u043b\u044e\u0447\u0438 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u0441\u0438\u043b\u044c\u043d\u043e \u0432\u043b\u0438\u044f\u044e\u0442 \u043d\u0430 \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c GZIP \u043a \u0441\u0436\u0430\u0442\u0438\u044e. \u0421 8 \u043f\u043e\u043b\u044f\u043c\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 40 320 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043d\u043e\u0432\u043e\u043a \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u043f\u043e\u043b\u0435\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u043d\u0430\u0439\u0442\u0438 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0441\u0436\u0438\u043c\u0430\u0435\u043c\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0437\u0430\u0439\u043c\u0435\u0442 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u0422\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u043f\u0435\u0440\u0435\u0443\u043f\u043e\u0440\u044f\u0434\u043e\u0447\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0438 \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0441\u0442\u043e\u043b\u0431\u0446\u0443 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u0438\u0437 \u043d\u0438\u0445 \u0441\u0436\u0438\u043c\u0430\u044e\u0442\u0441\u044f \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0441\u0435\u0433\u043e, \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e.<\/p>\n<pre><code class=\"bash\">$ COLUMNS=`echo \".mode list                  SELECT column_name                  FROM   information_schema.columns                  WHERE  table_name = 'mobile_perf';\" \\              | duckdb ~\/ookla.duckdb \\              | tail -n +2`  $ for COL in $COLUMNS; do       echo $COL       echo \"COPY (SELECT *                   FROM mobile_perf                   ORDER BY $COL)             TO 'mobile_perf.$COL.csv.gz'             WITH (HEADER 1,                   COMPRESSION gzip);\" \\         | duckdb ~\/ookla.duckdb   done<\/code><\/pre>\n<p>\u0414\u043b\u044f \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u044b\u0448\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0443\u043f \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0431\u0443\u0434\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0430 \u043d\u0435 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0441 xargs.<\/p>\n<p>DuckDB \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044f\u0434\u0435\u0440 \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u0432\u044b\u0448\u0435\u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b, \u043d\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u044f\u0434\u0440\u0435. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0441\u0442\u043e\u0438\u0442 \u043f\u0440\u043e\u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u0443\u044e \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 DuckDB \u0438 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u043b\u044e\u0447 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u0432 \u0441\u0432\u043e\u0435\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0435\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0432\u0430\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u043d\u044b\u0435 \u044f\u0434\u0440\u0430.<\/p>\n<p>\u041f\u0440\u0438 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0435 \u043f\u043e avg_u_kbps \u0431\u044b\u043b \u043f\u043e\u043b\u0443\u0447\u0435\u043d \u0444\u0430\u0439\u043b CSV, \u0441\u0436\u0430\u0442\u044b\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e GZIP, \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c 841 \u041c\u0411, \u0430 \u043f\u0440\u0438 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0435 \u043f\u043e quadkey \u2014 \u0444\u0430\u0439\u043b \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c 352 \u041c\u0411.<\/p>\n<p>\u0412\u044b\u0448\u0435\u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u043e\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435\u0445 16 \u0413\u0411 \u041e\u0417\u0423, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443 \u043c\u0435\u043d\u044f \u0431\u044b\u043b\u0438 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435. \u041f\u043e\u043c\u043d\u0438\u0442\u0435 \u043e\u0431 \u044d\u0442\u043e\u043c \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043d\u0430\u0431\u043e\u0440\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\/\u0438\u043b\u0438 \u0441\u0440\u0435\u0434 \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u043c \u043e\u0431\u044a\u0435\u043c\u043e\u043c \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438.<\/p>\n<p>ZStandard \u2014 \u044d\u0442\u043e \u0431\u043e\u043b\u0435\u0435 \u043d\u043e\u0432\u044b\u0439 \u043a\u043e\u043c\u043f\u0440\u0435\u0441\u0441\u043e\u0440 \u0434\u043b\u044f \u0441\u0436\u0430\u0442\u0438\u044f \u0431\u0435\u0437 \u043f\u043e\u0442\u0435\u0440\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u0436\u0438\u043c\u0430\u0442\u044c \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a GZIP, \u043d\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0432 3-6 \u0440\u0430\u0437 \u0431\u044b\u0441\u0442\u0440\u0435\u0435. \u042f \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u043f\u0440\u043e \u044d\u0442\u043e \u0432 \u0441\u0432\u043e\u0435\u043c \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u0438\u0441\u0442\u0441\u043a\u043e\u043c \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u0435 \u043f\u043e \u0441\u0436\u0430\u0442\u0438\u044e \u0431\u0435\u0437 \u043f\u043e\u0442\u0435\u0440\u044c. \u0415\u0441\u043b\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 \u0432\u0430\u0448\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0433\u0443\u0442 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b, \u0441\u0436\u0430\u0442\u044b\u0435 ZStandard, \u0438\u0445 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u0431\u044b\u0441\u0442\u0440\u0435\u0435.<\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u043e\u0441\u044c \u0432 3,4 \u0440\u0430\u0437\u0430 \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0447\u0435\u043c \u0435\u0433\u043e \u0430\u043d\u0430\u043b\u043e\u0433 GZIP, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0432\u044b\u0432\u043e\u0434 \u0431\u044b\u043b \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043d\u0430 6% \u0431\u043e\u043b\u044c\u0448\u0435.<\/p>\n<pre><code class=\"sql\">$ echo \"COPY (SELECT *               FROM mobile_perf)         TO 'mobile_perf.csv.zstd'         WITH (HEADER 1,               COMPRESSION zstd);\" \\     | duckdb ~\/ookla.duckdb<\/code><\/pre>\n<p>\u041e\u043f\u044f\u0442\u044c \u0436\u0435, \u0435\u0441\u043b\u0438 \u0432\u044b\u0448\u0435\u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u043e\u0435 \u0431\u044b\u043b\u043e \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u043f\u043e avg_u_kbps, \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d \u0444\u0430\u0439\u043b CSV \u0441\u043e \u0441\u0436\u0430\u0442\u0438\u0435\u043c ZStandard \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c 742 \u041c\u0411, \u0430 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u043f\u043e quadkey \u0434\u0430\u0441\u0442 \u0444\u0430\u0439\u043b \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c 367 \u041c\u0411.<\/p>\n<h3>\u042d\u043a\u0441\u043f\u043e\u0440\u0442 Parquet<\/h3>\n<p>\u0412 \u043c\u043e\u0435\u0439 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u00abFaster PostgreSQL To BigQuery Transfers\u00bb  \u0432 \u0431\u043b\u043e\u0433\u0435 \u043e\u0431\u0441\u0443\u0436\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 Microsoft Buildings, \u043d\u0430\u0431\u043e\u0440\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 GeoJSON \u043d\u0430 130M \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0432 \u0444\u0430\u0439\u043b Parquet, \u0441\u0436\u0430\u0442\u044b\u0439 Snappy. \u0412 \u0442\u043e\u043c \u043f\u043e\u0441\u0442\u0435 ClickHouse \u0441\u043f\u0440\u0430\u0432\u0438\u043b\u0441\u044f \u0441 \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u0432 1,38 \u0440\u0430\u0437\u0430 \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0447\u0435\u043c \u0435\u0433\u043e \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0438\u0439 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442. \u0422\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e \u0442\u0443 \u0436\u0435 \u0440\u0430\u0431\u043e\u0447\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0447\u0435\u0440\u0435\u0437 DuckDB.<\/p>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0432\u043d\u0435\u0448\u043d\u0438\u0439 SSD-\u043d\u0430\u043a\u043e\u043f\u0438\u0442\u0435\u043b\u044c \u043d\u0430 \u043c\u043e\u0435\u043c MacBook Pro \u0441 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u043e\u043c Intel 2020 \u0433\u043e\u0434\u0430 \u0432\u044b\u043f\u0443\u0441\u043a\u0430, ClickHouse \u0441\u043e\u0437\u0434\u0430\u043b \u0444\u0430\u0439\u043b \u0437\u0430 35,243 \u0441\u0435\u043a\u0443\u043d\u0434\u044b. \u041f\u043e\u0441\u043b\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0434 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u043d\u043e \u0441 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 DuckDB, \u044f \u0441\u043c\u043e\u0433 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0442\u0443 \u0436\u0435 \u0440\u0430\u0431\u043e\u0447\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0437\u0430 30,826 \u0441\u0435\u043a\u0443\u043d\u0434\u044b, \u0438, \u0435\u0441\u043b\u0438 \u0431\u044b \u044f \u0431\u044b\u043b \u0433\u043e\u0442\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432\u043e\u0441\u0435\u043c\u044c \u0444\u0430\u0439\u043b\u043e\u0432 Parquet \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u0434\u043d\u043e\u0433\u043e, \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u043b\u043e\u0441\u044c \u0434\u043e 25,146 \u0441\u0435\u043a\u0443\u043d\u0434\u044b. \u042d\u0442\u043e \u0431\u044b\u043b SQL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e.<\/p>\n<pre><code class=\"bash\">$ echo \"COPY (SELECT *               FROM read_ndjson_objects('California.jsonl'))         TO 'cali.duckdb.pq' (FORMAT 'PARQUET',                              CODEC  'Snappy',                              PER_THREAD_OUTPUT TRUE);\" \\     | duckdb<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 read_ndjson_objects \u0432\u043c\u0435\u0441\u0442\u043e read_json_objects, \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0443\u043b\u0443\u0447\u0448\u0438\u043b\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, PER_THREAD_OUTPUT TRUE \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u043e\u0432. \u0423\u0431\u0435\u0440\u0438\u0442\u0435 \u044d\u0442\u043e\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440, \u0435\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0444\u0430\u0439\u043b Parquet.<\/p>\n<p>\u041d\u043e \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u0441\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e, \u0442\u0430 \u0436\u0435 \u0440\u0430\u0431\u043e\u0447\u0430\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u0430\u044f \u043d\u0430 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435 Google Cloud e2-highcpu-32 \u0441 Ubuntu 20 LTS, \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0430, \u0447\u0442\u043e ClickHouse \u043f\u0440\u0435\u0432\u0437\u043e\u0448\u0435\u043b DuckDB \u0432 1,44 \u0440\u0430\u0437\u0430. \u041c\u0430\u0440\u043a \u0420\u0430\u0430\u0441\u0432\u0435\u043b\u0434\u0442 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043b, \u0447\u0442\u043e \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u0441\u0436\u0430\u0442\u0438\u044f DuckDB \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u0435 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0435\u0441\u0442\u044c \u0448\u0430\u043d\u0441, \u0447\u0442\u043e \u0432 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u043c \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043c\u044b \u0443\u0432\u0438\u0434\u0438\u043c \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u0440\u044b\u0432\u0430 \u0432 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 ClickHouse.<\/p>\n<p>PS. \u041d\u0443 \u0430 \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0442\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u043d\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0438 \u0445\u043e\u0442\u0438\u0442\u0435 \u043b\u0435\u0433\u043a\u043e \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0441\u0432\u0435\u0436\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 duckdb \u0441 \u043d\u043e\u0432\u044b\u043c\u0438 \u0444\u0438\u0447\u0430\u043c\u0438(\u043a\u0430\u043a \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 map_entries, map_values, map_keys \u0438\u0437 #<a href=\"https:\/\/github.com\/duckdb\/duckdb\/pull\/6522\" rel=\"noopener noreferrer nofollow\">6522<\/a>), \u0442\u043e \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0437\u044f\u0442\u044c <a href=\"https:\/\/github.com\/igor-suhorukov\/duckdb_geo_h3\" rel=\"noopener noreferrer nofollow\">\u044d\u0442\u043e\u0442 Docker \u0444\u0430\u0439\u043b<\/a> \u0437\u0430 \u043e\u0441\u043d\u043e\u0432\u0443.<\/p>\n<\/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\/post\/721832\/\"> https:\/\/habr.com\/ru\/post\/721832\/<\/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<p>\u0411\u043e\u043b\u044c\u0448\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0440\u043e\u0448\u043b\u043e\u0433\u043e \u0433\u043e\u0434\u0430 \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0441 Hexvarium. \u0411\u0430\u0437\u0438\u0440\u0443\u044e\u0449\u0430\u044f\u0441\u044f \u0432 \u0410\u0442\u0435\u0440\u0442\u043e\u043d\u0435, \u0448\u0442\u0430\u0442 \u041a\u0430\u043b\u0438\u0444\u043e\u0440\u043d\u0438\u044f, \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f \u0441\u0442\u0440\u043e\u0438\u0442 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u043f\u0442\u043e\u0432\u043e\u043b\u043e\u043a\u043e\u043d\u043d\u044b\u043c\u0438 \u0441\u0435\u0442\u044f\u043c\u0438. \u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0443 \u043d\u0438\u0445 \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u0442\u0435\u0439 \u0432 \u0440\u0430\u0439\u043e\u043d\u0435 \u0437\u0430\u043b\u0438\u0432\u0430, \u043d\u043e \u0443 \u043d\u0438\u0445 \u0435\u0441\u0442\u044c \u043f\u043b\u0430\u043d\u044b \u043f\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044e \u0432 \u0421\u0428\u0410.<\/p>\n<p>\u041c\u043e\u044f \u0440\u043e\u043b\u044c \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 30 \u043c\u0438\u043b\u043b\u0438\u0430\u0440\u0434\u043e\u0432 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0438\u0437 70 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438. \u042d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u0430\u043c\u0438, \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0449\u0438\u043c\u0438 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u043b\u0430\u043d\u044b \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u043e\u043f\u0442\u043e\u0432\u043e\u043b\u043e\u043a\u043e\u043d\u043d\u043e\u0439 \u0441\u0435\u0442\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e LocalSolver. \u0414\u0430\u043b\u0435\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043f\u0440\u0438\u043c\u0435\u0440 \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0437 \u0442\u0430\u043a\u0438\u0445 \u043f\u043b\u0430\u043d\u043e\u0432.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041d\u0430\u0448\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 PostGIS, ClickHouse \u0438 BigQuery. \u0414\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0442 \u0432 \u0441\u0430\u043c\u044b\u0445 \u0440\u0430\u0437\u043d\u044b\u0445, \u043d\u043e \u0447\u0430\u0449\u0435 \u043d\u0435 \u0432 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u0430\u0445. \u0417\u0430\u0442\u0435\u043c \u043c\u044b \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0438 \u043e\u0431\u043e\u0433\u0430\u0449\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435, \u0447\u0430\u0441\u0442\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e PostGIS \u0438\u043b\u0438 ClickHouse, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u0445 \u0432 BigQuery. \u0417\u0430\u0442\u0435\u043c \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u044b, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0435 \u0441 LocalSolver, \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u043e\u0447\u0438\u0449\u0435\u043d\u043d\u043e\u0439 \u0438 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0432 BigQuery.<\/p>\n<p>\u0410\u043d\u0430\u043b\u0438\u0437 \u043f\u043e\u0434\u043f\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u0432\u043e\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043e\u0432, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0447\u0430\u0441\u0442\u043e \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Unfolded. \u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0434\u043b\u044f Speedtest \u043e\u0442 Ookla \u043f\u0440\u043e\u0448\u043b\u044b\u043c \u043b\u0435\u0442\u043e\u043c. \u041c\u044b \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u043e \u0443\u0440\u043e\u0432\u043d\u044e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f H3 9 \u0438 \u0432\u0437\u044f\u043b\u0438 \u0441\u0430\u043c\u0443\u044e \u0432\u044b\u0441\u043e\u043a\u0443\u044e \u0441\u0440\u0435\u0434\u043d\u044e\u044e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438\u0437 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0448\u0435\u0441\u0442\u0438\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430, \u043d\u0430\u043d\u0435\u0441\u044f \u0438\u0445 \u043d\u0430 \u043a\u0430\u0440\u0442\u0443.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0430 \u0435\u0449\u0435 \u043e\u0434\u043d\u0430 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u0440\u0430\u0437\u043d\u0438\u0446\u0443 \u0432 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0448\u0438\u0440\u043e\u043a\u043e\u043f\u043e\u043b\u043e\u0441\u043d\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0432 \u043f\u0435\u0440\u0438\u043e\u0434 \u0441 \u0438\u044e\u043d\u044f \u043f\u043e \u043d\u043e\u044f\u0431\u0440\u044c \u043f\u0440\u043e\u0448\u043b\u043e\u0433\u043e \u0433\u043e\u0434\u0430. \u0414\u0430\u043d\u043d\u044b\u0435 \u0432 FCC \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u044b \u0448\u0438\u0440\u043e\u043a\u043e\u043f\u043e\u043b\u043e\u0441\u043d\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0438\u0437 \u0421\u0428\u0410.<\/p>\n<figure class=\"full-width\"><\/figure>\n<h2>\u0418\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 DuckDB<\/h2>\n<p>DuckDB \u2014 \u044d\u0442\u043e \u043f\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0430 \u041c\u0430\u0440\u043a\u0430 \u0420\u0430\u0430\u0441\u0432\u0435\u043b\u044c\u0434\u0442\u0430 \u0438 \u0425\u0430\u043d\u043d\u0435\u0441\u0430 \u041c\u044e\u043b\u0435\u0439\u0437\u0435\u043d\u0430. \u041e\u043d \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u0430 \u0441\u0442\u0440\u043e\u043a C++ \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0434\u0432\u043e\u0438\u0447\u043d\u044b\u0439 \u0444\u0430\u0439\u043b. \u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0438\u0434\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u0430\u043a\u0442\u0438\u0432\u043d\u043e: \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u043e\u043c\u043c\u0438\u0442\u043e\u0432 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 GitHub \u0443\u0434\u0432\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0447\u0442\u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u0433\u043e\u0434 \u0441 \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u0435\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0432 2018 \u0433\u043e\u0434\u0443. DuckDB \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043d\u0430\u043b\u0438\u0437\u0430\u0442\u043e\u0440 SQL PostgreSQL, \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 RE2 \u043e\u0442 Google \u0438 \u043e\u0431\u043e\u043b\u043e\u0447\u043a\u0443 SQLite.<\/p>\n<p>SQLite \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u044f\u0442\u044c \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445: NULL, INTEGER, REAL, TEXT \u0438 BLOB. \u041c\u0435\u043d\u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u044d\u0442\u043e \u0440\u0430\u0441\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u043b\u043e, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u0430 \u0441\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u0430 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0439 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0435 SELECT, \u0430 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u043e\u043b\u0435 \u043a\u0430\u043a \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u043d\u0435 \u043c\u043e\u0433\u043b\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u0442\u044c \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0438 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u044d\u0442\u0438\u0445 \u043f\u043e\u043b\u0435\u0439.<\/p>\n<p>\u041a \u0441\u0447\u0430\u0441\u0442\u044c\u044e, DuckDB \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 25 \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438, \u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439. \u0412\u0435\u0434\u0435\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u043d\u0430\u0434 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435\u043c, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u0442 \u0433\u0435\u043e\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 PostGIS \u041f\u043e\u043b\u0430 \u0420\u044d\u043c\u0441\u0438 \u0432 DuckDB. \u0418\u0441\u0430\u0430\u043a \u0411\u0440\u043e\u0434\u0441\u043a\u0438\u0439, \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u0438\u043d\u0436\u0435\u043d\u0435\u0440 Foursquare, \u043c\u0430\u0442\u0435\u0440\u0438\u043d\u0441\u043a\u043e\u0439 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 Unfolded, \u0442\u0430\u043a\u0436\u0435 \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043b \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 H3 \u0434\u043b\u044f DuckDB. \u0418 \u0445\u043e\u0442\u044f \u0435\u0449\u0435 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u043e, \u043f\u0440\u0435\u0434\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f \u043f\u043e\u043f\u044b\u0442\u043a\u0438 \u0432\u0441\u0442\u0440\u043e\u0438\u0442\u044c GDAL \u0447\u0435\u0440\u0435\u0437 \u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 Arrow \u0432 DuckDB.<\/p>\n<p>Min\/Max \u0438\u043d\u0434\u0435\u043a\u0441 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u0430 \u0441\u0442\u043e\u043b\u0431\u0446\u0430 \u0432 DuckDB. \u0418\u043c\u0435\u043d\u043d\u043e \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u044d\u0442\u043e\u043c\u0443 \u0442\u0438\u043f\u0443 \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445 OLAP \u0442\u0430\u043a \u0431\u044b\u0441\u0442\u0440\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f Parquet \u0438 JSON \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0431\u043e\u0440\u043a\u0435, \u0438 \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0445\u043e\u0440\u043e\u0448\u043e \u0437\u0430\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043e. \u0414\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432 Parquet \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0441\u0436\u0430\u0442\u0438\u0435 Snappy \u0438 ZStandard.<\/p>\n<p>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f DuckDB \u0445\u043e\u0440\u043e\u0448\u043e \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u0438 \u043e\u0447\u0435\u043d\u044c \u043b\u0430\u043a\u043e\u043d\u0438\u0447\u043d\u0430, \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438 \u0440\u044f\u0434\u043e\u043c \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0439.<\/p>\n<h2>\u0417\u0430\u043f\u0443\u0441\u043a DuckDB<\/h2>\n<p>\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f DuckDB \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 Geospatial \u0438 H3, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0432 \u044d\u0442\u043e\u043c \u043f\u043e\u0441\u0442\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u044e DuckDB \u0441 \u044d\u0442\u0438\u043c\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f\u043c\u0438.<\/p>\n<p>\u041f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0435 \u043d\u0438\u0436\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0431\u044b\u043b\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u044b \u043d\u0430 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0435 e2-standard-4 \u0432 Google Cloud \u043f\u043e\u0434 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c Ubuntu 20 LTS. \u042d\u0442\u0430 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u043c\u0430\u0448\u0438\u043d\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 4 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u0426\u041f \u0438 16 \u0413\u0411 \u041e\u0417\u0423. \u041e\u043d \u0431\u044b\u043b \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0432 \u041b\u043e\u0441-\u0410\u043d\u0434\u0436\u0435\u043b\u0435\u0441\u0435, \u0432 \u0440\u0435\u0433\u0438\u043e\u043d\u0435 us-west2-b, \u0438 \u0438\u043c\u0435\u0435\u0442 \u0441\u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u0435\u0440\u0441\u0438\u0441\u0442\u0435\u043d\u0442\u043d\u044b\u0439 \u0434\u0438\u0441\u043a \u043e\u0431\u044a\u0435\u043c\u043e\u043c 100 \u0413\u0411. \u0417\u0430\u043f\u0443\u0441\u043a \u0441\u0442\u043e\u0438\u043b 0,18 \u0434\u043e\u043b\u043b\u0430\u0440\u0430 \u0432 \u0447\u0430\u0441.<\/p>\n<p>\u041d\u0438\u0436\u0435 \u0431\u0443\u0434\u0443\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u043f\u0430\u043a\u0435\u0442\u044b \u041f\u041e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0432 \u044d\u0442\u043e\u043c \u043f\u043e\u0441\u0442\u0435.<\/p>\n<pre><code class=\"bash\">$ sudo apt update $ sudo apt install \\     awscli \\     build-essential \\     libssl-dev \\     pigz \\     unzip<\/code><\/pre>\n<p>\u0414\u043b\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f H3 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f CMake \u0432\u0435\u0440\u0441\u0438\u0438 3.20+, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0431\u0435\u0440\u0443 \u0435\u0433\u043e.<\/p>\n<pre><code class=\"bash\">$ cd ~ $ wget -c https:\/\/github.com\/Kitware\/CMake\/releases\/download\/v3.20.0\/cmake-3.20.0.tar.gz $ tar -xzf cmake-3.20.0.tar.gz $ cd cmake-3.20.0 $ .\/bootstrap --parallel=$(nproc) $ make -j$(nproc) $ sudo make install<\/code><\/pre>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u043a\u0430\u043a DuckDB, \u0442\u0430\u043a \u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 H3 \u0434\u043b\u044f \u043d\u0435\u0433\u043e. \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 geo \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u043e \u043a \u043a\u043e\u043c\u043c\u0438\u0442\u0443 DuckDB c817201, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u044e \u043a \u043d\u0435\u043c\u0443 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 H3.<\/p>\n<pre><code class=\"bash\">$ git clone https:\/\/github.com\/isaacbrodsky\/h3-duckdb ~\/duckdb_h3 $ cd ~\/duckdb_h3 $ git submodule update --init  $ cd duckdb $ git checkout c817201 $ cd ..  $ CMAKE_BUILD_PARALLEL_LEVEL=$(nproc) \\     make release<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u0442 \u0447\u0430\u0441\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 PostGIS \u0432 DuckDB.<\/p>\n<pre><code class=\"bash\">$ git clone https:\/\/github.com\/handstuyennn\/geo ~\/duckdb_geo $ cd ~\/duckdb_geo $ git submodule init $ git submodule update --recursive --remote  $ mkdir -p build\/release  $ cmake \\     .\/duckdb\/CMakeLists.txt \\     -DEXTERNAL_EXTENSION_DIRECTORIES=..\/geo \\     -DCMAKE_BUILD_TYPE=RelWithDebInfo \\     -DEXTENSION_STATIC_BUILD=1 \\     -DBUILD_TPCH_EXTENSION=1 \\     -DBUILD_PARQUET_EXTENSION=1 \\     -B build\/release  $ CMAKE_BUILD_PARALLEL_LEVEL=$(nproc) \\     cmake --build build\/release<\/code><\/pre>\n<p>\u0421\u043e\u0437\u0434\u0430\u043c \u0448\u0435\u043b\u043b \u0441\u043a\u0440\u0438\u043f\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442 \u0434\u0432\u043e\u0438\u0447\u043d\u044b\u0439 \u0444\u0430\u0439\u043b DuckDB \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u043d\u0435\u043f\u043e\u0434\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439.<\/p>\n<pre><code class=\"bash\">$ echo \"$HOME\/duckdb_geo\/build\/release\/duckdb -unsigned \\$@\" \\     | sudo tee \/usr\/sbin\/duckdb $ sudo chmod +x \/usr\/sbin\/duckdb<\/code><\/pre>\n<p>\u041d\u0430\u0441\u0442\u0440\u043e\u044e \u0444\u0430\u0439\u043b \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 DuckDB \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043e\u0431\u043e\u0438\u0445 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.<\/p>\n<pre><code class=\"bash\">$ vi ~\/.duckdbrc<\/code><\/pre>\n<pre><code class=\"bash\">.timer on LOAD '\/home\/mark\/duckdb_h3\/build\/release\/h3.duckdb_extension'; LOAD '\/home\/mark\/duckdb_geo\/build\/release\/extension\/geo\/geo.duckdb_extension'; <\/code><\/pre>\n<p>\u0417\u0430\u043f\u0443\u0449\u0443 DuckDB \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044e, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043b\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"bash\">$ duckdb<\/code><\/pre>\n<pre><code class=\"sql\">SELECT h3_cell_to_parent(CAST(586265647244115967 AS ubigint), 1) test; \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502        test        \u2502 \u2502       uint64       \u2502 \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524 \u2502 581764796395814911 \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/code><\/pre>\n<pre><code class=\"sql\">SELECT ST_MAKEPOINT(52.347113, 4.869454) test; \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502                    test                    \u2502 \u2502                 geography                  \u2502 \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524 \u2502 01010000001B82E3326E2C4A406B813D26527A1340 \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/code><\/pre>\n<p>\u041c\u043d\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c, \u0447\u0442\u043e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0442\u0438\u043f \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u043a\u0430\u0436\u0434\u044b\u043c \u0438\u043c\u0435\u043d\u0435\u043c \u043f\u043e\u043b\u044f.<\/p>\n<h2>\u041d\u0430\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 Ookla Speedtest<\/h2>\n<p>Ookla \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u0442 \u0441\u0432\u043e\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 Speedtest \u0432 AWS \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 Parquet. \u041d\u0438\u0436\u0435 \u044f \u0441\u043a\u0430\u0447\u0430\u044e \u043d\u0430\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 2022 \u0433\u043e\u0434\u0430 \u0434\u043b\u044f \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432.<\/p>\n<pre><code class=\"bash\">$ aws s3 sync \\     --no-sign-request \\     s3:\/\/ookla-open-data\/parquet\/performance\/type=mobile\/year=2022\/ \\     .\/<\/code><\/pre>\n<p>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0443\u0442\u0435\u0439 \u043a \u043f\u0430\u043f\u043a\u0430\u043c \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0430 \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0441\u0435\u043a\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f Apache Hive. \u042f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0442\u044b\u0440\u0435 \u0444\u0430\u0439\u043b\u0430 Parquet, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0443 \u0438\u0445 \u0432 \u043e\u0434\u043d\u0443 \u043f\u0430\u043f\u043a\u0443.<\/p>\n<pre><code class=\"bash\">$ mv quarter\\=*\/*.parquet .\/<\/code><\/pre>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u0440\u0430\u0437\u043c\u0435\u0440\u044b \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 \u0444\u0430\u0439\u043b\u043e\u0432. \u0412\u0441\u0435\u0433\u043e \u043e\u043d\u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 15 738 442 \u0441\u0442\u0440\u043e\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<pre><code class=\"bash\">$ ls -lht *.parquet  173M  2022-10-01_performance_mobile_tiles.parquet 180M  2022-07-01_performance_mobile_tiles.parquet 179M  2022-04-01_performance_mobile_tiles.parquet 174M  2022-01-01_performance_mobile_tiles.parquet<\/code><\/pre>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0430 \u0441\u0445\u0435\u043c\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0430\u044f \u0432 \u044d\u0442\u0438\u0445 \u0444\u0430\u0439\u043b\u0430\u0445 Parquet.<\/p>\n<pre><code class=\"sql\">$ echo \"SELECT name,                type,                converted_type         FROM parquet_schema('2022-10*.parquet');\" \\     | duckdb  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502    name    \u2502    type    \u2502 converted_type \u2502 \u2502  varchar   \u2502  varchar   \u2502    varchar     \u2502 \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524 \u2502 schema     \u2502 BOOLEAN    \u2502 UTF8           \u2502 \u2502 quadkey    \u2502 BYTE_ARRAY \u2502 UTF8           \u2502 \u2502 tile       \u2502 BYTE_ARRAY \u2502 UTF8           \u2502 \u2502 avg_d_kbps \u2502 INT64      \u2502 INT_64         \u2502 \u2502 avg_u_kbps \u2502 INT64      \u2502 INT_64         \u2502 \u2502 avg_lat_ms \u2502 INT64      \u2502 INT_64         \u2502 \u2502 tests      \u2502 INT64      \u2502 INT_64         \u2502 \u2502 devices    \u2502 INT64      \u2502 INT_64         \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 <\/code><\/pre>\n<p>Ookla \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0430 \u0441\u0436\u0430\u0442\u0438\u0435 Snappy \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u0442\u043e\u043b\u0431\u0446\u0430. DuckDB \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u044c \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0443 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u044b \u0434\u0430\u043d\u043d\u044b\u0435, \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0441\u0442\u043e\u043b\u0431\u0446\u0443. \u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0441\u0442\u043e\u043b\u0431\u0446\u0435 \u0442\u0430\u0439\u043b\u0430.<\/p>\n<pre><code class=\"sql\">$ echo \".mode line         SELECT *         EXCLUDE (stats_min_value,                  stats_max_value)         FROM parquet_metadata('2022-10-01_*.parquet')         WHERE path_in_schema = 'tile'         AND   row_group_id   = 0;\" \\     | duckdb                 file_name = 2022-10-01_performance_mobile_tiles.parquet            row_group_id = 0      row_group_num_rows = 665938   row_group_num_columns = 7         row_group_bytes = 31596007               column_id = 1             file_offset = 24801937              num_values = 665938          path_in_schema = tile                    type = BYTE_ARRAY               stats_min =               stats_max =        stats_null_count = 0    stats_distinct_count =             compression = SNAPPY               encodings = PLAIN_DICTIONARY, PLAIN, RLE, PLAIN       index_page_offset = 0  dictionary_page_offset = 3332511        data_page_offset = 3549527   total_compressed_size = 21469426 total_uncompressed_size = 124569336<\/code><\/pre>\n<h2>\u0418\u043c\u043f\u043e\u0440\u0442 Parquet \u0434\u0430\u043d\u043d\u044b\u0445<\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0433\u0443 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0447\u0435\u0442\u044b\u0440\u0435 \u0444\u0430\u0439\u043b\u0430 Parquet \u0432 DuckDB \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u0434\u043d\u043e\u0433\u043e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 SQL. \u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0442\u043e\u043b\u0431\u0435\u0446 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u0438\u043c\u0435\u043d\u0438 \u0444\u0430\u0439\u043b\u0430, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043a\u0430\u0436\u0434\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445. \u0418\u0437 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0445 706 \u041c\u0411 Parquet \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043a\u043e\u043b\u043e\u043d\u043a\u0430 \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u043b\u0438\u0441\u044c \u0432 \u0444\u0430\u0439\u043b DuckDB \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c 1,4 \u0413\u0411.<\/p>\n<pre><code class=\"sql\">$ echo \"CREATE TABLE mobile_perf AS         SELECT *         FROM read_parquet('*.parquet',                           filename=true);\" \\       | duckdb ~\/ookla.duckdb<\/code><\/pre>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 DuckDB HTTPFS, \u044f \u043c\u043e\u0433\u0443 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b Parquet \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0438\u0437 S3.<\/p>\n<pre><code class=\"sql\">$ echo \"INSTALL httpfs;         CREATE TABLE mobile_perf AS         SELECT *         FROM parquet_scan('s3:\/\/ookla-open-data\/parquet\/performance\/type=mobile\/year=2022\/*\/*.parquet',                           FILENAME=1);\" \\       | duckdb ~\/ookla.duckdb<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0435\u0433\u043e \u0435\u0449\u0435 \u043d\u0435\u0442, \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 HTTPFS \u0431\u0443\u0434\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-346742","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/346742","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=346742"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/346742\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=346742"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=346742"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=346742"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}