%3CLINGO-SUB%20id%3D%22lingo-sub-1715269%22%20slang%3D%22en-US%22%3EUse%20Azure%20IR%20to%20Tune%20ADF%20and%20Synapse%20Data%20Flows%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1715269%22%20slang%3D%22en-US%22%3E%3CP%3EAzure%20Integration%20Runtimes%20are%20ADF%20and%20Synapse%20entities%20that%20define%20the%20amount%20of%20compute%20you%20wish%20to%20apply%20to%20your%20data%20flows%2C%20as%20well%20as%20other%20resources.%20Here%20are%20some%20tips%20on%20how%20to%20tune%20data%20flows%20with%20proper%20Azure%20IR%20settings.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EIn%20all%203%20of%20these%20examples%2C%20I%20tested%20my%20data%20flows%20with%20a%20demo%20set%20of%20mocked-up%20loans%20data%20in%20a%20CSV%20file%20located%20in%20my%20Blob%20Store%20container.%20There%20were%20887k%20rows%20with%2074%20columns%20and%20in%20each%20case%20I%20read%20from%20the%20file%2C%20duplicated%20the%20data%20into%202%20separate%20streams%2C%201%20row%20aggregated%20a%20row%20count%2C%20and%20the%202nd%20row%20masked%20PII%20data%20with%20a%201-way%20hash.%20I%20then%20loaded%20the%20data%20into%20a%20destination%20blob%20store%20folder%20sink.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22perf4.png%22%20style%3D%22width%3A%20385px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F222330i37994F156695962A%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20title%3D%22perf4.png%22%20alt%3D%22perf4.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EEach%20of%20these%20executions%20below%20was%20run%20from%20an%20ADF%20pipeline%20using%20the%20%22Debug%20%26gt%3B%20Use%20Activity%20Runtime%22%20setting%20so%20that%20I%20could%20manually%20adjust%20the%20number%20of%20cores%20and%20compute%20type%20for%20each%20run.%20This%20means%20that%20I%20am%20not%20using%20the%20warmed-up%20debug%20cluster%20session.%20The%20average%20start-up%20time%20for%20the%20Databricks%20cluster%20was%204.5%20mins.%20I%20also%20left%20all%20optimization%20settings%20in%20the%20transformations%20to%20default%20%2F%20use%20current%20partitioning.%20This%20allowed%20data%20flows%20to%20rely%20fully%20on%20Spark's%20best%20guess%20for%20partitioning%20my%20file-based%20data.%3C%2FP%3E%0A%3CH3%20id%3D%22toc-hId-1254399824%22%20id%3D%22toc-hId-1254399823%22%3ECompute%20Optimized%3C%2FH3%3E%0A%3CP%3EFirst%2C%20I%20ran%20the%20pipeline%20using%20the%20lowest%20cost%20option%2C%20Compute%20Optimized.%20For%20very%20memory-intensive%20ETL%20pipelines%2C%20we%20do%20not%20generally%20recommend%20using%20this%20category%20because%20it%20has%20the%20lowest%20RAM%2FCore%20ratio%20for%20the%20underlying%20VMs.%20But%20it%20can%20be%20useful%20for%20cost-savings%20and%20pipelines%20that%20are%20not%20acting%20on%20very%20large%20data%20without%20many%20joins%20or%20lookups.%20In%20this%20case%2C%20I%20chose%2016%20cores%2C%20which%20is%208%20cores%20for%20the%20driver%20node%20and%208%20cores%20for%20the%20worker%20nodes.%3C%2FP%3E%0A%3CH4%20id%3D%22toc-hId-1944961298%22%20id%3D%22toc-hId-1944961297%22%3EResults%3C%2FH4%3E%0A%3CUL%3E%0A%3CLI%3ESink%20IO%20writing%3A%2020s%3C%2FLI%3E%0A%3CLI%3ETransformation%20time%3A%2035s%3C%2FLI%3E%0A%3CLI%3ESink%20post-processing%20time%3A%2040s%3C%2FLI%3E%0A%3CLI%3EData%20Flows%20used%208%20Spark%20partitions%20based%20on%20my%208%20core%20worker%20nodes.%3C%2FLI%3E%0A%3C%2FUL%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22perfco1.png%22%20style%3D%22width%3A%20334px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F222334iE8ABAA97883C9780%2Fimage-dimensions%2F334x464%3Fv%3D1.0%22%20width%3D%22334%22%20height%3D%22464%22%20title%3D%22perfco1.png%22%20alt%3D%22perfco1.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH3%20id%3D%22toc-hId-1934458194%22%20id%3D%22toc-hId-1934458193%22%3EGeneral%20Purpose%3C%2FH3%3E%0A%3CP%3ENext%2C%20I%20tried%20the%20exact%20same%20pipeline%20using%20General%20Purpose%20with%20the%20small%208%20core%20(4%2B4)%20option%2C%20which%20gives%20you%201%20driver%20and%201%20worker%20node%2C%20each%20with%204%20cores.%20This%20is%20the%20small%20default%20debug%20cluster%20you%20are%20provided%20with%20the%20Default%20Auto%20Azure%20Integration%20Runtime.%20General%20Purpose%20is%20a%20very%20good%20middle%20option%20for%20data%20flows%20with%20a%20better%20RAM-to-CPU%20ratio%20than%20Compute%20Optimized.%20But%20I%20would%20highly%20recommend%20much%20higher%20core%20counts%20than%20I%20used%20here%20in%20this%20test.%20I%20am%20only%20using%20the%20default%204%2B4%20to%20demonstrate%20to%20you%20that%20the%20default%208%20core%20total%20is%20fine%20for%20small%20debugging%2C%20but%20not%20good%20for%20operationalized%20pipelines.%26nbsp%3B%3C%2FP%3E%0A%3CH4%20id%3D%22toc-hId--1669947628%22%20id%3D%22toc-hId--1669947629%22%3EResults%3C%2FH4%3E%0A%3CUL%3E%0A%3CLI%3ESink%20IO%20writing%3A%2046s%3C%2FLI%3E%0A%3CLI%3ETransformation%20time%3A%2042s%3C%2FLI%3E%0A%3CLI%3ESink%20post-processing%20time%3A%2045s%3C%2FLI%3E%0A%3CLI%3EData%20Flows%20partitioned%20the%20file%20data%20into%204%20parts%20because%20in%20this%20case%20because%20I%20backed%20out%20to%20only%204%20worker%20cores.%3C%2FLI%3E%0A%3C%2FUL%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22perfgp1.png%22%20style%3D%22width%3A%20334px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F222335iD461380A18DF2F4F%2Fimage-dimensions%2F334x454%3Fv%3D1.0%22%20width%3D%22334%22%20height%3D%22454%22%20title%3D%22perfgp1.png%22%20alt%3D%22perfgp1.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CH3%20id%3D%22toc-hId--1680450732%22%20id%3D%22toc-hId--1680450733%22%3EMemory%20Optimized%3C%2FH3%3E%0A%3CP%3EThis%20is%20the%20most%20expensive%20option%20and%20the%20highest%20RAM-to-CPU%20ratio%2C%20making%20it%20very%20good%20for%20large%20workloads%20that%20you've%20operationalized%20in%20triggered%20pipelines.%20I%20gave%20it%2080%20cores%20(64%20for%20workers%2C%2016%20for%20driver)%20and%20I%20naturally%20had%20the%20best%20individual%20stage%20timings%20with%20this%20option.%20The%20Databricks%20cluster%20took%20the%20longest%20to%20startup%20in%20this%20configuration%20and%20the%20larger%20number%20of%20partitions%20led%20to%20a%20slightly%20higher%20post-processing%20time%20as%20the%20additional%20partitions%20were%20coalesced.%20I%20ended%20up%20with%2064%20partitions%2C%20one%20for%20each%20worker%20core.%3C%2FP%3E%0A%3CH4%20id%3D%22toc-hId--989889258%22%20id%3D%22toc-hId--989889259%22%3EResults%3C%2FH4%3E%0A%3CUL%3E%0A%3CLI%3ESink%20IO%20writing%3A%2019s%3C%2FLI%3E%0A%3CLI%3ETransformation%20time%3A%2017s%3C%2FLI%3E%0A%3CLI%3ESink%20post-processing%20time%3A%2040s%3C%2FLI%3E%0A%3C%2FUL%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22perfmo.png%22%20style%3D%22width%3A%20313px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F222336i8343F404E6F178EB%2Fimage-dimensions%2F313x439%3Fv%3D1.0%22%20width%3D%22313%22%20height%3D%22439%22%20title%3D%22perfmo.png%22%20alt%3D%22perfmo.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3C%2FP%3E%3CDIV%20class%3D%22video-embed-center%20video-embed%22%3E%3CIFRAME%20class%3D%22embedly-embed%22%20src%3D%22https%3A%2F%2Fcdn.embedly.com%2Fwidgets%2Fmedia.html%3Fsrc%3Dhttps%253A%252F%252Fwww.youtube.com%252Fembed%252FVT_2ZV3a7Fc%253Ffeature%253Doembed%26amp%3Bdisplay_name%3DYouTube%26amp%3Burl%3Dhttps%253A%252F%252Fwww.youtube.com%252Fwatch%253Fv%253DVT_2ZV3a7Fc%26amp%3Bimage%3Dhttps%253A%252F%252Fi.ytimg.com%252Fvi%252FVT_2ZV3a7Fc%252Fhqdefault.jpg%26amp%3Bkey%3Db0d40caa4f094c68be7c29880b16f56e%26amp%3Btype%3Dtext%252Fhtml%26amp%3Bschema%3Dyoutube%22%20width%3D%22400%22%20height%3D%22225%22%20scrolling%3D%22no%22%20title%3D%22YouTube%20embed%22%20frameborder%3D%220%22%20allow%3D%22autoplay%3B%20fullscreen%22%20allowfullscreen%3D%22true%22%3E%3C%2FIFRAME%3E%3C%2FDIV%3E%3CP%3E%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-TEASER%20id%3D%22lingo-teaser-1715269%22%20slang%3D%22en-US%22%3E%3CP%3EAzure%20Integration%20Runtimes%20are%20ADF%20and%20Synapse%20entities%20that%20define%20the%20amount%20of%20compute%20you%20wish%20to%20apply%20to%20your%20data%20flows%2C%20as%20well%20as%20other%20resources.%20Here%20are%20some%20tips%20on%20how%20to%20tune%20data%20flows%20with%20proper%20Azure%20IR%20settings.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22perf3.png%22%20style%3D%22width%3A%20414px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F222329i2A6F6BB87F8808B6%2Fimage-dimensions%2F414x233%3Fv%3D1.0%22%20width%3D%22414%22%20height%3D%22233%22%20title%3D%22perf3.png%22%20alt%3D%22perf3.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%3C%2FLINGO-TEASER%3E%3CLINGO-LABS%20id%3D%22lingo-labs-1715269%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3EAzure%20Data%20Factory%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3Eazure%20synapse%20data%20flows%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EMapping%20Data%20Flows%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E
Microsoft

