Kayıtlar

Sbt #3 : Dependency Yonetimi

Resim
 Bu postumuzda sbt ile dependency'ler nasil manage edilir (konustugumz dile bak) konusunu isleyecegiz. Sub-projelerin birbirine depend etmesi soz konusu oldugu gibi 3rd party library kullanimina da deginecegiz.  3rd Party Library Daha once sayisal loto tahmin uygulamasi yapmistik. Simdi buna bir ek yaparak, doviz kurlarini da ekleyecegiz. Bunun icin http request yapmamizi saglayacak scala-request kutuphanesini projeye ekliyoruz. buid.sbt dosyasindaki proje tanimlamasina soyle bir ek yapacagiz: name := "hello_sbt" version := "0.1" scalaVersion := "2.13.4" val sansOyunlari = project.settings(      libraryDependencies ++= Seq(           "com.lihaoyi" %% "requests" % "0.6.5",           "org.scala-lang.modules" %% "scala-xml" % "1.2.0",      ) ) Sbt projesini reload ediyoruz. Gidip IntelliJ sbt plugin sekmesine bakarsak su sekilde dependency'lerin olsuturuldugunu gorebiliriz: Simdi requests cal

Sbt #2: Proje yonetimi

Resim
Postun basligi iki yillik bolum adi gibi oldu ama idare edelim.  IntelliJ Yeni projesi Oncelikle IntelliJ ile bir sbt projesi olsuturuyoruz. (IntelliJ community edition ucretsiz ve scala plugini de kurulabiliyor). Sbt'nin de sisteminizde yuklu oldugunu varsayarak (onceki postta bahsetmistik), yeni proje'ye tikliyoruz ve sbt'yi seciyoruz. Projeye bir isim verim tamam'a tikliyoruz. Akabinde IntelliJ hemen build.sbt'yi yuklemeye baslayacak ve karsimiza su sekilde bir klasor yapisi cikacaktir: build.sbt'ye goz atarsak, 3 adet key tanimlanmis oldugunu goruyoruz. Ek olarak IntelliJ spesifik dosyalari ve de projeyi build ettikten sonra olusan artifactlari source repository'e gondermemek icin bir .gitignore dosyasi olusutup su iki satiri ekliyoruz: .idea/ target/ Sub-project yapisi Genisletilebilir (extensible) bir proje yapisi elde etmek icin proje icerisinde sub-proje'ler olsuturmak yaygin bir yaklasim. Bu sayede buyuk bir projenin alt sistemlerini izole veya

Sbt #1 : Temeller

Resim
 Sbt, scala icin var olan en populer build system'lerden bir tanesidir. Peki neden bir build system kullanmaliyiz? 1. compile 2. dependency management 3. test 4. package Bu asamalarin hepsini manuel olarak yapmak heralde cok sacma olacaktir.  Sbt, 2008'de ortaya cikiyor.  Ilk ciktiginda ismi simple build tool seklinde olsa da sonra scala build tool olarak degistiriliyor. Ancak gunumuzde java ve scala projeleri icin kullanilabildiginden artik o anlamini da yitirdi ve sbt bir anlama gelmiyor. Java build tool'lari olan Maven ve Ant ile ayni isi yapiyor denilebilir. Gelistirilmesi ise komunite ve Lightbend (scala ve ekosisteminin arkasinda olan sirket) tarafindan gerceklestiriliyor ki arkasi saglam. Sbt'nin baslica ozellikleri: 1. Zero config: cok az bir konfigurasyon gerektirmesi 2. Testing: scala-test, junit, scala-check ve specs testing frameworkleri ile iyi integrasyon saglar 3. Incremental compilation: proje ve testler icin incremental compilation saglar 4. Multi-p

Spark jobum nasil calisiyor?

Resim
 Spark ogrenmek gercekten cok kolay. Esas hazine spark ile paralelize edilmis bir computation'u inceleyip optimizasyon noktalarini bulup optimize edebilmek. Bazen pata kute yazdigimizi spark job'lari cok performanssiz ya da olabileceginden cok daha az performansli olabiliyor. Bunun icin gelin bir spark job'unun cigerini nasil sokebiliriz inceleyeim: Spark UI. Ever gorsellestirmeler bize cok yardimci olacak.  Timeleline gosterimi Tum joblar, tek bir job veya tek bir stage icin timeline view seklinde olan olaylari gorebiliriz. Bu sayede bircok icgoru elde edebiliriz.  Bu gorsel sparkUI'in giris sayfasindan. Yani tum joblar bir timeline uzerinde gosteriliyor. Oncelikle 4 adet executor'in kayit edildidigini goruyoruz. Hemen sonra 4 farkli job paralel bir sekilde calismaya basliyor. Bir tanesi (kirmizi olan) fail olurken digerleri basariyla tamamlaniyor. Tum job'lar tamamlandiktan sonra bizim spark job sona eriyor ve executor'lar bizden alinarak tekrar clustera&#

