{"id":15499,"date":"2019-03-20T14:58:46","date_gmt":"2019-03-20T13:58:46","guid":{"rendered":"https:\/\/scriptfactory.pl\/blog\/?p=15499"},"modified":"2022-02-17T10:11:34","modified_gmt":"2022-02-17T09:11:34","slug":"wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record","status":"publish","type":"post","link":"https:\/\/scriptfactory.pl\/blog\/google\/wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record\/","title":{"rendered":"BigQuery i przetwarzanie plik\u00f3w"},"content":{"rendered":"\n<h2 id=\"wprowadzenie\">Wprowadzenie:<\/h2>\n\n\n\n<p>W zwi\u0105zku z rosn\u0105c\u0105 popularno\u015bci\u0105 platform chmurowych, takich jak\u00a0<a href=\"https:\/\/scriptfactory.pl\/blog\/category\/google\/\">Google<\/a>,\u00a0<a href=\"https:\/\/aws.amazon.com\/\">AWS\u00a0<\/a>i\u00a0<a href=\"https:\/\/azure.microsoft.com\/pl-pl\/\">Azure<\/a>, postanowili\u015bmy stworzy\u0107 seri\u0119 artyku\u0142\u00f3w, w kt\u00f3rych om\u00f3wimy podstawowe funkcjonalno\u015bci tych \u015brodowisk na konkretnych przyk\u0142adach u\u017cycia.<\/p>\n\n\n\n<p>Zacznijmy od Google oraz jednego z bardziej dojrza\u0142ych i u\u017cytecznych komponent\u00f3w, czyli <a href=\"https:\/\/cloud.google.com\/bigquery\/\">BigQuery<\/a>. B\u0119dziemy r\u00f3wnie\u017c wykorzystywa\u0107 Google&nbsp;<a href=\"https:\/\/cloud.google.com\/storage\/\">Cloud Storage<\/a> jako podstawowe miejsce przechowywania danych przetwarzanych w BigQuery. <\/p>\n\n\n\n<p>Podstawowe rzeczy, kt\u00f3re chcieliby\u015bmy zweryfikowa\u0107 w tym artykule:<\/p>\n\n\n\n<ul><li>jak trudno jest utworzy\u0107 proste \u015brodowisko, pozwalaj\u0105ce procesowa\u0107 pliki CDR (struktura opisana poni\u017cej) z 100 mln rekord\u00f3w,<\/li><li>jaki jest koszt platformy u\u017cywanej w trakcie naszego testu,<\/li><li>jaka jest wydajno\u015b\u0107 platformy<\/li><\/ul>\n\n\n\n<h2 id=\"use-case\">Use Case:<\/h2>\n\n\n\n<p>Jako przyk\u0142ad u\u017cycia wybrali\u015bmy przetwarzanie plik\u00f3w zwanych CDR, czyli call detail record, s\u0105 to pliki cz\u0119sto wykorzystywane w bran\u017cy telekomunikacyjnej. Ich formaty mog\u0105 by\u0107 najr\u00f3\u017cniejsze, nie ma te\u017c jednego przyj\u0119tego standardu. Na potrzeby tego przyk\u0142adu przygotowali\u015bmy nast\u0119puj\u0105cy format plik\u00f3w: <\/p>\n\n\n\n<p>Id INT, CustomerId INT, DestinationPhone INT, CallDate DATE, CallTime STRING, Duration INT, Network STRING, Location STRING, NetAmount NUMBER, Amount NUMBER &#8211; NetAmount i Amount s\u0105 przechowywane w pliku \u017ar\u00f3d\u0142owym jako INT, jednak odpowiadaj\u0105 liczbie o precyzji 2 miejsc po przecinku, np. 101 oznacza 1.01.<\/p>\n\n\n\n<p>Przyk\u0142adowe dane:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" width=\"953\" height=\"63\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/6a.png\" alt=\"\" class=\"wp-image-15503\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/6a.png 953w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/6a-300x20.png 300w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/6a-768x51.png 768w\" sizes=\"(max-width: 953px) 100vw, 953px\" \/><\/figure>\n\n\n\n<p>Przeprowadzimy na nich proste agregacje w celu sprawdzenia wydajno\u015bci \u015brodowiska i&nbsp;oszacowania z\u0142o\u017cono\u015bci wdro\u017cenia nowej platformy.<\/p>\n\n\n\n<p>Komponent Google BigQuery jest chmurow\u0105, komercyjn\u0105 implementacj\u0105 narz\u0119dzia znanego wcze\u015bniej jako&nbsp;<a href=\"https:\/\/en.wikipedia.org\/wiki\/Dremel_(software)\">Dremel<\/a>. Google zaprojektowa\u0142 je z my\u015bl\u0105 o przetwarzaniu du\u017cych zbior\u00f3w danych w rozproszonym \u015brodowisku (podobnie jak&nbsp;<a href=\"https:\/\/hadoop.apache.org\/\">Apache Hadoop<\/a>) \u2013 Dremel wykorzystuje dwa podstawowe za\u0142o\u017cenia architekturalne, (a) Columnar Storage (b) Tree Architecture \u2013 czyli wielowarstwowa struktura serwer\u00f3w. Po\u0142\u0105czenie tych za\u0142o\u017ce\u0144 oraz skali \u2013 kilka tysiecy serwer\u00f3w dzia\u0142aj\u0105cych r\u00f3wnocze\u015bnie \u2013 BigQuery jest w stanie z du\u017c\u0105 wydajno\u015bci\u0105 przetwarza\u0107 PB danych. Na dodatek Google zadba\u0142o o odpowiedni\u0105 wycen\u0119 \u015brodowiska, dostawca pobiera op\u0142at\u0119 za ilo\u015b\u0107 przechowywanych i transferowanych GB. Czyli w przypadku, kiedy zbiory nie s\u0105 du\u017ce oraz wykorzystujemy je tylko w okre\u015blony, przewidywalny spos\u00f3b \u2013 BigQuery okazuje si\u0119 du\u017co ta\u0144szym rozwi\u0105zaniem ni\u017c inne bazy danych, bez konieczno\u015bci utrzymania skomplikowanej infrastruktury. W kolejnych artyku\u0142ach b\u0119dziemy por\u00f3wnywa\u0107 to rozwi\u0105zanie do konkurencji oraz do klastra Apache Hadoop, kt\u00f3ry zbudowali\u015bmy na platformie DigitalOcean.<\/p>\n\n\n\n<h2 id=\"pierwsze-kroki\">Pierwsze kroki:<\/h2>\n\n\n\n<p>Aby zacz\u0105\u0107 nasz\u0105 przygod\u0119 z Google BigQuery, potrzebujemy mie\u0107 za\u0142o\u017cone konto Google \u2013 nie ma tutaj wi\u0119kszego znaczenia, czy jest to konto indywidualne czy korporacyjne. Logujemy si\u0119 na <a href=\"https:\/\/console.cloud.google.com\/\">Google Cloud Console<\/a>&nbsp;\u2013 Google oferuje \u201efree trial\u201d w postaci 300$ w prezencie na 12 miesi\u0119cy. <\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" width=\"412\" height=\"231\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/1.png\" alt=\"\" class=\"wp-image-15507\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/1.png 412w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/1-300x168.png 300w\" sizes=\"(max-width: 412px) 100vw, 412px\" \/><\/figure><\/div>\n\n\n\n<p>Aby m\u00f3c komercyjnie wykorzystywa\u0107 mo\u017cliwo\u015bci tej platformy, nale\u017cy w zak\u0142adce po lewej stronie wybra\u0107 Billing i przej\u015b\u0107 przez Wizard, uzupe\u0142niaj\u0105c nasze dane (dane firmy, je\u015bli chcemy otrzymywa\u0107 faktury, dane karty kredytowej).<\/p>\n\n\n\n<p>Po ich uzupe\u0142nieniu mo\u017cemy przej\u015b\u0107 do korzystania z platformy, mamy ju\u017c za\u0142o\u017cony sw\u00f3j inicjalny projekt. W ramach niego b\u0119dziemy tworzy\u0107 zasoby, np. dyski, serwery, a tak\u017ce korzysta\u0107 z us\u0142ug, takich jak BigQuery. Koncepcja kilku projekt\u00f3w w ramach jednego konta, pozwala na podejmowanie r\u00f3\u017cnych inicjatyw\/dzia\u0142a\u0144 r\u00f3wnocze\u015bnie.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" width=\"839\" height=\"205\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/3.png\" alt=\"\" class=\"wp-image-15508\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/3.png 839w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/3-300x73.png 300w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/3-768x188.png 768w\" sizes=\"(max-width: 839px) 100vw, 839px\" \/><\/figure>\n\n\n\n<h2 id=\"google-cloud-storage-gcs\">Google Cloud Storage (GCS):<\/h2>\n\n\n\n<p>W celu skorzystania z mo\u017cliwo\u015bci BigQuery zak\u0142adamy Bucket w us\u0142udze Google Cloud Storage. Bucket jest naszym odpowiednikiem macierzy dyskowej wykorzystywanej przez znaczn\u0105 wi\u0119kszo\u015b\u0107 us\u0142ug Google. Fizycznie Cloud Storage odpowiada architekturze HDFS (Apache Hadoop), czy Blob Storage (Azure). Zapewnia dystrybucj\u0119 danych w ramach rozproszonego \u015brodowiska, pokrywaj\u0105c jednocze\u015bnie potrzeby bezpiecze\u0144stwa czy wydajno\u015bci. W celu utworzenia Bucket-u nale\u017cy z lewego menu wybra\u0107 <strong>Storage-&gt;Browse<\/strong>. <\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" width=\"422\" height=\"167\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/4.png\" alt=\"\" class=\"wp-image-15510\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/4.png 422w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/4-300x119.png 300w\" sizes=\"(max-width: 422px) 100vw, 422px\" \/><\/figure><\/div>\n\n\n\n<p>Wybieramy <strong>Create bucket:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" width=\"427\" height=\"234\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/5.png\" alt=\"\" class=\"wp-image-15512\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/5.png 427w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/5-300x164.png 300w\" sizes=\"(max-width: 427px) 100vw, 427px\" \/><\/figure>\n\n\n\n<p>W nast\u0119pnym\nkroku okre\u015blamy takie atrybuty, jak unikaln\u0105 nazw\u0119, lokalizacj\u0119 danych oraz nadajemy\nuprawnienia do zasob\u00f3w: <\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" width=\"600\" height=\"743\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/6.png\" alt=\"\" class=\"wp-image-15511\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/6.png 600w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/6-242x300.png 242w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><\/figure><\/div>\n\n\n\n<p>Po wygenerowaniu\nBucket-u tworzymy katalogi, najpierw&nbsp;<strong>cdr,&nbsp;<\/strong>nast\u0119pnie&nbsp;<strong>stg<\/strong>. Pos\u0142u\u017c\u0105 nam one do umieszczenia\ndanych wej\u015bciowych z plikami cdr. Dane testowe to zbi\u00f3r 10 plik\u00f3w CSV, ka\u017cdy o\nrozmiarze oko\u0142o 800 MB \u2013 ca\u0142y zbi\u00f3r to niemal 8 GB \u2013 liczba rekord\u00f3w to ponad\n100 mln.<\/p>\n\n\n\n<p>Za pomoc\u0105\nprzycisku <strong>Upload files<\/strong>&nbsp;dodajemy dane do naszego bucketu w lokalizacji<strong>&nbsp;sf-001\/cdr\/stg\/<\/strong><\/p>\n\n\n\n<p>Dane poprzez przycisk <strong>Upload files<\/strong> dodajemy do naszego bucket-u w lokalizacji<strong> sf-001\/cdr\/stg\/<\/strong><\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" width=\"502\" height=\"253\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/7_2.png\" alt=\"\" class=\"wp-image-15513\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/7_2.png 502w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/7_2-300x151.png 300w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/7_2-500x253.png 500w\" sizes=\"(max-width: 502px) 100vw, 502px\" \/><\/figure><\/div>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" width=\"512\" height=\"439\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/7_3.png\" alt=\"\" class=\"wp-image-15514\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/7_3.png 512w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/7_3-300x257.png 300w\" sizes=\"(max-width: 512px) 100vw, 512px\" \/><\/figure><\/div>\n\n\n\n<h2 id=\"google-bigquery-bq\">Google BigQuery (BQ):<\/h2>\n\n\n\n<p>Po zasileniu Cloud Storage udajemy si\u0119 do us\u0142ugi BigQuery.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" width=\"740\" height=\"513\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/8.png\" alt=\"\" class=\"wp-image-15515\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/8.png 740w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/8-300x208.png 300w\" sizes=\"(max-width: 740px) 100vw, 740px\" \/><\/figure><\/div>\n\n\n\n<p>W pierwszej kolejno\u015bci tworzymy dataset &#8211; odpowiada on bazie danych w instancji SQL Server, lub Schematowi w bazie Oracle. Jest wi\u0119c logicznym pogrupowaniem tabel pod jedn\u0105 encj\u0105.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" width=\"498\" height=\"298\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/9.png\" alt=\"\" class=\"wp-image-15516\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/9.png 498w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/9-300x180.png 300w\" sizes=\"(max-width: 498px) 100vw, 498px\" \/><\/figure><\/div>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" width=\"288\" height=\"193\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/10.png\" alt=\"\" class=\"wp-image-15517\"\/><\/figure><\/div>\n\n\n\n<p>Maj\u0105c nasz\u0105\n\u201ebaz\u0119 danych\u201d, mo\u017cemy utworzy\u0107 w niej tabel\u0119, w sekcji&nbsp;<strong>Source <\/strong>jest mo\u017cliwo\u015b\u0107 wybrania do niej \u017ar\u00f3d\u0142a\ndanych (tabela mo\u017ce by\u0107 te\u017c pusta), wskazujemy wi\u0119c nasz bucket na Google Cloud\nStorage, wildcard&nbsp;<strong>*<\/strong>&nbsp;oznacza, \u017ce chcemy skorzysta\u0107 ze wszystkich\nplik\u00f3w w lokalizacji&nbsp;<strong>sf-001\/cdr\/stg\/<\/strong>,&nbsp;format plik\u00f3w to CSV (s\u0105 r\u00f3wnie\u017c formaty, takie jak AVRO czy\nParquet). Okre\u015blamy, czy tabela ma by\u0107&nbsp;<strong>native table<\/strong>&nbsp;(fizycznie przechowywana w\nklastrze ukrytym pod us\u0142ug\u0105 BigQuery) czy&nbsp;<strong>external\ntable<\/strong>&nbsp;(tylko\nlogiczna warstwa okre\u015blaj\u0105ca metadane tabeli). Wybieramy&nbsp;<strong>Auto-detect<\/strong>&nbsp;na schemacie tabeli, atrybut&nbsp;<strong>Field\ndelimiter \u201e;\u201d&nbsp;<\/strong>oraz, aby pierwszy\nwiersz (nag\u0142\u00f3wek) w plikach zosta\u0142 pomini\u0119ty:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" width=\"657\" height=\"928\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/11.png\" alt=\"\" class=\"wp-image-15519\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/11.png 657w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/11-212x300.png 212w\" sizes=\"(max-width: 657px) 100vw, 657px\" \/><\/figure><\/div>\n\n\n\n<h3 id=\"krok-1\">Krok 1:<\/h3>\n\n\n\n<p>Mo\u017cemy odpyta\u0107 utworzon\u0105 tabel\u0119:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" width=\"925\" height=\"623\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/12.png\" alt=\"\" class=\"wp-image-15520\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/12.png 925w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/12-300x202.png 300w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/12-768x517.png 768w\" sizes=\"(max-width: 925px) 100vw, 925px\" \/><\/figure><\/div>\n\n\n\n<p>Mo\u017cemy r\u00f3wnie\u017c obejrze\u0107 co\u015b w rodzaju planu zapytania:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" width=\"1024\" height=\"349\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/13-1024x349.png\" alt=\"\" class=\"wp-image-15521\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/13-1024x349.png 1024w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/13-300x102.png 300w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/13-768x262.png 768w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/13.png 1603w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n\n<p>Dok\u0142adna liczba rekord\u00f3w w tabeli:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" width=\"301\" height=\"127\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/15.png\" alt=\"\" class=\"wp-image-15522\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/15.png 301w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/15-300x127.png 300w\" sizes=\"(max-width: 301px) 100vw, 301px\" \/><\/figure><\/div>\n\n\n\n<p>Na tym etapie mo\u017cemy ju\u017c skorzysta\u0107 z danych w raportowaniu jako \u017ar\u00f3d\u0142a dla aplikacji lub innych us\u0142ug Google. Jednak external table nie s\u0105 tak wydajne, jak native tables, dodatkowo wiemy, \u017ce wykryty schemat tabeli nie do ko\u0144ca pokrywa si\u0119 z tym, czego by\u015bmy oczekiwali. <\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" width=\"521\" height=\"564\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/14.png\" alt=\"\" class=\"wp-image-15523\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/14.png 521w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/14-277x300.png 277w\" sizes=\"(max-width: 521px) 100vw, 521px\" \/><\/figure><\/div>\n\n\n\n<p>NetAmount , Amount &#8211; powinny by\u0107 liczbami o precyzji 2 miejsc po przecinku, a nie INTEGEREM. Podobnie CallTime powinno by\u0107 typu TIME. Aby to naprawi\u0107 utworzymy wi\u0119c kolejn\u0105 tabel\u0119 typu native:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" width=\"657\" height=\"948\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/16-1.png\" alt=\"\" class=\"wp-image-15525\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/16-1.png 657w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/16-1-208x300.png 208w\" sizes=\"(max-width: 657px) 100vw, 657px\" \/><\/figure><\/div>\n\n\n\n<h3 id=\"krok-2\">Krok 2:<\/h3>\n\n\n\n<p>Nast\u0119pnie wykonamy polecenie SQL:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\"><p>INSERT INTO cdrdata.rep_cdr(Id, CustomerId, DestinationPhone, CallDate, CallTime,<br>   Duration,Network, Location, NetAmount, Amount, CallType)<br> SELECT <br>   Id, <br>   CustomerId, <br>   DestinationPhone, <br>   CallDate,<br>   CAST(CONCAT(CallTime,&#8221;:00&#8243;) AS TIME),<br>   Duration,<br>   Network,<br>   Location,<br>   CAST(NetAmount AS NUMERIC)\/100,<br>   CAST(Amount AS NUMERIC)\/100,<br>   CallType<br> FROM cdrdata.stg_cdr<\/p><\/blockquote>\n\n\n\n<p>Operacja zako\u0144czona sukcesem:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" width=\"506\" height=\"124\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/17.png\" alt=\"\" class=\"wp-image-15527\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/17.png 506w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/17-300x74.png 300w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/17-500x124.png 500w\" sizes=\"(max-width: 506px) 100vw, 506px\" \/><\/figure><\/div>\n\n\n\n<p>Por\u00f3wnamy teraz wydajno\u015b\u0107 tabel przy prostej agregacji ze zbioru stg_cdr (external table) oraz rep_cdr (native table) na podstawie poni\u017cszego zapytania SQL:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\"><p>SELECT SUM(Duration) NbrOfSms,CustomerId <br> FROM 'grounded-garage-234712.cdrdata.rep_cdr&#8217;<br> WHERE CallType = 'sms&#8217;<br> GROUP BY CustomerId<br> ORDER BY 1 DESC LIMIT 100<\/p><\/blockquote>\n\n\n\n<p>Oto wyniki odpowiednio stg_cdr i rep_cdr:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" width=\"355\" height=\"329\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/19.png\" alt=\"\" class=\"wp-image-15528\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/19.png 355w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/19-300x278.png 300w\" sizes=\"(max-width: 355px) 100vw, 355px\" \/><\/figure><\/div>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" width=\"343\" height=\"320\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/18.png\" alt=\"\" class=\"wp-image-15529\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/18.png 343w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/18-300x280.png 300w\" sizes=\"(max-width: 343px) 100vw, 343px\" \/><\/figure><\/div>\n\n\n\n<p>Jak wida\u0107 na powy\u017cszych zdj\u0119ciach, zapytanie SQL na native table jest ponad 10x szybsze ni\u017c na tabeli external table. Wynika to z faktu, \u017ce native table analogicznie jak w Apache Hive (na Apache Hadoop) s\u0105 przechowywane w formacie kolumnowym i skompresowanym. Dzi\u0119ki czemu ka\u017cdy node klastra wykonuje mniejsz\u0105 ilo\u015b\u0107 operacji i jest w stanie szybciej zwr\u00f3ci\u0107 dane.<\/p>\n\n\n\n<p>Na tym etapie na bazie powy\u017cszego zapytania dla tabeli rep_cdr mo\u017cemy r\u00f3wnie\u017c utworzy\u0107 widok przy pomocy GUI:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" width=\"523\" height=\"300\" src=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/20.png\" alt=\"\" class=\"wp-image-15530\" srcset=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/20.png 523w, https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/20-300x172.png 300w\" sizes=\"(max-width: 523px) 100vw, 523px\" \/><\/figure><\/div>\n\n\n\n<h2 id=\"podsumowanie\">Podsumowanie:<\/h2>\n\n\n\n<p>Mo\u017cemy teraz odpowiedzie\u0107 na kilka pyta\u0144 postawionych na pocz\u0105tku:<\/p>\n\n\n\n<ul><li>Uruchomienie \u015brodowiska wraz z rejestracj\u0105 konta, utworzeniem Cloud Storage oraz tabele BigQuery zaj\u0119\u0142o 30min &#8211; 1h, by\u0142o intuicyjne i proste. Us\u0142uga BigQuery nie ma (w przeciwie\u0144stwie do Azure Data Warehouse r\u00f3\u017cnych opcji wydajno\u015bci us\u0142ugi) , wi\u0119c korzystali\u015bmy z domy\u015blnych opcji przy rejestracji us\u0142ugi.<\/li><li> koszt platformy wykorzystanej w trakcie naszych test\u00f3w wyni\u00f3s\u0142 0.00z\u0142, nie posiadali\u015bmy du\u017co danych, ani nie utworzyli\u015bmy us\u0142ug na do\u015b\u0107 d\u0142ugi czas aby Google zd\u0105\u017cy\u0142o nas obci\u0105\u017cy\u0107.<\/li><li>wydajno\u015b\u0107 BigQuery jest bardzo dobra, us\u0142uga skaluje zasoby w zale\u017cno\u015bci od aktualnego obci\u0105\u017cenia zapewniaj\u0105c zawsze adekwatne wyniki.<\/li><\/ul>\n\n\n\n<p>Jak wida\u0107 wykonanie podstawowych operacji na platformie Google Cloud nie musi by\u0107 trudne ani czasoch\u0142onne. \u015arodowisko zadziwia stabilno\u015bci\u0105, wydajno\u015bci\u0105 i prostot\u0105. W nast\u0119pnych artyku\u0142ach poka\u017cemy, jak mo\u017cna wykorzysta\u0107 polecenia konsolowe&nbsp;<strong>gcloud<\/strong>&nbsp;do automatyzacji operacji w ramach Google Cloud. W naszej opinii jest to jedna z lepszych platform na rynku.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wprowadzenie: W zwi\u0105zku z rosn\u0105c\u0105 popularno\u015bci\u0105 platform chmurowych, takich jak\u00a0Google,\u00a0AWS\u00a0i\u00a0Azure, postanowili\u015bmy stworzy\u0107 seri\u0119 artyku\u0142\u00f3w, w kt\u00f3rych om\u00f3wimy podstawowe funkcjonalno\u015bci tych \u015brodowisk na konkretnych przyk\u0142adach u\u017cycia. Zacznijmy od Google oraz jednego z bardziej dojrza\u0142ych i u\u017cytecznych komponent\u00f3w, czyli BigQuery. B\u0119dziemy r\u00f3wnie\u017c wykorzystywa\u0107 Google&nbsp;Cloud Storage jako podstawowe miejsce przechowywania danych przetwarzanych w BigQuery. Podstawowe rzeczy, kt\u00f3re chcieliby\u015bmy zweryfikowa\u0107 w tym artykule: jak trudno jest utworzy\u0107 proste \u015brodowisko, pozwalaj\u0105ce procesowa\u0107 pliki CDR (struktura opisana poni\u017cej) z 100 mln rekord\u00f3w, jaki jest koszt platformy u\u017cywanej w trakcie naszego testu, jaka jest wydajno\u015b\u0107 platformy Use Case: Jako przyk\u0142ad u\u017cycia wybrali\u015bmy przetwarzanie plik\u00f3w zwanych CDR, czyli call detail record, s\u0105 to pliki cz\u0119sto wykorzystywane w bran\u017cy telekomunikacyjnej. Ich formaty mog\u0105 by\u0107 najr\u00f3\u017cniejsze, nie ma te\u017c jednego przyj\u0119tego standardu. Na potrzeby tego przyk\u0142adu przygotowali\u015bmy nast\u0119puj\u0105cy format plik\u00f3w: Id INT, CustomerId INT, DestinationPhone INT, CallDate DATE, CallTime STRING, Duration INT, Network STRING, Location STRING, NetAmount NUMBER, Amount NUMBER &#8211; NetAmount i Amount s\u0105 przechowywane w pliku \u017ar\u00f3d\u0142owym jako INT, jednak odpowiadaj\u0105 liczbie o precyzji 2 miejsc po przecinku, np. 101 oznacza 1.01. Przyk\u0142adowe dane: Przeprowadzimy na nich proste agregacje w celu sprawdzenia wydajno\u015bci \u015brodowiska i&nbsp;oszacowania z\u0142o\u017cono\u015bci wdro\u017cenia nowej platformy. Komponent Google BigQuery jest chmurow\u0105, komercyjn\u0105 implementacj\u0105 narz\u0119dzia znanego [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":15504,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[89,88,91],"tags":[96,99,93,79,97,77,81,98,95,94],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v18.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<meta name=\"description\" content=\"Przyk\u0142ad wykorzystania platformy Google BigQuery do przetwarzanie plik\u00f3w p\u0142askich w w oparciu o tzw. pliki CDR.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/scriptfactory.pl\/blog\/google\/wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record\/\" \/>\n<meta property=\"og:locale\" content=\"pl_PL\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"BigQuery i przetwarzanie plik\u00f3w - SCRIPT FACTORY | BI BLOG\" \/>\n<meta property=\"og:description\" content=\"Przyk\u0142ad wykorzystania platformy Google BigQuery do przetwarzanie plik\u00f3w p\u0142askich w w oparciu o tzw. pliki CDR.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/scriptfactory.pl\/blog\/google\/wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record\/\" \/>\n<meta property=\"og:site_name\" content=\"SCRIPT FACTORY | BI BLOG\" \/>\n<meta property=\"article:published_time\" content=\"2019-03-20T13:58:46+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-02-17T09:11:34+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/1_A8liBoeAwAZg7rDu394jYg.png\" \/>\n\t<meta property=\"og:image:width\" content=\"500\" \/>\n\t<meta property=\"og:image:height\" content=\"213\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Napisane przez\" \/>\n\t<meta name=\"twitter:data1\" content=\"Wojciech Zduniak\" \/>\n\t<meta name=\"twitter:label2\" content=\"Szacowany czas czytania\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minut\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/scriptfactory.pl\/blog\/#website\",\"url\":\"https:\/\/scriptfactory.pl\/blog\/\",\"name\":\"SCRIPT FACTORY | BI BLOG\",\"description\":\"Blog techniczny pokazuj\u0105cy jak poradzi\u0107 sobie z najwi\u0119kszymi problemami\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/scriptfactory.pl\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"pl-PL\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/scriptfactory.pl\/blog\/google\/wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record\/#primaryimage\",\"inLanguage\":\"pl-PL\",\"url\":\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/1_A8liBoeAwAZg7rDu394jYg.png\",\"contentUrl\":\"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/1_A8liBoeAwAZg7rDu394jYg.png\",\"width\":500,\"height\":213},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/scriptfactory.pl\/blog\/google\/wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record\/#webpage\",\"url\":\"https:\/\/scriptfactory.pl\/blog\/google\/wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record\/\",\"name\":\"BigQuery i przetwarzanie plik\u00f3w - SCRIPT FACTORY | BI BLOG\",\"isPartOf\":{\"@id\":\"https:\/\/scriptfactory.pl\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/scriptfactory.pl\/blog\/google\/wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record\/#primaryimage\"},\"datePublished\":\"2019-03-20T13:58:46+00:00\",\"dateModified\":\"2022-02-17T09:11:34+00:00\",\"author\":{\"@id\":\"https:\/\/scriptfactory.pl\/blog\/#\/schema\/person\/e39ed2fd20838bb0d87220cc919e2f21\"},\"description\":\"Przyk\u0142ad wykorzystania platformy Google BigQuery do przetwarzanie plik\u00f3w p\u0142askich w w oparciu o tzw. pliki CDR.\",\"breadcrumb\":{\"@id\":\"https:\/\/scriptfactory.pl\/blog\/google\/wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record\/#breadcrumb\"},\"inLanguage\":\"pl-PL\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/scriptfactory.pl\/blog\/google\/wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/scriptfactory.pl\/blog\/google\/wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Strona g\u0142\u00f3wna\",\"item\":\"https:\/\/scriptfactory.pl\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"BigQuery i przetwarzanie plik\u00f3w\"}]},{\"@type\":\"Person\",\"@id\":\"https:\/\/scriptfactory.pl\/blog\/#\/schema\/person\/e39ed2fd20838bb0d87220cc919e2f21\",\"name\":\"Wojciech Zduniak\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/scriptfactory.pl\/blog\/#personlogo\",\"inLanguage\":\"pl-PL\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/5d954513663b7b760bcae861966c5069?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/5d954513663b7b760bcae861966c5069?s=96&d=mm&r=g\",\"caption\":\"Wojciech Zduniak\"},\"description\":\"BI zajmuj\u0119 si\u0119 kilkana\u015bcie lat, od Microsoft po Teradat\u0119, od on-premise do cloud, od pojedy\u0144czych serwer\u00f3w po klastr\u00f3w obliczeniowych. Temat jest tak szeroki i ciekawy \u017ce postanowi\u0142em opisa\u0107 po kolei wszystko co wiem i z czym si\u0119 zetkn\u0105\u0142em. Mam nadzieje \u017ce b\u0119dzie Wam si\u0119 podoba\u0107 ta lektura :)\",\"url\":\"https:\/\/scriptfactory.pl\/blog\/author\/admin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"description":"Przyk\u0142ad wykorzystania platformy Google BigQuery do przetwarzanie plik\u00f3w p\u0142askich w w oparciu o tzw. pliki CDR.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/scriptfactory.pl\/blog\/google\/wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record\/","og_locale":"pl_PL","og_type":"article","og_title":"BigQuery i przetwarzanie plik\u00f3w - SCRIPT FACTORY | BI BLOG","og_description":"Przyk\u0142ad wykorzystania platformy Google BigQuery do przetwarzanie plik\u00f3w p\u0142askich w w oparciu o tzw. pliki CDR.","og_url":"https:\/\/scriptfactory.pl\/blog\/google\/wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record\/","og_site_name":"SCRIPT FACTORY | BI BLOG","article_published_time":"2019-03-20T13:58:46+00:00","article_modified_time":"2022-02-17T09:11:34+00:00","og_image":[{"width":500,"height":213,"url":"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/1_A8liBoeAwAZg7rDu394jYg.png","type":"image\/png"}],"twitter_card":"summary_large_image","twitter_misc":{"Napisane przez":"Wojciech Zduniak","Szacowany czas czytania":"12 minut"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebSite","@id":"https:\/\/scriptfactory.pl\/blog\/#website","url":"https:\/\/scriptfactory.pl\/blog\/","name":"SCRIPT FACTORY | BI BLOG","description":"Blog techniczny pokazuj\u0105cy jak poradzi\u0107 sobie z najwi\u0119kszymi problemami","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/scriptfactory.pl\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"pl-PL"},{"@type":"ImageObject","@id":"https:\/\/scriptfactory.pl\/blog\/google\/wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record\/#primaryimage","inLanguage":"pl-PL","url":"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/1_A8liBoeAwAZg7rDu394jYg.png","contentUrl":"https:\/\/scriptfactory.pl\/blog\/wp-content\/uploads\/2019\/03\/1_A8liBoeAwAZg7rDu394jYg.png","width":500,"height":213},{"@type":"WebPage","@id":"https:\/\/scriptfactory.pl\/blog\/google\/wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record\/#webpage","url":"https:\/\/scriptfactory.pl\/blog\/google\/wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record\/","name":"BigQuery i przetwarzanie plik\u00f3w - SCRIPT FACTORY | BI BLOG","isPartOf":{"@id":"https:\/\/scriptfactory.pl\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/scriptfactory.pl\/blog\/google\/wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record\/#primaryimage"},"datePublished":"2019-03-20T13:58:46+00:00","dateModified":"2022-02-17T09:11:34+00:00","author":{"@id":"https:\/\/scriptfactory.pl\/blog\/#\/schema\/person\/e39ed2fd20838bb0d87220cc919e2f21"},"description":"Przyk\u0142ad wykorzystania platformy Google BigQuery do przetwarzanie plik\u00f3w p\u0142askich w w oparciu o tzw. pliki CDR.","breadcrumb":{"@id":"https:\/\/scriptfactory.pl\/blog\/google\/wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record\/#breadcrumb"},"inLanguage":"pl-PL","potentialAction":[{"@type":"ReadAction","target":["https:\/\/scriptfactory.pl\/blog\/google\/wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/scriptfactory.pl\/blog\/google\/wykorzystanie-google-bigquery-w-przetwarzaniu-cdr-call-detail-record\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Strona g\u0142\u00f3wna","item":"https:\/\/scriptfactory.pl\/blog\/"},{"@type":"ListItem","position":2,"name":"BigQuery i przetwarzanie plik\u00f3w"}]},{"@type":"Person","@id":"https:\/\/scriptfactory.pl\/blog\/#\/schema\/person\/e39ed2fd20838bb0d87220cc919e2f21","name":"Wojciech Zduniak","image":{"@type":"ImageObject","@id":"https:\/\/scriptfactory.pl\/blog\/#personlogo","inLanguage":"pl-PL","url":"https:\/\/secure.gravatar.com\/avatar\/5d954513663b7b760bcae861966c5069?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/5d954513663b7b760bcae861966c5069?s=96&d=mm&r=g","caption":"Wojciech Zduniak"},"description":"BI zajmuj\u0119 si\u0119 kilkana\u015bcie lat, od Microsoft po Teradat\u0119, od on-premise do cloud, od pojedy\u0144czych serwer\u00f3w po klastr\u00f3w obliczeniowych. Temat jest tak szeroki i ciekawy \u017ce postanowi\u0142em opisa\u0107 po kolei wszystko co wiem i z czym si\u0119 zetkn\u0105\u0142em. Mam nadzieje \u017ce b\u0119dzie Wam si\u0119 podoba\u0107 ta lektura :)","url":"https:\/\/scriptfactory.pl\/blog\/author\/admin\/"}]}},"_links":{"self":[{"href":"https:\/\/scriptfactory.pl\/blog\/wp-json\/wp\/v2\/posts\/15499"}],"collection":[{"href":"https:\/\/scriptfactory.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/scriptfactory.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/scriptfactory.pl\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/scriptfactory.pl\/blog\/wp-json\/wp\/v2\/comments?post=15499"}],"version-history":[{"count":16,"href":"https:\/\/scriptfactory.pl\/blog\/wp-json\/wp\/v2\/posts\/15499\/revisions"}],"predecessor-version":[{"id":15689,"href":"https:\/\/scriptfactory.pl\/blog\/wp-json\/wp\/v2\/posts\/15499\/revisions\/15689"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/scriptfactory.pl\/blog\/wp-json\/wp\/v2\/media\/15504"}],"wp:attachment":[{"href":"https:\/\/scriptfactory.pl\/blog\/wp-json\/wp\/v2\/media?parent=15499"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/scriptfactory.pl\/blog\/wp-json\/wp\/v2\/categories?post=15499"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/scriptfactory.pl\/blog\/wp-json\/wp\/v2\/tags?post=15499"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}