Azure Integration Runtimes are ADF and Synapse entities that define the amount of compute you wish to apply to your data flows, as well as other resources. Here are some tips on how to tune data flows with proper Azure IR settings.

 

In all 3 of these examples, I tested my data flows with a demo set of mocked-up loans data in a CSV file located in my Blob Store container. There were 887k rows with 74 columns and in each case I read from the file, duplicated the data into 2 separate streams, 1 row aggregated a row count, and the 2nd row masked PII data with a 1-way hash. I then loaded the data into a destination blob store folder sink.

 

perf4.png

 

Each of these executions below was run from an ADF pipeline using the "Debug > Use Activity Runtime" setting so that I could manually adjust the number of cores and compute type for each run. This means that I am not using the warmed-up debug cluster session. The average start-up time for the Databricks cluster was 4.5 mins. I also left all optimization settings in the transformations to default / use current partitioning. This allowed data flows to rely fully on Spark's best guess for partitioning my file-based data.

Compute Optimized

First, I ran the pipeline using the lowest cost option, Compute Optimized. For very memory-intensive ETL pipelines, we do not generally recommend using this category because it has the lowest RAM/Core ratio for the underlying VMs. But it can be useful for cost-savings and pipelines that are not acting on very large data without many joins or lookups. In this case, I chose 16 cores, which is 8 cores for the driver node and 8 cores for the worker nodes.