Spark Dataset ile typed bir gelecek

Resim
Hersey RDD ile basliyor. Kendisi type-safe. Ama tum execution dag bir kara kutu gibi, optimizasyon yazana kalmis durumda, low level bir API. Daha sonra Dataframe geliyor. Tum execution dag optimize edilebiliyor. Sql'e yakin ve bu durumda type safety kaybediliyor, hersey Row adi verilen jenerik bir class uzerinden donuyor.  Son olarak da Sql optimizasyonlari ve typesafety birleserek Dataset'i olusturuyor.  Hatta aslinda Spark 2.0'dan sonra Dataframe ve Dataset birlestirilmis durumda. Yani Dataframe, Dataset'in ozel bir hali gibi. Yani aslinda Dataframe = Dataset[Row] . Dataset Actions Dataframe uzerinde tanimlanan collect, take, foreach gibi action metodlari Row nesnesi collection'u uzerinden calisiyor. Ornek olarak bir df uzerinde collect yaparsak geriye Row listesi donecektir. Bunu da tekrardan parse edip kullanmamiz gerekir. Oyse ki Dataset, olusturuldugu class ne ise Dataset[BizimClass] o class tipinen bir kolleksion dondurecektir. Bu durumda tekrar parse etmeye

Spark Basit Join

Resim
En buyuk problemlerden bir tanesi. Ozellikle performans konusunda ciddi bottleneck olusturabiliyor. Yapabilecegimiz en iyi sey, Catalyst Reyizi en iyi sekilde kullanip, maksimum optimizasyon saglayabilmek. Soyle uc bir ornek verelim: Iki tabloyu join etmek icin bir join kriterine ihtiyacimiz var oyle degil mi? Bu bir esitlik olabilir, bir ID uzerinden join etmek icin. Bu esitlik operatorunu bir UDF'e kaydirabiliriz, hayet legit.  scala> val esitUDF = udf((id1: Long, id2: Long) => id1 == id2) scala> val joinedDF = df1.join(df2, esitUDF($"id1", $"id2")) Ancak buradaki UDF bir blackbox, yani catalyst buradaki imperative kod hakkinda bir optimizasyon gerceklestiremedigi gibi, bunu diger execution plan'daki adimlarla da kaynastiramiyor. Bu durumda join islemi bir kartezyen karsilastirma yapmak durumunda kaliyor ve sonuc olarak n2 complexity elde etmis oluyoruz. Ancak biz bu karsilastirmayi efendi gibi SparkSQL ile yazsa idik, scala> val joinedDF = df

Spark #20 : Dataframe

Resim
Spark DataFrame, Pandas dataframes ile kullanim acisindan benzerdir. Ancak tabi ki de altyapi cok farkli, spark distributed bir yapiya sahip iken, Pandas single core kullanabilmektedir. En nihayetinde de bir database table gibi dusunulebilir. Her satir bir kaydi temsil ederken bir veya daha fazla stuna sahip olabilir. Hemen basit bir ornek ile RDD ile farki gorelim. Diyelim ki elimizde isim - yas iceren bir buyuk veri var. Ayni isme sahip kisilerin yas ortalamasini bulmak istiyoruz. Ornek bir data tanimlayalim,  scala> val rddBireyler = sc.parallelize(Seq(("babur", 20), ("jamiryo", 12), ("babur", 56), ("babur", 44), ("jamiryo", 67))) dfBireyler: org.apache.spark.rdd.RDD[(String, Int)] = ParallelCollectionRDD[145] at parallelize at <console>:30 Yas ortalamasi almak icin her bir isimden kac tane oldugunu da bulmamiz gerek. Bu acidan kelime sayma yaklasiminda oldugu gibi her bir kaydi 1 ile baslatiyoruz ve daha sonra bir reduce i