Results

  • Sink IO writing: 20s
  • Transformation time: 35s
  • Sink post-processing time: 40s
  • Data Flows used 8 Spark partitions based on my 8 core worker nodes.

perfco1.png

 

General Purpose

Next, I tried the exact same pipeline using General Purpose with the small 8 core (4+4) option, which gives you 1 driver and 1 worker node, each with 4 cores. This is the small default debug cluster you are provided with the Default Auto Azure Integration Runtime. General Purpose is a very good middle option for data flows with a better RAM-to-CPU ratio than Compute Optimized. But I would highly recommend much higher core counts than I used here in this test. I am only using the default 4+4 to demonstrate to you that the default 8 core total is fine for small debugging, but not good for operationalized pipelines. 

Results

  • Sink IO writing: 46s
  • Transformation time: 42s
  • Sink post-processing time: 45s
  • Data Flows partitioned the file data into 4 parts because in this case because I backed out to only 4 worker cores.

perfgp1.png

Memory Optimized

This is the most expensive option and the highest RAM-to-CPU ratio, making it very good for large workloads that you've operationalized in triggered pipelines. I gave it 80 cores (64 for workers, 16 for driver) and I naturally had the best individual stage timings with this option. The Databricks cluster took the longest to startup in this configuration and the larger number of partitions led to a slightly higher post-processing time as the additional partitions were coalesced. I ended up with 64 partitions, one for each worker core.

Results

  • Sink IO writing: 19s
  • Transformation time: 17s
  • Sink post-processing time: 40s

perfmo.png