<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Bradley Schacht - Development]]></title><description><![CDATA[Bradley Schacht is a Principal Program Manager on the Microsoft Fabric product team based in Saint Augustine, FL.]]></description><link>https://test.bradleyschacht.com</link><generator>RSS for Node</generator><lastBuildDate>Tue, 09 Jun 2026 11:53:54 GMT</lastBuildDate><atom:link href="https://test.bradleyschacht.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Using sempy to get SQL query CU cost from the Fabric Capacity Metrics App]]></title><description><![CDATA[Download the notebook used in this post from my GitHub account here:Get SQL query CUs from Capacity Metrics.ipynb
A frequent inquiry from customers goes something like this: "I ran a query on the [data warehouse or SQL analytics endpoint] and now I w...]]></description><link>https://test.bradleyschacht.com/using-sempy-to-get-sql-query-cu-cost-from-the-fabric-capacity-metrics-app-1</link><guid isPermaLink="true">https://test.bradleyschacht.com/using-sempy-to-get-sql-query-cu-cost-from-the-fabric-capacity-metrics-app-1</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Wed, 15 May 2024 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Download the notebook used in this post from my GitHub account here:</strong><br /><a target="_blank" href="https://github.com/bradleyschacht/resources/blob/main/Fabric/Capacity%20Metrics/Get%20SQL%20query%20CUs%20from%20Capacity%20Metrics.ipynb">Get SQL query CUs from Capacity Metrics.ipynb</a></p>
<p>A frequent inquiry from customers goes something like this: "I ran a query on the [data warehouse or SQL analytics endpoint] and now I want to know how much that query cost me."</p>
<p>On the surface that seems easy enough. Afterall, the Capacity Metrics app tracks the usage for every operation that occurs on your Fabric capacity right down to the individual T-SQL query.</p>
<p>Before getting into how to get the capacity usage, let's outline the assumptions this post is going to make:</p>
<ol>
<li><p>You understand the association between workspaces and capacities.</p>
</li>
<li><p>You understand the concept of smoothing as it relates to capacity usage.</p>
</li>
</ol>
<h2 id="heading-how-would-i-do-this-manually">How would I do this manually?</h2>
<p>However, when you try to use the app, you soon realize it's far more cumbersome than you'd like. This is the process you need to go through:</p>
<ol>
<li><p>Run a query using the SQL endpoint (web browser, SSMS, ADS, etc.).</p>
</li>
<li><p>Gather the distributed_statement_id and query execution date and time from Query Insights (or capture it through another method of your choosing).</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005602366/be381402-602d-4bbd-a6b3-d66fac90ce82.png" alt /></p>
<ol start="3">
<li>In the capacity metrics app, navigate to a time point that is at least 15 minutes after the query finished running.</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005603438/7f55d32b-fc16-4b4e-86c0-dacf390fcb41.png" alt /></p>
<ol start="4">
<li>Filter the background operations table to just the operations you want to see (Operation Id = distributed_statement_id).</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005604518/58aa1359-0532-4824-b0fb-35a34f19a3c9.png" alt /></p>
<p>It's step number 3 and 4 that cause the most pain and what we will address here today programmatically. Step 3 is just confusing for people because you need to wait for the query to show up in the report, but you need to go to "someplace after the query finishes running", usually 10-15 minutes, and find the query there. Step 4 is the bigger challenge because you need to get the list of IDs in step 2 then search for one of them in the filter in step 4, click the check the box, go back to step 2 to copy the next ID, search for it, and repeat that over for each query's distributed statement id.</p>
<p>The process is cumbersome for one query, it will drain your evening if you need to do this for a lot of queries, and it's just impossible if you need to do this for any number of queries at scale.</p>
<h2 id="heading-how-would-i-do-this-programmatically">How would I do this programmatically?</h2>
<p>The overall process is similar: Run a query (or queries), get the distributed_statement_id list, look them up in the capacity metrics app.</p>
<p>To accomplish this programmatically we will need to make a couple of changes to the manual process above. Let's do an overview then we'll dive into details.</p>
<ol>
<li><p>Run a query using the SQL endpoint (web browser, SSMS, ADS, etc.).</p>
</li>
<li><p>Gather the distributed_statement_id and query execution date and time from Query Insights. Turn it into a string in the format of "distributed_statement_id_01", "distributed_statement_id_02", "distributed_statement_id_NN"</p>
</li>
<li><p>Enter parameters into data engineering notebook.</p>
</li>
<li><p>Run the notebook.</p>
</li>
</ol>
<p>Before you try to use this method, you will need to download the notebook <a target="_blank" href="https://github.com/bradleyschacht/resources/blob/main/Fabric/Capacity%20Metrics/Get%20SQL%20query%20CUs%20from%20Capacity%20Metrics.ipynb">Get SQL query CUs from Capacity Metrics</a> which is hosted on my GitHub account. Then, upload the notebook to a Fabric workspace. The workspace will need capacity to run the notebook. The notebook can be in any Fabric workspace; it does not need to be collocated with the Capacity Metrics app or with the workspace where your lakehouses/warehouses live. In fact, this notebook doesn't even require a lakehouse to be in the workspace to run.</p>
<p>Let's look at a walkthrough of this.</p>
<h3 id="heading-run-queries">Run queries</h3>
<p>I think this is self explanatory. Run your queries however you'd like. Keep in mind that it takes several minutes for the queries to show up in Query Insights and a few more minutes to show up in the Capacity Metrics data. Just assume that you need to wait at least 15 minutes after running a query for this whole process to work (the same is true of the manual process above as we are using the same dataset).</p>
<h3 id="heading-gather-the-distributedstatementids">Gather the distributed_statement_id(s)</h3>
<p>Here is where things deviate from the manual process. While we are still going to be using Query Insights, we want to combine all the distributed statement ids into a single string, grouped by the date the query was run. This is necessary for the magic of a solution that allows you to get the CUs in bulk. Consider the following query to be a guide on how to do this but by no means the only way. The key is the format: double quotes around each distributed_statement_id forming a comma separated list.</p>
<pre><code class="lang-plaintext">SELECT
    CONVERT(DATE, start_time) ExecutionDate,
    COUNT(*) AS CountOfQueries,
    '"' + STRING_AGG(CONVERT(VARCHAR(MAX), distributed_statement_id), '", "') + '"' AS OperationIDList
FROM
    (
        SELECT
            *
        FROM queryinsights.exec_requests_history
        WHERE
            command LIKE '%%'
            AND start_time &gt;= '2024-05-08 20:53:38.000000'
            AND start_time &lt;= '2024-05-13 20:25:53.000000'
    ) AS queryinsights_requests
GROUP BY
    CONVERT(DATE, start_time)
</code></pre>
<p>The output from this query will provide the date the queries were executed, how many matched the subquery criteria, and the complete string of query ids. You will want to copy the ExecutionDate and the corresponding OperationIDList for the next step.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005605941/2093ee4b-2f9e-4673-8adc-1af80146f9a8.png" alt /></p>
<p>For the screenshots later in this post, I chose the 14 queries that were run on May 13th.</p>
<h3 id="heading-enter-parameters-in-the-notebook">Enter parameters in the notebook</h3>
<p>The big departure from the manual process is that we will use a notebook to query the Capacity Metrics dataset to get the data we need. You will need to import the notebook to any Fabric workspace (it requires capacity to use Spark) then fill in the 5 parameters in the first code cell.</p>
<ul>
<li><p>capacity_metrics_workspace</p>
<ul>
<li>The name of the workspace that hosts the Capacity Metrics app.</li>
</ul>
</li>
<li><p>capacity_metrics_dataset</p>
<ul>
<li>The name of the dataset used by the Capacity Metrics app.</li>
</ul>
</li>
<li><p>capacity_id</p>
<ul>
<li>The capacity which hosted the workspace where user query were run.</li>
</ul>
</li>
<li><p>date_of_operations</p>
<ul>
<li><p>This is the <strong>ExecutionDate</strong> column from the prior step.</p>
</li>
<li><p>The date the operations were run.</p>
</li>
</ul>
</li>
<li><p>operation_id_list</p>
<ul>
<li><p>This is the <strong>OperationIDList</strong> column from the prior step.</p>
</li>
<li><p>The list of operations of which you want to collect the capacity unit usage.</p>
</li>
<li><p>This should be a comma separate list and each operation should be enclosed in double quotes</p>
</li>
<li><p>For example: "AAAAAAAA-BBBB-CCCC-DDDD-1234567890AB", "EEEEEEEE-FFFF-GGGG-HHHH-1234567890AB"</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-run-the-notebook">Run the notebook</h3>
<p>That's it. Run it!</p>
<p>After the notebook runs, scroll down to the very last cell where the dataframe will display each distributed_statement_id (this is the OperationID field in Capacity Metrics) the total CUs consumed by that query and some additional information.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005606987/357381be-1aea-4f79-b499-4aa59e619097.png" alt /></p>
<p>Here you can see the total CUs for each of the 14 queries from step 2.</p>
<p>Did you also notice that we didn't have to deal with a timepoint? We only had to know what date the SQL query ran. You didn't even have to know the time that the query ran. The amount of time that I spend waiting for time period to show up in the capacity metrics report just so I can search for my data is wild. And it's all gone!</p>
<p>The magic that makes this happen is <a target="_blank" href="https://learn.microsoft.com/en-us/fabric/data-science/semantic-link-overview">Semantic Link</a> which provides a bridge between the data engineering and Power BI experiences in Fabric. It contains a variety of functionality including refreshing semantic models, reading tables from a semantic model, listing workspaces, getting workspace information, and executing DAX statements to return a dataset from a semantic model which is what this notebook uses.</p>
<h2 id="heading-wrapping-it-up">Wrapping it up</h2>
<p>There you have it! Now instead of looking up each query individually, you can just run a simple notebook to look up the CU usage in bulk! Let's wrap up with some key things to be aware of.</p>
<ol>
<li><p>Here is a link to get a copy of the notebook (<a target="_blank" href="https://github.com/bradleyschacht/resources/blob/main/Fabric/Capacity%20Metrics/Get%20SQL%20query%20CUs%20from%20Capacity%20Metrics.ipynb">Get SQL CUs from Capacity Metrics</a>) from my GitHub account.</p>
</li>
<li><p>You still need Capacity Metrics. Make note of the workspace name and semantic model name. Those are needed.</p>
</li>
<li><p>This notebook assumes that your Capacity Metrics semantic model is refreshed. Perhaps I will extend this in the future to add model refresh.</p>
</li>
<li><p>You will need the ID for the capacity that runs your workspace, not just the capacity name. This is the one part that's a little more difficult than the manual approach.</p>
</li>
<li><p>You do need to run this notebook for each date individually. I wanted to make this as easy as possible to use, so I started simple. It's still far faster than looking up individual queries manually. The nice thing though, is you can take this notebook and wrap it in another process that can be much more flexible.</p>
<p> For me, I have another version of this project where I persist the data from queryinsights.exec_requests_history into a user table, run this notebook to get the CU information, and then update the user table with the CU usage. The next time the process runs it only looks up the queries from query insights that do NOT have any CU usage already.</p>
<p> You could also do this across many workspaces to centralize the data. You could parameterize this with a pipeline instead of calling it from another notebook. The possibilities are endless! Would love to hear what you have built with it though!</p>
</li>
<li><p>I believe there is a limit of 10,000 or 100,000 records that can be returned at any one time. Yes, those numbers are very different. I don't know this for a fact though, but I'm fairly certain that limit is in place. Which means if you have a highly used system, you may need to break the query list into chunks and feed them through. Another great reason to parameterize this and build a framework around it.</p>
</li>
</ol>
<p>What do you think? Time saver? Did I waste my time building this?</p>
<p>Let me know in the comments what you think!</p>
]]></content:encoded></item><item><title><![CDATA[List Parameters for a Python Function]]></title><description><![CDATA[As someone who is newer to the world of Python I have a lot of questions. I mean a LOT. I know my way around SQL really well, but when I come to write some PySpark code I often need to dissect things to better understand what is going on and how to u...]]></description><link>https://test.bradleyschacht.com/list-parameters-for-a-python-function</link><guid isPermaLink="true">https://test.bradleyschacht.com/list-parameters-for-a-python-function</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Tue, 07 May 2024 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As someone who is newer to the world of Python I have a lot of questions. I mean a LOT. I know my way around SQL really well, but when I come to write some PySpark code I often need to dissect things to better understand what is going on and how to use different functions.</p>
<p>Which leads me to today's question...how do I get a list of all the parameters for a Python function? In today's case: mssparkutils.credentials.getSecret.</p>
<p>You could go to the documentation, but that's often not complete (I'm looking at you, my fellow Microsoft employees on the documentation team!). Usually, I just want to know what my possibilities are so I can at least throw some options in there to see what happens. Maybe I'll get lucky. That's where inspect.signature comes into play.</p>
<h2 id="heading-help">help</h2>
<p>The first thing I could try is using Python's built in "help" method. By simply passing a module, method, function, keyword, or other object the help information from PyDoc.</p>
<p>Python</p>
<pre><code>help(mssparkutils.credentials.getSecret)
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005595831/fecb2f9c-5232-46d7-aa8e-aa56d72af8a0.png" alt /></p>
<p>Easy enough. What if I want a little more detail?</p>
<h2 id="heading-inspect">inspect</h2>
<p>The inspect module can help get some useful information for us in this case as well. Using my new friend help, I can see this will give me a look at useful information from Python objects. Here we will look at two functions: inspect.signature() and inspect.getfullargspec().</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005596905/436fbb3f-31f2-4a1b-81d6-ee679e89356e.png" alt /></p>
<p>To begin, we will import the inspect module.</p>
<h3 id="heading-inspectsignature">inspect.signature()</h3>
<p>As you can see, running inspect.signature(msparkutils.credentials.getSecret) returns what I need in a simple output which is very similar to what we say with help(mssparkutils.credentials.getSecret) earlier. It gives me the list of inputs which are akvName, secret, and linkedService which is optional as it has a default value assigned to it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005597753/45c533a8-d10c-4513-8980-f2e946b632f1.png" alt /></p>
<p>But I am a simple person. I need things spelled out a bit more explicitly sometimes.</p>
<h3 id="heading-inspectgetfullargspec">inspect.getfullargspec()</h3>
<p>When I run inspect.getfullargspec(mssparkutils.credentials.getSecret) I am given a much more detailed breakdown of the output. While help and signature() will usually get the job done, it is nice knowing that I can get a full breakdown of the inputs and outputs.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005598500/c3a820bd-0104-455d-9c9c-91287a0e4aee.png" alt /></p>
<p>I am sure there are reasons to use signature over getfullargspec and reasons to use getfullargspec over signature. I saw something about a decorated function being handled properly by signature but not getfullargspec. Since the only possible time I can think of to use a decorator function is when I'm putting up Christmas decor and it is currently May, I think that is a deep dive topic for future Brad.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005599429/0e686b70-86f3-490b-b690-5d391b327e6a.png" alt /></p>
]]></content:encoded></item><item><title><![CDATA[Building The Big Demo]]></title><description><![CDATA[In the coming weeks I'm going to start building out a brand new demo environment and I'm going to blog the whole thing...probably...and I plan to blog the whole thing!
As you may (or may not) know, I work on the Fabric product team at Microsoft. I am...]]></description><link>https://test.bradleyschacht.com/building-the-big-demo</link><guid isPermaLink="true">https://test.bradleyschacht.com/building-the-big-demo</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Mon, 08 Apr 2024 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the coming weeks I'm going to start building out a brand new demo environment and I'm going to blog the whole thing...probably...and I <em>plan</em> to blog the whole thing!</p>
<p>As you may (or may not) know, I work on the Fabric product team at Microsoft. I am a principal program manager on the Fabric CAT (Customer Advisory Team) team. I always feel strange saying CAT team because then it's team team. It's like trying to explain Microsoft Teams to people. "Just post it on our Teams...uh...team?" or "I need to go to the ATM machine to get cash." You see cash is what people used to use to pay for things before...ok, we are wayyyy off topic. Where was I?</p>
<p>Ah yes, I work on the Fabric CAT team, and I often go talk to people about Fabric as a whole. However, most of the demos I do are just touching on one piece of the puzzle. What I'm setting out to do with this series is show the process of building an end-to-end solution in Microsoft Fabric from data source to visualization showing various options along the way. My goal is to be able to walk into any room and be able to say "let me pull up a workspace a show you what this looks like" for most of the major Fabric functionality.</p>
<p>Let's cover some of the basics...</p>
<h2 id="heading-what-this-will-not-be">What this will not be</h2>
<p>Let's get this out of the way first. What will this demo not be, or what purpose will it not be designed to serve.</p>
<ul>
<li><p>This will not be comprehensive of every single piece of functionality in Microsoft Fabric. We are sticking to major themes, the Heading 1 topics if you will.</p>
</li>
<li><p>This will not include every experience, just the ones I deal with on a regular basis. Think data science or private endpoints. Maybe it will expand in the future, but we'll see where it goes. The idea is big picture, make the concepts simple.</p>
</li>
<li><p>This will not be complicated where it can be simple. Again, let's not boil the ocean. We aren't hitting every security feature. I'll leave that for individual posts or other people to cover.</p>
</li>
<li><p>This will not be smoke and mirrors. I will only use what everyone has access to, and I won't hide any code from you to make things look easier than they are or fake any data along the way.</p>
</li>
<li><p>This will not show every architecture option. I honestly don't know if I am going to show loading data using Dataflows Gen2 since I can do everything I need in a pipeline copy activity. Again, we shall see what happens. Maybe I'll have secondary posts that cover alternative methods or design patterns.</p>
</li>
</ul>
<h2 id="heading-what-this-will-be">What this will be</h2>
<p>Now that we have some ground rules for what this project will not be, let's go over what it will be.</p>
<ul>
<li><p>This will walk you through every step of building an end-to-end analytics solution on Microsoft Fabric.</p>
</li>
<li><p>This will be something you can build in your environment as well. I'll make everything available in one form or another, be it screenshots, step-by-step clicks instructions, code on GitHub, or videos on YouTube.</p>
</li>
<li><p>This will be using the Microsoft Wide World Importers dataset. It's easy to understand (retail sales), has all the translation code to go from the OLTP to DW, and is easily available to everyone.</p>
</li>
<li><p>This will be as representative of the real world as possible while still keeping the concepts simple. For example, we will use an Azure SQL DB for the source data, but we aren't going to be simulating transactions on the source system and build slowly changing dimension logic. It's easy enough to extend the solution to include those items if you really want to.</p>
</li>
<li><p>This will be built out over the course of N weeks. That is not a typo, that's not a placeholder I forgot to update, that is the truth. I don't know how long this is going to take. I've thought about doing one post a week, breaking up into approximately 30 minute building sessions, covering one step at a time no matter how long it takes. This is going to change as we go along, I just don't know how long it's going to take. I know I can build everything from scratch in a few hours, but teaching/blogging time is a different animal.</p>
</li>
<li><p>This will be somewhat sanitized but, as I mentioned above, I won't hide things from you. What I mean by that is that to covert the Wide World Importers into Wide World Importers DW there are a series of views and stored procedures that need to be built/converted. I'm not going to cover every step of that code building/conversion process because it's frankly a bit boring and doesn't serve the purpose of this series, but I will give you all the real code. That means some of the steps you have to do in a real-world project will be happening behind the scenes or will be already done for you. Again, our focus is Fabric not project management or BI development.</p>
</li>
</ul>
<h2 id="heading-what-the-architecture-will-look-like">What the architecture will look like</h2>
<p>This is still to be defined, but here's what I'm thinking:</p>
<p><strong>Azure SQL Database</strong> --- Data Factory Pipeline ---&gt; <strong>Lakehouse Files</strong> --- Notebook ---&gt; <strong>Lakehouse Tables</strong> --- T-SQL ---&gt; <strong>Data Warehouse</strong> --- DirectLake ---&gt; <strong>Power BI report</strong></p>
<p>Be on the lookout for the first post in the series where we will setup the source database soon!</p>
]]></content:encoded></item><item><title><![CDATA[Upcoming Presentation – Jacksonville SQL Server User Group]]></title><description><![CDATA[I’m excited to announce that I will be speaking at the February meeting of the Jacksonville SQL Server User Group (JSSUG). It’s always fun to spend some time with local SQL community. I’ll be presenting a session recapping all the exciting features a...]]></description><link>https://test.bradleyschacht.com/upcoming-presentation-jacksonville-sql-server-user-group-1</link><guid isPermaLink="true">https://test.bradleyschacht.com/upcoming-presentation-jacksonville-sql-server-user-group-1</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Wed, 17 Jan 2024 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I’m excited to announce that I will be speaking at the February meeting of the <a target="_blank" href="https://www.meetup.com/jaxssug/">Jacksonville SQL Server User</a> Group (JSSUG). It’s always fun to spend some time with local SQL community. I’ll be presenting a session recapping all the exciting features added to <a target="_blank" href="https://www.microsoft.com/en-us/microsoft-fabric">Microsoft Fabric</a> in 2023 and previewing what's ahead for 2024. If you’re local, come on out and join us for an evening of learning, networking, and of course food. The event is free, but please register at the link below to help the organizers with logistics and planning.</p>
<p>I hope to see you there!</p>
<p><strong>Date:</strong> Wednesday July 19, 2023<br /><strong>Time:</strong> 6:00 - 8:00 PM Eastern<br /><strong>Where:</strong> <a target="_blank" href="https://goo.gl/maps/E6jnYZ1BBsNzjcT87">Keiser University (6430 Southpoint Parkway Suite #100, Jacksonville, FL 32216</a><br /><strong>Cost:</strong> Free!<br /><strong>Registration:</strong> <a target="_blank" href="https://www.meetup.com/jaxssug/events/">Meetup</a></p>
<h3 id="heading-microsoft-fabric-2023-year-in-review-and-2024-roadmap">Microsoft Fabric 2023 Year in Review and 2024 Roadmap</h3>
<p>Less than one year ago Microsoft Fabric was announced at the Build 2023 conference. Since then the team has been hard at work rolling out new features and functionality each month. From small improvements like the ability to convert entire folders to Delta with a right-click rather than going file by file or background improvements like faster CSV loading to marquee functionality like the launch of multiple Copilots and the announcement of general availability or the new database mirroring, 2023 was a huge year for Fabric. We will run down the list of some of the biggest announcements and show demos along the way so you can see the exciting functionality that is being delivered each and every month. Then, we will take a look at the year ahead with a sneak peak into the 2024 roadmap. If you're using Fabric or considering using Fabric for a project, you'll want to join this session to see what all the buzz is about!</p>
]]></content:encoded></item><item><title><![CDATA[The Year Ahead: 2024]]></title><description><![CDATA[My favorite time of year is now behind us: Christmas. The weather cools down (I live in Florida, so that's a little iffy), the neighborhood lights up with decorations, people are a little more friendly, church services are more full than normal, Nich...]]></description><link>https://test.bradleyschacht.com/the-year-ahead-2024</link><guid isPermaLink="true">https://test.bradleyschacht.com/the-year-ahead-2024</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Wed, 03 Jan 2024 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>My favorite time of year is now behind us: Christmas. The weather cools down (I live in Florida, so that's a little iffy), the neighborhood lights up with decorations, people are a little more friendly, church services are more full than normal, Nichole and I get to watch cheesy holiday movies, and we get to work through all our favorite traditions with our boys.</p>
<p>As the Christmas season closes and we move deeper into winter there is now a new year to look forward to which means it's time for new year's resolutions.</p>
<blockquote>
<p><strong><em>Resolution</em></strong></p>
<p>A firm decision to do or not to do something.</p>
</blockquote>
<p>I'm not a big fan of resolutions. They are often lofty, unattainable (realistically anyway), and leave little room for error which means people abandon them as soon as things start to go off the rails even a little. Saying "I resolve to go to the gym 3 times a week" psychologically gives you an out as soon as you miss that third day. It creates the feeling of "I said I was going to go this, I messed it up, now my streak is done, and I don't need to keep trying." In fact, almost 25% of people give up on their resolutions in the first week, and more than 2/3 give up before the end of January.</p>
<blockquote>
<p><strong><em>Goal</em></strong></p>
<p>The object of a person's ambition or effort; an aim or desired result.</p>
</blockquote>
<p>Instead, I like to set goals. Goals give you something to aim for but allow for the inevitable error and adjustment that comes along with being human and needing to respond to life events. Someone with the goal of exercising 3 times a week that has a lot of travel coming up would have the freedom to exchange the gym with a jog around the park or a workout in their hotel room before an early morning flight. And if they don't hit the goal that week, then they can evaluate what went wrong, how they can do better and get back to it the next week. Or if they set a goal of 5 days at the gym, they may have a baby and realize that's no longer viable and adjust to 2 gym days with walks on the other days.</p>
<p>Are those two things really all that different. No, of course not. But the mindset that comes with resolutions vs. goals tends to be very different.</p>
<p>What then are my goals for the new year? Some of these are aimed at being healthier so I can live a long, fulfilling life for my family. Some of these are centered around being more intentional with my time. And likely the most important are about deepening my relationship with Jesus Christ. Some of these I already do and want to make sure I don't lose focus, some are things I don't do well and want to improve, and others are areas I haven't started yet.</p>
<ol>
<li><p>Read through the entire Bible this year (<a target="_blank" href="https://www.thebiblerecap.com/start">The Bible Recap</a>)</p>
</li>
<li><p>Pray every day with the family and on my own</p>
</li>
<li><p>Listen to 1 audiobook each month (I'm not a big reader, but I'll listen!)</p>
</li>
<li><p>Dedicate as much time between 5:00 PM and the boys bedtime to my family as possible (less screen time/work and more play time with the kids and talk with Nichole)</p>
</li>
<li><p>Spend more quality time with Nichole after the boys go to bed (puzzles, crafts, just chatting)</p>
</li>
<li><p>Get more sleep (fewer work until 2:00 - 3:00 AM nights)</p>
</li>
<li><p>Daily walk and/or bike ride with the family</p>
</li>
<li><p>Do something outside with the family every weekend (bike trail, kayak, beach, park trip, etc.)</p>
</li>
<li><p>Eat better (less Dr Pepper, more meals at home, fewer carbs, more veggies, all that good stuff)</p>
</li>
<li><p>Reduce and shift the kind of content I consume (more history, Bible commentary, educational material and fewer TV shows/movies)</p>
</li>
<li><p>Create more content than I did last year (more blogs, more videos)</p>
</li>
</ol>
<p>What do you think?<br />Am I nitpicking about settings resolutions vs. goals?<br />What are you resolving to do this year?<br />What goals are you setting for yourself?</p>
]]></content:encoded></item><item><title><![CDATA[Upcoming Presentation - Boston Business Intelligence User Group]]></title><description><![CDATA[I'm excited to announce that I will be speaking at the July meeting of the virtual Boston Business Intelligence User Group. I'll be presenting an introductory session on Microsoft Fabric. The session is hosted online so everyone is welcome to join fo...]]></description><link>https://test.bradleyschacht.com/upcoming-presentation-boston-business-intelligence-user-group</link><guid isPermaLink="true">https://test.bradleyschacht.com/upcoming-presentation-boston-business-intelligence-user-group</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Thu, 08 Jun 2023 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I'm excited to announce that I will be speaking at the July meeting of the virtual <a target="_blank" href="https://www.meetup.com/boston_bi/">Boston Business Intelligence User Group</a>. I'll be presenting an introductory session on <a target="_blank" href="https://www.microsoft.com/en-us/microsoft-fabric">Microsoft Fabric</a>. The session is hosted online so everyone is welcome to join for an evening of learning and networking. The event is free, but please register at the link below to help the organizers with logistics and planning.</p>
<p>I hope to see you there!</p>
<p><strong>Date:</strong> Thursday July 20, 2023<br /><strong>Time:</strong> 7:00 - 9:00 PM Eastern<br /><strong>Where:</strong> Online (Register to receive the link)<br /><strong>Cost:</strong> Free!<br /><strong>Registration:</strong> <a target="_blank" href="https://www.meetup.com/boston_bi/events/293862841/">Meetup</a></p>
<h3 id="heading-introducing-microsoft-fabric-the-all-in-one-analytics-solution">Introducing Microsoft Fabric: The All-in-One Analytics Solution</h3>
<p>The world is awash with data and it is up to data professionals to make sense of it all. Just a few weeks ago Microsoft announced the next generation of analytics at Build: Microsoft Fabric!</p>
<p>Fabric is a complete end-to-end analytics platform bringing together Azure Data Factory, Azure Synapse, and Power BI in a single location and more deeply integrated than ever. It’s built on a SaaS platform which helps deliver innovation more quickly and allowing users to get up and running in seconds. At the core Fabric provides a lake-centric and open data hub using the popular Delta format with built-in security, governance, and compliance throughout. At the edge, Fabric delivers flexibility for data scientists, data warehouse developers, and Power BI users to build and analyze using their unique skill sets.</p>
<p>During this session we will discuss the guiding principles and architecture behind Fabric and show a lot of demos! Whether you’re a data engineer, data scientist, data warehouse developer, or an existing Power BI user, Fabric has something for everyone. You won’t want to miss this session!</p>
]]></content:encoded></item><item><title><![CDATA[What is Microsoft Fabric]]></title><description><![CDATA[This year at the annual Build developer conference, Microsoft announced the public preview of Microsoft Fabric, an all-in-one analytics platform that will drive the future of analytics. To say that this release is huge would be an understatement.
On ...]]></description><link>https://test.bradleyschacht.com/what-is-microsoft-fabric</link><guid isPermaLink="true">https://test.bradleyschacht.com/what-is-microsoft-fabric</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Thu, 08 Jun 2023 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This year at the annual Build developer conference, Microsoft announced the public preview of <a target="_blank" href="https://www.microsoft.com/en-us/microsoft-fabric">Microsoft Fabric</a>, an all-in-one analytics platform that will drive the future of analytics. To say that this release is huge would be an understatement.</p>
<p>On the surface Fabric looks like an iteration on the work that was done when <a target="_blank" href="https://azure.microsoft.com/en-us/products/synapse-analytics/?ef_id=_k_CjwKCAjw1YCkBhAOEiwA5aN4AdhInV-VS2IR5UGSbPGFpIcwr1zMHHwbvkp86woEQ4htL8BlZ72oXBoC_lMQAvD_BwE_k_&amp;OCID=AIDcmm5edswduu_SEM__k_CjwKCAjw1YCkBhAOEiwA5aN4AdhInV-VS2IR5UGSbPGFpIcwr1zMHHwbvkp86woEQ4htL8BlZ72oXBoC_lMQAvD_BwE_k_&amp;gad=1&amp;gclid=CjwKCAjw1YCkBhAOEiwA5aN4AdhInV-VS2IR5UGSbPGFpIcwr1zMHHwbvkp86woEQ4htL8BlZ72oXBoC_lMQAvD_BwE">Azure Synapse Analytics</a> was launched a few years ago. The reality is that this is not just a step forward but a leap. Many of the components of Fabric do look similar to Synapse, including carrying forward the brand in several of the workloads like Synapse Data Warehousing. However, the architecture, integration, and delivery are vastly different.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005585759/444691ab-9654-4127-ac3b-6e5ec5d81466.png" alt /></p>
<h2 id="heading-onelake">OneLake</h2>
<p>We have to start with <a target="_blank" href="https://learn.microsoft.com/en-us/fabric/onelake/onelake-overview">OneLake</a> because that is the thread that holds this Fabric together. Everyone is going to write, Tweet, or say that so I'm just going to get it out of the way. Please don't hold it against me. I know, low hanging fruit and all, but it is what it is. Moving on... At the core, OneLake is Azure Data Lake Storage but it's so much more than that. Gone are the days of provisioning storage accounts, setting up private endpoints between storage and compute, copying data so different compute engines can access it, managing security in multiple locations, duplicating data when you want to create development environments, and so much more.</p>
<p>You don't create OneLake. You just have OneLake. It's described as OneDrive for your data, which now that I think about it, I already store data in OneDrive...I'll figure that all out another time. The point is, you interact with OneLake just as easily as you interact with OneDrive. It's driven by your Azure AD account by default. It's easy to share with others. You don't have to worry about how to tune to get the necessary IOPS. It's just there.</p>
<p>The best part is that all of the compute engines in Fabric store their data in OneLake, which means all the compute engines can access each other's data. All the architects out there are probably thinking "Does this mean I don't have to do all that data copying to give my SQL people access to the data in my lake? And does that mean I don't have to copy the data from my warehouse to a dataset in Power BI to be able to report on it?" That is absolutely correct. Along with OneLake comes "One Copy" which means every engine can see and interact with the all the data (with proper security of course).</p>
<p>The other best part...or maybe the equally best part, however you'd say that...is OneLake acts just like Azure Data Lake Storage. That means my data is not locked inside OneLake never to be seen again by any of the other Azure services. Therefore, all the Databricks users out there can read and write data to OneLake meaning you can continue to leverage all of those investments and integrations with other services that you've spent years building.</p>
<p>The other, other best part (this is getting out of hand) is if you have an existing Azure Data Lake Storage account you can create a shortcut and bring that data right into OneLake without even having to move it! So everything in your data estate can then be seen and analyzed through OneLake. More on all of this in a future post. As you can see, there is a huge amount of integration that OneLake unlocks and it's arguably the most important piece of the entire puzzle.</p>
<h2 id="heading-one-format">One format</h2>
<p>In addition to OneLake there is one other key change that enables all the functionality in Fabric: standardizing on <a target="_blank" href="https://learn.microsoft.com/en-us/fabric/data-engineering/lakehouse-and-delta-tables">Delta</a>. Every compute engine in Fabric now reads and writes Delta format. This is how we prevent the need to copy data from the lakehouse into the warehouse or into the lakehouse from Kusto. Why Delta? At this point, it's the industry standard. Sure, there is some <a target="_blank" href="https://learn.microsoft.com/en-us/fabric/data-engineering/delta-optimization-and-v-order?tabs=sparksql">secret sauce</a> going on under the covers that enables all kinds of nifty functionality but that's for another time...</p>
<h2 id="heading-workloads">Workloads</h2>
<p>Fabric supports a variety of workloads that are more deeply integrated than ever before. We will go into details of each of these workloads in separate posts, but for now let's talk about what is built into the platform.</p>
<ul>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/fabric/data-factory/data-factory-overview">Data Factory</a> - Easily integrate and transform data from any source. Provides no-code and low-code transformation experiences and continues to be the orchestration hub of the data solution.</p>
</li>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/fabric/data-engineering/data-engineering-overview">Synapse Data Engineering</a> - Provides data engineers a familiar, notebook-based experience for transforming data at scale using Spark.</p>
</li>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/fabric/data-science/data-science-overview">Synapse Data Science</a> - The place to go for managing, training, and deploying machine learning models.</p>
</li>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/fabric/data-warehouse/data-warehousing">Synapse Data Warehousing</a> - A relational data warehouse with truly independent compute and storage that provides industry-leading performance. This is NOT Synapse dedicated SQL pools and it is NOT Synapse serverless SQL pools.</p>
</li>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/fabric/real-time-analytics/overview">Synapse Real Time Analytics</a> - Dive into large volumes of data from apps, websites, IoT devices and any other time series data you can get your hands on.</p>
</li>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/power-bi/fundamentals/power-bi-overview">Power BI</a> - I feel like this doesn't even need an introduction. Create interactive reports with stunning visuals (I'm not that creative, but I know some people that are) to gain insights from data across your organization.</p>
</li>
<li><p>Data Activator - Coming soon! - A detection system that provides alerting and monitoring, so you know exactly when important information is changing.</p>
</li>
</ul>
<h2 id="heading-experiences">Experiences</h2>
<p>The experience in Fabric line up with the workloads to reduce the noise and quickly surface the most relevant information for what you need to get done.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005586985/78b76fde-5fd3-40f6-8524-83eea1a34ebf.png" alt /></p>
<p>Selecting an experience, such as Synapse Data Warehouse, will bring you to a screen that shows common tasks and resources that a user working on a data warehouse would find useful. In this case, the ability to create a new warehouse, create a new data pipeline, or link directly to the getting started documentation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005588124/1bf7dd1c-2aca-41ca-a194-b2118f61b654.png" alt /></p>
<h2 id="heading-software-as-a-service">Software-as-a-Service</h2>
<p>Fabric will be delivered like no analytics platform at Microsoft before. Fabric is leveraging a <a target="_blank" href="https://learn.microsoft.com/en-us/fabric/get-started/microsoft-fabric-overview#saas-foundation">Software as a Service (SaaS)</a> model. This doesn't mean that you have any less functionality, you will still have complete control over your data and experience like you have in all Azure PaaS services. However, it does mean some things are changing for the better including:</p>
<ul>
<li><p>It just works.</p>
</li>
<li><p>One capacity that will be shared between all the workloads. No more paying for each individual dedicated SQL pool and worrying about paying for dedicated capacity in multiple databases that may sit unused.</p>
</li>
<li><p>Updates delivered weekly! That means the platform can be updated with the latest and greatest functionality all the time rather than waiting for less-frequent "big bang" releases.</p>
</li>
<li><p>Trials to get started in seconds if you just want to kick the tires.</p>
</li>
<li><p>Fast provisioning and automatic scaling. A data warehouse takes about 10-20 seconds to spin up rather than the 10+ minutes that it takes today. Spark pools come online in less than 15 seconds rather than 5+ minutes today.</p>
</li>
<li><p>Success by default, meaning fewer knobs to tune because the best practices are implemented automatically (for SQL think things like stats <strong><em>always</em></strong> being up to date) and the workloads are all integrated seamlessly.</p>
</li>
</ul>
<h2 id="heading-wrapping-up">Wrapping up</h2>
<p>This is the biggest advance in analytics at Microsoft since I started building data warehouses on SQL Server back in 2009. Full disclosure, I may be a little biased since I work on the Fabric product team, as of the time of writing this post I am a member of Fabric CAT (Customer Advisory Team). Sure, all the core components of this platform existed in one shape or another before, but the level of integration, ease of use, and new functionality that is unlocked with Fabric is quite amazing.</p>
<p>If you want to hear directly from the leadership and feature PM teams about all the different workloads, you can head over to the <a target="_blank" href="https://powerbi.microsoft.com/en-in/blog/microsoft-digital-event-may-24-25/">Microsoft Fabric Launch Event</a> page to find a list of sessions that were presented on May 24 and 25 showcasing all the functionality that was announced. If you want to just jump right in and watch the full 6+ hours of content, you can catch the on-demand versions for <a target="_blank" href="https://www.youtube.com/watch?v=1o_QDFq6gzE">Day 1</a> and <a target="_blank" href="https://www.youtube.com/watch?v=_Y-XyCRE6ec">Day 2</a> over on YouTube.</p>
<p>In a livestream I did earlier this week someone said Fabric was just Synapse repackaged. I can assure you that is not the case. If you have any doubts, just go <a target="_blank" href="https://learn.microsoft.com/en-us/fabric/get-started/fabric-trial">try the 60-day free trial</a> and see for yourself.</p>
]]></content:encoded></item><item><title><![CDATA[Upcoming Presentation - Jacksonville SQL Server User Group]]></title><description><![CDATA[I'm excited to announce that I will be speaking at the July meeting of the Jacksonville SQL Server User Group (JSSUG). It's always fun to spend some time with local SQL community. I'll be presenting an introductory session on Microsoft Fabric. If you...]]></description><link>https://test.bradleyschacht.com/upcoming-presentation-jacksonville-sql-server-user-group</link><guid isPermaLink="true">https://test.bradleyschacht.com/upcoming-presentation-jacksonville-sql-server-user-group</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Wed, 07 Jun 2023 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I'm excited to announce that I will be speaking at the July meeting of the <a target="_blank" href="https://www.meetup.com/jaxssug/">Jacksonville SQL Server User</a> Group (JSSUG). It's always fun to spend some time with local SQL community. I'll be presenting an introductory session on <a target="_blank" href="https://www.microsoft.com/en-us/microsoft-fabric">Microsoft Fabric</a>. If you're local, come on out and join us for an evening of learning, networking, and of course food. The event is free, but please register at the link below to help the organizers with logistics and planning.</p>
<p>I hope to see you there!</p>
<p><strong>Date:</strong> Wednesday July 19, 2023<br /><strong>Time:</strong> 6:00 - 8:00 PM Eastern<br /><strong>Where:</strong> <a target="_blank" href="https://goo.gl/maps/E6jnYZ1BBsNzjcT87">Keiser University (6430 Southpoint Parkway Suite #100, Jacksonville, FL 32216</a><br /><strong>Cost:</strong> Free!<br /><strong>Registration:</strong> <a target="_blank" href="https://www.meetup.com/jaxssug/events/294028133/">Meetup</a></p>
<h3 id="heading-introducing-microsoft-fabric-the-all-in-one-analytics-solution">Introducing Microsoft Fabric: The All-in-One Analytics Solution</h3>
<p>The world is awash with data and it is up to data professionals to make sense of it all. Just a few weeks ago Microsoft announced the next generation of analytics at Build: Microsoft Fabric!</p>
<p>Fabric is a complete end-to-end analytics platform bringing together Azure Data Factory, Azure Synapse, and Power BI in a single location and more deeply integrated than ever. It’s built on a SaaS platform which helps deliver innovation more quickly and allowing users to get up and running in seconds. At the core Fabric provides a lake-centric and open data hub using the popular Delta format with built-in security, governance, and compliance throughout. At the edge, Fabric delivers flexibility for data scientists, data warehouse developers, and Power BI users to build and analyze using their unique skill sets.</p>
<p>During this session we will discuss the guiding principles and architecture behind Fabric and show a lot of demos! Whether you’re a data engineer, data scientist, data warehouse developer, or an existing Power BI user, Fabric has something for everyone. You won’t want to miss this session!</p>
<p><a target="_blank" href="https://www.meetup.com/jaxssug/events/294028133/attendees/"></a></p>
]]></content:encoded></item><item><title><![CDATA[Upcoming Presentation - Toronto Data Professionals Community]]></title><description><![CDATA[I'm excited to announce that I will be speaking at the June meeting of the virtual Toronto Data Professionals Community. I'll be presenting an introductory session on Microsoft Fabric. The session is hosted online so everyone is welcome to join for a...]]></description><link>https://test.bradleyschacht.com/upcoming-presentation-toronto-data-professionals-community</link><guid isPermaLink="true">https://test.bradleyschacht.com/upcoming-presentation-toronto-data-professionals-community</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Wed, 07 Jun 2023 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I'm excited to announce that I will be speaking at the June meeting of the virtual <a target="_blank" href="https://www.meetup.com/toronto-data-professionals-meetup-group/">Toronto Data Professionals Community</a>. I'll be presenting an introductory session on <a target="_blank" href="https://www.microsoft.com/en-us/microsoft-fabric">Microsoft Fabric</a>. The session is hosted online so everyone is welcome to join for an evening of learning and networking. The event is free, but please register at the link below to help the organizers with logistics and planning.</p>
<p>I hope to see you there!</p>
<p><strong>Date:</strong> Thursday June 15, 2023<br /><strong>Time:</strong> 6:00 - 7:30 PM Eastern<br /><strong>Where:</strong> Online (Microsoft Teams, register to receive the link)<br /><strong>Cost:</strong> Free!<br /><strong>Registration:</strong> <a target="_blank" href="https://www.meetup.com/toronto-data-professionals-meetup-group/events/293805152">Meetup</a></p>
<h3 id="heading-introducing-microsoft-fabric-the-all-in-one-analytics-solution">Introducing Microsoft Fabric: The All-in-One Analytics Solution</h3>
<p>The world is awash with data and it is up to data professionals to make sense of it all. Just a few weeks ago Microsoft announced the next generation of analytics at Build: Microsoft Fabric!</p>
<p>Fabric is a complete end-to-end analytics platform bringing together Azure Data Factory, Azure Synapse, and Power BI in a single location and more deeply integrated than ever. It’s built on a SaaS platform which helps deliver innovation more quickly and allowing users to get up and running in seconds. At the core Fabric provides a lake-centric and open data hub using the popular Delta format with built-in security, governance, and compliance throughout. At the edge, Fabric delivers flexibility for data scientists, data warehouse developers, and Power BI users to build and analyze using their unique skill sets.</p>
<p>During this session we will discuss the guiding principles and architecture behind Fabric and show a lot of demos! Whether you’re a data engineer, data scientist, data warehouse developer, or an existing Power BI user, Fabric has something for everyone. You won’t want to miss this session!</p>
<p><a target="_blank" href="https://www.meetup.com/jaxssug/events/294028133/attendees/"></a></p>
]]></content:encoded></item><item><title><![CDATA[What is a DWU?]]></title><description><![CDATA[You're new to Azure Synapse Analytics but you know you want to build a data warehouse. What do you do? After a quick search of the internet, you discover you need a Synapse dedicated SQL pool. Log into Azure, click a few buttons, deploy a Synapse wor...]]></description><link>https://test.bradleyschacht.com/what-is-a-dwu</link><guid isPermaLink="true">https://test.bradleyschacht.com/what-is-a-dwu</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Tue, 14 Feb 2023 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You're new to Azure Synapse Analytics but you know you want to build a data warehouse. What do you do? After a quick search of the internet, you discover you need a Synapse dedicated SQL pool. Log into Azure, click a few buttons, deploy a Synapse workspace, and it's time to get started with the dedicated SQL pool but there is one problem...you have no idea what a DWU is.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005578945/4c13b591-eedc-4a83-9457-15d0e9bf68dd.png" alt /></p>
<p>The default is 1,000 of them and they aren't cheap.</p>
<p>Do you need 1,000? 100? 8,278?</p>
<p>These are all good questions, but let's try to address the "What is a DWU?" question first.</p>
<h2 id="heading-what-is-a-dwu">What is a DWU?</h2>
<p>A DWU, or Data Warehouse Unit, is the Synapse dedicated SQL pool's blended representation of compute power. Similar to the early days of Azure SQL Database where we only had DTUs, you won't find vCores or memory listed anywhere on the page or documentation.</p>
<p>This number drives a number of things that we will cover in separate posts at a later date, but at the core it combines CPU, memory, and IO. The used DWU percentage will therefore be represented by the maximum of those three metrics. For example, a workload that is very CPU intensive using 60% of the available CPU for the currently selected DWU, but uses very little memory at 10% and a small amount of IO at 15% would show as using 60% of the available DWU. Similarly, an IO intensive workload using 5% CPU, 15% memory, and 40% of the provisioned IO would show as using 40% of the available DWU.</p>
<h2 id="heading-how-do-i-choose-the-right-number-of-dwus">How do I choose the right number of DWUs?</h2>
<p>To oversimplify things, if you need less overall performance then go with a lower DWU. If you need more overall performance, then go with a higher DWU.</p>
<p>I'm a former consultant, so I am well trained in saying "it depends". To that end, in reality, the number of required DWUs is very workload specific. Here are a few guiding principals for helping land on the right setting:</p>
<ul>
<li><p>Do you initial development on a very small number of DWUs. Start with 100 DWUs just get the DDL deployed even.</p>
</li>
<li><p>DW100 to DW500 are all a single compute node with varying levels of compute power. That means you are really running a single node server with the overhead of an MPP engine. Not until DW1000 do you get a second compute node.</p>
</li>
<li><p>When doing load tests, use at least DW1000. Anything lower shouldn't be considered for production and should only be used for development purposes.</p>
</li>
<li><p>Use a tool like JMeter to simulate a workload. Be sure to look at the whole workload.</p>
<ul>
<li><p>Build a simulation for your ETL.</p>
</li>
<li><p>Build another for ad hoc user queries.</p>
</li>
<li><p>Build another for reporting tool queries.</p>
</li>
<li><p>Run them in series or parallel depending on expected loading and query patterns.</p>
</li>
<li><p>Use realistic data sizes. Don't build the simulation on 100k records when you're going to have 100 billion records. It doesn't need to be a 100% match on data size, but it should be representative.</p>
</li>
</ul>
</li>
<li><p>Scale up or down based on the performance observed in your test.</p>
</li>
<li><p>Don't forget to account for bursts of activity and plan to scale appropriately. A monthly or quarterly load may mean you scale up a few hours in advance or at some logical point where you can take a few minutes of downtime for the scaling operation to complete.</p>
</li>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/azure/synapse-analytics/sql-data-warehouse/memory-concurrency-limits#concurrency-maximums-for-workload-groups">DWUs drive concurrency</a>. Maximum concurrency, 128 queries, in not unlocked until DW6000c.</p>
</li>
<li><p>The more CCI rebuilds you want to run in parallel, the more memory you will need, the more DWUs you will need.</p>
</li>
<li><p>The moral of the story is this...test, test, test.</p>
</li>
</ul>
<h2 id="heading-how-do-i-know-what-dwu-im-running">How do I know what DWU I'm running?</h2>
<p>The current SQL pool service level will be shown in the Azure Portal, Synapse Studio, PowerShell, and through the T-SQL query below when connected to the master database.</p>
<p>SQL</p>
<pre><code>SELECT
    d.name AS DatabaseName,
    Edition AS DatabaseEdition,
    service_objective AS ServiceObjective
FROM sys.database_service_objectives AS dso
INNER JOIN sys.databases AS d
    ON dso.database_id = d.database_id
</code></pre><p>There you have it. Data warehouse units simplified!</p>
]]></content:encoded></item><item><title><![CDATA[PASS Data Community Summit 2022]]></title><description><![CDATA[We are back in business!
It's been a few years since there was an in-person PASS Summit. Some major changes and a couple of years later we are excited to be back in person for what is now the "PASS Data Community Summit".
If SQL Saturday and Data Sat...]]></description><link>https://test.bradleyschacht.com/pass-data-community-summit-2022</link><guid isPermaLink="true">https://test.bradleyschacht.com/pass-data-community-summit-2022</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Tue, 15 Nov 2022 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We are back in business!</p>
<p>It's been a few years since there was an in-person PASS Summit. Some major changes and a couple of years later we are excited to be back in person for what is now the "PASS Data Community Summit".</p>
<p>If SQL Saturday and Data Saturday event sizes are any indication, this conference will be significantly smaller than past years when it was the PASS Summit but with just as much great content and many great networking opportunities. I can't wait to make my way out to Seattle, meet some new people, and present on Synapse + Power BI.</p>
<p>This year I will be presenting a session called "<a target="_blank" href="https://passdatacommunitysummit.com/sessions/all-sessions/1855">Better Together: Power BI and Azure Synapse Analytics</a>". If you have ever attended a session of mine in the past, you will know I don't like slides. This session will walk through the adventure of creating a Power BI report on Synapse serverless, eventually hitting performance challenges as the dataset gets really big, tuning the report and Synapse layers, and ultimately making the end users happy again.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005575695/65eef3ae-33f6-4fdb-ac39-182f15a19638.png" alt /></p>
<p>If you're attending the Data Community Summit and are looking for a fun place to go at 2:30 PM, come on by! I'll also be around on Wednesday at the Microsoft booth and other places around the conference. If you have Synapse questions or just want to meet to talk, come find me!</p>
]]></content:encoded></item><item><title><![CDATA[Create Comma Delimited List in SQL]]></title><description><![CDATA[Previously, I wrote a blog about how to create a comma separated list in T-SQL. 12 years later...one moment I have to go check and see if I'm really so old that I can say I wrote a blog post 12 years ago...
Ok, I'm back. It is confirmed. I am in fact...]]></description><link>https://test.bradleyschacht.com/create-comma-delimited-list-in-sql</link><guid isPermaLink="true">https://test.bradleyschacht.com/create-comma-delimited-list-in-sql</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Tue, 02 Aug 2022 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Previously, I <a target="_blank" href="https://bradleyschacht.com/comma-delimited-list-with-coalesce/">wrote a blog</a> about how to create a comma separated list in T-SQL. 12 years later...one moment I have to go check and see if I'm really so old that I can say I wrote a blog post 12 years ago...</p>
<p>Ok, I'm back. It is confirmed. I am in fact officially old. I really did write that blog 12 years ago on June 23, 2010. Wow. Anyway...</p>
<p>12 years later that post has received dozens of views from me trying to remember how I did that. Well, I'm here to tell you there is a better way! I didn't discover this because I wanted to improve my code or because I was scanning the release notes for SQL Server to see what new T-SQL functionality has been released in the last few versions. No, I had to find a better way because my previous method which used a variable and the COALESCE function does not work on Azure Synapse Analytics.</p>
<p>The new method: <a target="_blank" href="https://docs.microsoft.com/en-us/sql/t-sql/functions/string-agg-transact-sql?view=sql-server-ver16">STRING_AGG()</a></p>
<p>Let's get started with some sample data:</p>
<pre><code>CREATE TABLE dbo.State
    (
        StateID [int],
        StateName [varchar](<span class="hljs-number">50</span>)
    )

INSERT INTO dbo.State
SELECT <span class="hljs-number">1</span>, <span class="hljs-string">'Florida'</span>
UNION ALL
SELECT <span class="hljs-number">2</span>, <span class="hljs-string">'Tennessee'</span>
UNION ALL
SELECT <span class="hljs-number">3</span>, <span class="hljs-string">'Georgia'</span>
UNION ALL
SELECT <span class="hljs-number">4</span>, NULL
UNION ALL
SELECT <span class="hljs-number">5</span>, <span class="hljs-string">'Texas'</span>

SELECT * FROM dbo.State
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005572349/a10d489d-e5fd-4b3d-a094-bb7c90303e87.png" alt /></p>
<p>Now, a simple STRING_AGG(expression, separator) and we are good to go!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005573343/1ffa3b38-392b-4c01-9fe7-074b6894fb52.png" alt /></p>
<p>Quick and simple!</p>
<p>A couple quick notes in closing.</p>
<ol>
<li>Notice that NULL values are ignored and the separator is not added. If you want to include NULL values you'll need to wrap the column name in this example with ISNULL so it would look something like SELECT STRING_AGG(ISNULL(StateName, 'No Name Provided'), ',') FROM dbo.State</li>
<li>There is an optional order by operator that can be used to order the list.</li>
<li>The data type is determined by the expression. That means if the column is a string it will retain the string properties. MAX fields will result in a MAX data type. Non-max fields will result in the largest possible non-MAX value (VARCHAR(8000) or NVARCHAR(4000)). All other data types result in an NVARCHAR(4000) result.</li>
<li>You aren't limited to a literal string like a comma or a pipe for the separator. That's just my most common request. CHAR(13), CHAR(9), and just about any other expression are all valid as well.</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Azure Synapse Analytics Release Notes]]></title><description><![CDATA[Each month the Azure Synapse Analytics team works hard to get new features, updates, and improvements out the door. Here you will find a running list of updates released each month and links to the corresponding blog posts from the product team. You ...]]></description><link>https://test.bradleyschacht.com/azure-synapse-analytics-release-notes</link><guid isPermaLink="true">https://test.bradleyschacht.com/azure-synapse-analytics-release-notes</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Tue, 24 May 2022 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Each month the Azure Synapse Analytics team works hard to get new features, updates, and improvements out the door. Here you will find a running list of updates released each month and links to the corresponding blog posts from the product team. You can always find the full updates from the product team and other great Synapse content over on the <a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/bg-p/AzureSynapseAnalyticsBlog">Azure Synapse Blog</a>.</p>
<h2 id="heading-may-2022">May 2022</h2>
<p>Read about the <a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-may-update-2022/ba-p/3430970">May 2022</a> updates on the <a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/bg-p/AzureSynapseAnalyticsBlog">Azure Synapse Blog</a>.</p>
<ul>
<li>General<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-may-update-2022/ba-p/3430970#TOCREF_1">See Details</a>] Get connected with the Azure Synapse Influencer program</li>
</ul>
</li>
<li>SQL<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-may-update-2022/ba-p/3430970#TOCREF_3">See Details</a>] Data Warehouse Migration guide for Dedicated SQL Pools in Azure Synapse Analytics</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-may-update-2022/ba-p/3430970#TOCREF_4">See Details</a>] Specify character column lengths... Not anymore!</li>
</ul>
</li>
<li>Apache Spark for Synapse<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-may-update-2022/ba-p/3430970#TOCREF_6">See Details</a>] Azure Synapse Dedicated SQL Pool Connector for Apache Spark Now Available in Python</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-may-update-2022/ba-p/3430970#TOCREF_7">See Details</a>] Manage Azure Synapse Apache Spark configuration</li>
</ul>
</li>
<li>Synapse Data Explorer<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-may-update-2022/ba-p/3430970#TOCREF_9">See Details</a>] Synapse Data Explorer live query in Excel</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-may-update-2022/ba-p/3430970#TOCREF_11">See Details</a>] Use Managed Identities for External SQL Server Tables</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-may-update-2022/ba-p/3430970#TOCREF_12">See Details</a>] New KQL Learn module (2 out of 3) is live!</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-may-update-2022/ba-p/3430970#TOCREF_13">See Details</a>] Azure Synapse Data Explorer connector for Microsoft Power Automate, Logic Apps, and Power Apps [Gen...</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-may-update-2022/ba-p/3430970#TOCREF_15">See Details</a>] Dynamic events routing from event hub to multiple databases </li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-may-update-2022/ba-p/3430970#TOCREF_16">See Details</a>] Configure a database using a KQL inline script as part of JSON ARM deployment template</li>
</ul>
</li>
<li>Data Integration<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-may-update-2022/ba-p/3430970#TOCREF_18">See Details</a>] Export pipeline monitoring as a CSV</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-may-update-2022/ba-p/3430970#TOCREF_19">See Details</a>] Incremental data loading made easy for Synapse and Azure Database for PostgreSQL and MySQL</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-may-update-2022/ba-p/3430970#TOCREF_20">See Details</a>] User-Defined Functions for Mapping Data Flows [Public Preview]</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-may-update-2022/ba-p/3430970#TOCREF_21">See Details</a>] Assert Error Handling</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-may-update-2022/ba-p/3430970#TOCREF_22">See Details</a>] Mapping data flows projection editing</li>
</ul>
</li>
<li>Synapse Link<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-may-update-2022/ba-p/3430970#TOCREF_24">See Details</a>] Azure Synapse Link for SQL [Public Preview]</li>
</ul>
</li>
</ul>
<hr />
<h2 id="heading-april-2022">April 2022</h2>
<p>Read about the <a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-april-update-2022/ba-p/3295633">April 2022</a> updates on the <a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/bg-p/AzureSynapseAnalyticsBlog">Azure Synapse Blog</a>.</p>
<ul>
<li>SQL<ul>
<li><a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-april-update-2022/ba-p/3295633#TOCREF_2">[See Details]</a> Cross-subscription restore for Azure Synapse SQL [Generally Available]</li>
<li><a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-april-update-2022/ba-p/3295633#TOCREF_3">[See Details]</a> Recover SQL pool from dropped server or workspace</li>
</ul>
</li>
<li>Synapse Database Templates &amp; Database Designer<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-april-update-2022/ba-p/3295633#TOCREF_5">See Details</a>] Revamped exploration experience</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-april-update-2022/ba-p/3295633#TOCREF_6">See Details</a>] Clone lake database</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-april-update-2022/ba-p/3295633#TOCREF_7">See Details</a>] Use wildcards to specify custom folder hierarchies</li>
</ul>
</li>
<li>Apache Spark for Synapse<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-april-update-2022/ba-p/3295633#TOCREF_9">See Details</a>] Apache Spark 3.2 [Public Preview]</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-april-update-2022/ba-p/3295633#TOCREF_10">See Details</a>] Parameterization for Spark job definition</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-april-update-2022/ba-p/3295633#TOCREF_11">See Details</a>] Notebook snapshot</li>
</ul>
</li>
<li>Security<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-april-update-2022/ba-p/3295633#TOCREF_12">See Details</a>] Synapse Monitoring Operator RBAC role [Generally Available]</li>
</ul>
</li>
<li>Data Integration<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-april-update-2022/ba-p/3295633#TOCREF_14">See Details</a>] Dataverse connector added to Synapse Data Flows</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-april-update-2022/ba-p/3295633#TOCREF_16">See Details</a>] Synapse Pipelines Web activity response timeout improvement</li>
</ul>
</li>
<li>Developer Experience<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-april-update-2022/ba-p/3295633#TOCREF_18">See Details</a>] Reference unpublished notebooks</li>
</ul>
</li>
</ul>
<hr />
<h2 id="heading-march-2022">March 2022</h2>
<p>Read about the <a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-march-update-2022/ba-p/3269194">March 2022</a> updates on the <a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/bg-p/AzureSynapseAnalyticsBlog">Azure Synapse Blog</a>.</p>
<ul>
<li>Developer Experience<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-march-update-2022/ba-p/3269194#TOCREF_1">See Details</a>] Synapse notebooks: Code cells with exception to show standard output</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-march-update-2022/ba-p/3269194#TOCREF_1">See Details</a>] Synapse notebooks: Partial output is available for running notebook code cells</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-march-update-2022/ba-p/3269194#TOCREF_2">See Details</a>] Synapse notebooks: Dynamically control your Spark session configuration with pipeline parameters</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-march-update-2022/ba-p/3269194#TOCREF_3">See Details</a>] Synapse notebooks: Reuse and manage notebook sessions</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-march-update-2022/ba-p/3269194#TOCREF_4">See Details</a>] Synapse notebooks: Support for Python logging</li>
</ul>
</li>
<li>SQL<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-march-update-2022/ba-p/3269194#TOCREF_6">See Details</a>] Column Level Encryption for Azure Synapse dedicated SQL Pools [Generally Available]</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-march-update-2022/ba-p/3269194#TOCREF_7">See Details</a>] Better performance for CETAS and subsequent SELECTs</li>
</ul>
</li>
<li>Apache Spark for Synapse<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-march-update-2022/ba-p/3269194#TOCREF_9">See Details</a>] Synapse Spark Common Data Model (CDM) Connector [Generally Available]</li>
<li>[[](https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-march-update-2022/ba-p/3269194#TOCREF_10)<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-march-update-2022/ba-p/3269194#TOCREF_9">See Details</a>] Spark Dedicated SQL Pool (DW) Connector: Performance Improvements</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-march-update-2022/ba-p/3269194#TOCREF_11">See Details</a>] Synapse Spark Dedicated SQL Pool (DW) Connector: Support for all Spark Dataframe SaveMode choices (...</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-march-update-2022/ba-p/3269194#TOCREF_12">See Details</a>] Accelerate Spark execution speed using the new Intelligent Cache feature [Public Preview]</li>
</ul>
</li>
<li>Security<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-march-update-2022/ba-p/3269194#TOCREF_14">See Details</a>] Azure Synapse Analytics now supports Azure Active Directory (Azure AD) only authentication</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-march-update-2022/ba-p/3269194#TOCREF_15">See Details</a>] API support to raise or lower Workspace Managed SQL Server Dedicated SQL Minimal TLS version</li>
</ul>
</li>
<li>Data Integration<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-march-update-2022/ba-p/3269194#TOCREF_17">See Details</a>] Flowlets and CDC Connectors [Generally Available]</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-march-update-2022/ba-p/3269194#TOCREF_18">See Details</a>] sFTP connector for Synapse data flows</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-march-update-2022/ba-p/3269194#TOCREF_19">See Details</a>] Data flow improvements to Data Preview</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-march-update-2022/ba-p/3269194#TOCREF_20">See Details</a>] Pipeline script activity</li>
</ul>
</li>
</ul>
<hr />
<h2 id="heading-february-2022">February 2022</h2>
<p>Read about the <a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-february-update-2022/ba-p/3221841">February 2022</a> updates on the <a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/bg-p/AzureSynapseAnalyticsBlog">Azure Synapse Blog</a>.</p>
<ul>
<li>SQL<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-february-update-2022/ba-p/3221841#TOCREF_2">See Details</a>] More consistent query execution times for Serverless SQL Pools</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-february-update-2022/ba-p/3221841#TOCREF_3">See Details</a>] The OPENJSON function makes it easy to get array element indexes</li>
</ul>
</li>
<li>Data Integration<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-february-update-2022/ba-p/3221841#TOCREF_5">See Details</a>] Upsert supported by Copy Activity</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-february-update-2022/ba-p/3221841#TOCREF_6">See Details</a>] Transform Dynamics Data Visually in Synapse Data Flows</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-february-update-2022/ba-p/3221841#TOCREF_7">See Details</a>] Connect to your SQL sources in data flows using Always Encrypted</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-february-update-2022/ba-p/3221841#TOCREF_8">See Details</a>] Capture descriptions from Asserts in Data Flows</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-february-update-2022/ba-p/3221841#TOCREF_9">See Details</a>] Easily define schemas for complex type fields</li>
</ul>
</li>
</ul>
<hr />
<h2 id="heading-january-2022">January 2022</h2>
<p>Read about the <a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-december-2021-update/ba-p/3042904">January 2022</a> updates on the <a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/bg-p/AzureSynapseAnalyticsBlog">Azure Synapse Blog</a>.</p>
<ul>
<li>Apache Spark for Synapse<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-january-update-2022/ba-p/3071681#TOCREF_2">See Details</a>] 4 New database templates [Public Preview]</li>
</ul>
</li>
<li>Machine Learning<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-january-update-2022/ba-p/3071681#TOCREF_3">See Details</a>] Improvements to the SynapseML library</li>
</ul>
</li>
<li>Security<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-january-update-2022/ba-p/3071681#TOCREF_5">See Details</a>] Azure Synapse Analytics security overview</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-january-update-2022/ba-p/3071681#TOCREF_6">See Details</a>] TLS 1.2 required for new workspaces</li>
</ul>
</li>
<li>Data Integration<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-january-update-2022/ba-p/3071681#TOCREF_8">See Details</a>] Data quality validation rules using Assert transformation</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-january-update-2022/ba-p/3071681#TOCREF_9">See Details</a>] Native data flow connector for Dynamics</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-january-update-2022/ba-p/3071681#TOCREF_10">See Details</a>] IntelliSense and auto-complete added to pipeline expressions</li>
</ul>
</li>
<li>Synapse SQL<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-january-update-2022/ba-p/3071681#TOCREF_12">See Details</a>] COPY schema discovery for complex data ingestion</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-january-update-2022/ba-p/3071681#TOCREF_13">See Details</a>] HASHBYTES easily generates hashes in Serverless SQL</li>
</ul>
</li>
</ul>
<hr />
<h2 id="heading-december-2021">December 2021</h2>
<p>Read about the <a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-december-2021-update/ba-p/3042904">December 2021</a> updates on the <a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/bg-p/AzureSynapseAnalyticsBlog">Azure Synapse Blog</a>.</p>
<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-december-2021-update/ba-p/3042904#REF1">See Details</a>] Finding Synapse Monthly Update blogs</li>
<li>Apache Spark in Synapse<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-december-2021-update/ba-p/3042904#REF3">See Details</a>] Additional notebook export formats</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-december-2021-update/ba-p/3042904#REF4">See Details</a>] Three new chart types in notebooks</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-december-2021-update/ba-p/3042904#REF5">See Details</a>] Reconnect notebooks to Spark sessions</li>
</ul>
</li>
<li>Data Integration<ul>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-december-2021-update/ba-p/3042904#REF7">See Details</a>] Map Data tool [Public Preview], a no-code guided ETL experience</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-december-2021-update/ba-p/3042904#REF7">See Details</a>] Quick Reuse of Spark clusters</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-december-2021-update/ba-p/3042904#REF9">See Details</a>] External call transformation</li>
<li>[<a target="_blank" href="https://techcommunity.microsoft.com/t5/azure-synapse-analytics-blog/azure-synapse-analytics-december-2021-update/ba-p/3042904#REF10">See Details</a>] Flowlets [Public Preview]</li>
</ul>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Log Analytics with Azure Synapse Analytics]]></title><description><![CDATA[There are a lot of services in Azure. Way more than a few. What is something you want to do with all your services and applications? You want to monitor them. How do you do that? By looking at the logs that are produced. How do you capture and make s...]]></description><link>https://test.bradleyschacht.com/log-analytics-with-azure-synapse-analytics</link><guid isPermaLink="true">https://test.bradleyschacht.com/log-analytics-with-azure-synapse-analytics</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Mon, 01 Nov 2021 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There are a lot of services in Azure. Way more than a few. What is something you want to do with all your services and applications? You want to monitor them. How do you do that? By looking at the logs that are produced. How do you capture and make sense of thousands of log entries from hundreds of services for this really awesome solution you’ve been working on? Azure Monitor.</p>
<p>This post isn’t about Azure Monitor though. Not directly anyway.</p>
<p>Azure Synapse is no different than any other application or service in your environment. It serves a purpose in the architecture and as a result needs special attention from people with a specific skillset, in this case DBAs and developers. That’s where Azure Monitor comes into the picture and what we will be discussing today: how to make sense of the integration between auditing in Azure Synapse and Azure Monitor. The focus will be on Azure Synapse Analytics Dedicated SQL Pools (Gen 2) specifically, but there is integration for monitoring serverless SQL pools, Spark pools, pipelines, and general workspace operations.</p>
<p>First, those with an eye for detail will notice that this post has Log Analytics in the title and not Azure Monitor. That’s true. A very brief explanation so everyone has things straight in their heads. I put Log Analytics in the title because when you set up auditing or diagnostics the option is labeled “Send to Log Analytics workspace” not “Send to Azure Monitor” and I wanted people to be able to find this post. Azure Monitor is a set of functionalities for collecting and analyzing logs. There are some prebuilt integrations and visualizations with some Azure services like Key Vault or Storage Accounts Then there is Log Analytics, a functionality inside Azure Monitor which also happens to be where Synapse writes its logs, for storing and querying all log data. Queries are written in a Kusto Query Language or KQL.</p>
<p>Second, let’s be sure a few very important details are clear. When referring to Azure Synapse there are two distinct but very similar services. They are both the same Microsoft cloud MPP database engine, both cover the same general T-SQL surface area, both scale in terms of DWUs, both talk about “Azure Synapse Analytics” in the documentation and description, but one is deployed to an Azure SQL Server, and one is deployed to a Workspace.</p>
<p>We need to be very clear about this because they both operate slightly different. Again, this post is focused on Azure Synapse Analytics Dedicated SQL Pools (Gen 2). An alternate post is available for <a target="_blank" href="https://bradleyschacht.com/log-analytics-with-dedicated-sql-pools-formerly-sql-dw/">Dedicate SQL Pools (Formerly SQL DW)</a> if you need information about that deployment option.</p>
<p>Let’s get started.</p>
<h1 id="heading-what-are-my-options">What are my options?</h1>
<p>There are two types of logging that can be enabled: Auditing and Diagnostics. Auditing tracks a set of database events like queries and login attempts. Diagnostics will make copies of a specific set of system DMVs periodically which can be helpful because Synapse only stores a few thousand records depending on the DMV.</p>
<p>Everything from here assumes that you have a Log Analytics workspace created and a Synapse Workspace with a Gen 2 dedicated SQL pool deployed.</p>
<h1 id="heading-enabling-auditing">Enabling Auditing</h1>
<p>Auditing can be enabled at the workspace level, which will cover all databases on the workspace automatically, or at the individual database level.</p>
<p>First, navigate to your Synapse Analytics Workspace or dedicated SQL pool in the Azure Portal. My screenshots will show the configuration from the dedicated SQL pool, but the same setting can be found under the label of Azure SQL Auditing at the workspace level. From here, select Auditing from the Security section.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005552996/46111c2c-a1b1-479c-8c0a-7918e08db857.png" alt /></p>
<p>Next, toggle the <strong>Enable Azure SQL Auditing</strong> to the on position. Next, check the boxes for the locations where you would like the log to be written, in this example we are going to focus on Log Analytics. Select a log analytics workspace to which the data will be written. Click <strong>Save</strong> once complete.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005554145/2e84c121-8a5d-47da-87b0-9ddf8d00fdd4.png" alt /></p>
<h1 id="heading-enabling-diagnostics">Enabling Diagnostics</h1>
<p>While Auditing can be turned on for a database by either enabling it at the workspace or database level, diagnostics must be enabled at the database level. There are diagnostics at the workspace level, but those are different metrics and do not apply to monitoring the dedicated SQL pool.</p>
<p>If you’re not there already, navigate in the Azure Portal to your dedicated SQL pool. Select <strong>Diagnostic Settings</strong> from the <strong>Monitoring</strong> section.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005555179/eda1e52f-8e84-4c6d-9b3d-7888c848c59b.png" alt /></p>
<p>Next, click the <strong>Add diagnostic setting</strong> button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005556441/3a5ca131-d32f-4c08-9078-608565a74533.png" alt /></p>
<p>Provide a name for this diagnostic setting. Check the box next to <strong>Send to Log Analytics workspace</strong>. Select the subscription and workspace to which the DMVs will be written. Select which DMVs you want to log. Finally, click Save.</p>
<p>Remember, the diagnostic settings each correspond to a different DMV that will be copied to your Log Analytics workspace. If you need additional DMVs you’ll need to roll your own auditing solution at this time.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Diagnostic Setting Label</td><td>System DMV</td></tr>
</thead>
<tbody>
<tr>
<td>SqlRequests</td><td>sys.dm_pdw_sql_requests</td></tr>
<tr>
<td>RequestSteps</td><td>sys.dm_pdw_request_steps</td></tr>
<tr>
<td>ExecRequests</td><td>sys.dm_pdw_exec_requests</td></tr>
<tr>
<td>DmsWorkers</td><td>sys.dm_dms_workers</td></tr>
<tr>
<td>Waits</td><td>sys.dm_pdw_waits</td></tr>
</tbody>
</table>
</div><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005557439/cbc1d1ef-ad0b-40a4-8d51-592367f53a6c.png" alt /></p>
<h1 id="heading-reading-the-logs">Reading the Logs</h1>
<p>Data will take several minutes to show up in Log Analytics. I’ve had the initial population take up to 30 minutes. After that the data should show up much more quickly, within several minutes. Connect to your database and run a query or two to ensure we have some user queries show up in the logs.</p>
<p>For my example I have run the following query:<br />SELECT COUNT(*), GETDATE(), DB_NAME() FROM IMDB.stage_Person</p>
<p>To view the logs, you can navigate to your log analytics workspace, or select <strong>Logs</strong> from your dedicated SQL pool’s <strong>Monitoring</strong> section. This can be found directly beneath the Diagnostic Settings option used in the last section.</p>
<h2 id="heading-viewing-the-audit-log">Viewing the Audit Log</h2>
<p>Within the Log Analytics Workspace you will see a group of tables with the prefix Synapse* and at least one table prefixed with SQL*. More tables may appear if you are using auditing for Azure SQL Database. The audit setup in the first section of this post will be logged to the SQLSecurityAuditEvents table.</p>
<p>This sample query pulls a few of the relevant columns from the SQLSecurityAuditEvents table.</p>
<pre><code class="lang-sql">SQLSecurityAuditEvents
| project
    ResourceGroup,
    LogicalServerName,
    DatabaseName,
    EventTime,
    Category,
    ActionName,
    IsServerLevelAudit,
    Succeeded,
    tostring(SessionId),
    ClientIp,
    HostName,
    ServerPrincipalName,
    DurationMs,
    Statement,
    TenantId,
    _ResourceId
</code></pre>
<p>Here you can see the query I ran in the log with an action of BATCH COMPLETED.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005558424/3c4c8cc9-acc0-41c8-a260-ea82a2233863.png" alt /></p>
<h2 id="heading-viewing-the-diagnostic-logs-dmvs">Viewing the Diagnostic Logs (DMVs)</h2>
<p>Where all audit events are logged to the same table, regardless of the event type, each of the DMVs enabled in Diagnostic settings gets logged to its own table. Expanding on the list of DMVs from earlier in the post we can see the Log Analytics table closely matches the diagnostic setting name with a prefix of SynapseSqlPool.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Diagnostic Setting Label</td><td>System DMV</td><td>Log Analytics Table</td></tr>
</thead>
<tbody>
<tr>
<td>SqlRequests</td><td>sys.dm_pdw_sql_requests</td><td>SynapseSqlPoolSqlRequests</td></tr>
<tr>
<td>RequestSteps</td><td>sys.dm_pdw_request_steps</td><td>SynapseSqlPoolRequestSteps</td></tr>
<tr>
<td>ExecRequests</td><td>sys.dm_pdw_exec_requests</td><td>SynapseSqlPoolExecRequests</td></tr>
<tr>
<td>DmsWorkers</td><td>sys.dm_dms_workers</td><td>SynapseSqlPoolDmsWorkers</td></tr>
<tr>
<td>Waits</td><td>sys.dm_pdw_waits</td><td>SynapseSqlPoolWaits</td></tr>
</tbody>
</table>
</div><p>This sample query pulls a few of the relevant columns from the SynapseSqlPoolExecRequests table.</p>
<pre><code class="lang-sql">SynapseSqlPoolExecRequests
| summarize
    TimeGenerated = max(TimeGenerated),
    ResourceGroup = any(ResourceGroup),
    LogicalServerName = any(LogicalServerName),
    DatabaseId = any(toreal(DatabaseId)),
    StartTime = max(StartTime),
    EndCompileTime = max(EndCompileTime),
    Category = any(Category),
    Status = min(Status),
    Command = any(Command)
    by RequestId
</code></pre>
<p>Here you can see the query I ran in the SynapseSqlPoolExecRequests table.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005559483/0552c836-eab3-4035-bd5d-d883ec160109.png" alt /></p>
<h1 id="heading-wrapping-it-up">Wrapping it up</h1>
<p>There is a lot more that can be accomplished with KQL queries in Log Analytics. You may even take the queries found in the accompanying <a target="_blank" href="https://bradleyschacht.com/log-analytics-with-dedicated-sql-pools-formerly-sql-dw/">Dedicate SQL Pools (Formerly SQL DW)</a> post and combine them to give a single view of all your dedicate SQL pools.</p>
<p>The key take learning from this walkthrough is:</p>
<ol>
<li>Auditing and Diagnostics are different options and enabled in different locations.</li>
<li>Auditing writes all the data to a single table no matter the action.</li>
<li>Diagnostics pull a few key DMVs from Synapse and write them to the log. Each DMV is written to its own table in Log Analytics.</li>
<li>Something not discussed is that there is the potential on highly used systems for some audit or diagnostic records could be missed.</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Log Analytics with Dedicated SQL Pools (Formerly SQL DW)]]></title><description><![CDATA[There are a lot of services in Azure. Way more than a few. What is something you want to do with all your services and applications? You want to monitor them. How do you do that? By looking at the logs that are produced. How do you capture and make s...]]></description><link>https://test.bradleyschacht.com/log-analytics-with-dedicated-sql-pools-formerly-sql-dw</link><guid isPermaLink="true">https://test.bradleyschacht.com/log-analytics-with-dedicated-sql-pools-formerly-sql-dw</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Mon, 01 Nov 2021 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There are a lot of services in Azure. Way more than a few. What is something you want to do with all your services and applications? You want to monitor them. How do you do that? By looking at the logs that are produced. How do you capture and make sense of thousands of log entries from hundreds of services for this really awesome solution you’ve been working on? Azure Monitor.</p>
<p>This post isn’t about Azure Monitor though. Not directly anyway.</p>
<p>Azure Synapse is no different than any other application or service in your environment. It serves a purpose in the architecture and as a result needs special attention from people with a specific skillset, in this case DBAs and developers. That’s where Azure Monitor comes into the picture and what we will be discussing today: how to make sense of the integration between auditing in Dedicated SQL Pools (Formerly SQL DW) and Azure Monitor. The focus will be on Dedicated SQL Pools (Formerly SQL DW) not Azure Synapse Analytics, but more on that in a moment.</p>
<p>First, those with an eye for detail will notice that this post has Log Analytics in the title and not Azure Monitor. That’s true. A very brief explanation so everyone has things straight in their heads. I put Log Analytics in the title because when you set up auditing or diagnostics the option is labeled “Send to Log Analytics workspace” not “Send to Azure Monitor” and I wanted people to be able to find this post. Azure Monitor is a set of functionalities for collecting and analyzing logs. There are some prebuilt integrations and visualizations with some Azure services like Key Vault or Storage Accounts Then there is Log Analytics, a functionality inside Azure Monitor which also happens to be where Synapse writes its logs, for storing and querying all log data. Queries are written in a Kusto Query Language or KQL.</p>
<p>Second, let’s be sure a few very important details are clear. When referring to Azure Synapse there are two distinct but very similar services. They are both the same Microsoft cloud MPP database engine, both cover the same general T-SQL surface area, both scale in terms of DWUs, both talk about “Azure Synapse Analytics” in the documentation and description, but one is deployed to an Azure SQL Server, and one is deployed to a Workspace.</p>
<p>We need to be very clear about this because they both operate slightly different. Again, this post is focused on Dedicated SQL Pools (Formerly SQL DW). An alternate post is available for <a target="_blank" href="https://bradleyschacht.com/log-analytics-with-azure-synapse-analytics/">Azure Synapse Analytics Dedicated SQL Pools (Gen 2)</a> if you need information about that deployment option.</p>
<p>Let’s get started.</p>
<h1 id="heading-what-are-my-options">What are my options?</h1>
<p>There are two types of logging that can be enabled: Auditing and Diagnostics. Auditing tracks a set of database events like queries and login attempts. Diagnostics will make copies of a specific set of system DMVs periodically which can be helpful because Synapse only stores a few thousand records depending on the DMV.</p>
<p>Everything from here assumes that you have a Log Analytics workspace created and a Dedicated SQL Pools (Formerly SQL DW) deployed.</p>
<h1 id="heading-enabling-auditing">Enabling Auditing</h1>
<p>Auditing can be enabled at the logical server level, which will cover all databases on the logical server automatically, or at the individual database level.</p>
<p>First, navigate to your logical SQL server or dedicated SQL pool in the Azure Portal. My screenshots will show the configuration from the dedicated SQL pool, but the same setting can be found under the label of Auditing at the logical SQL server level. From here, select Auditing from the Security section.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005562525/0ecdbfcb-1da1-48cf-a0c2-fe274af00b52.png" alt /></p>
<p>Next, toggle the <strong>Enable Azure SQL Auditing</strong> to the on position. Next, check the boxes for the locations where you would like the log to be written, in this example we are going to focus on Log Analytics. Select a log analytics workspace to which the data will be written. Click <strong>Save</strong> once complete.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005563762/5024089d-a09b-40e3-b682-909978b46a0f.png" alt /></p>
<h1 id="heading-enabling-diagnostics">Enabling Diagnostics</h1>
<p>While Auditing can be turned on for a database by either enabling it at the logical SQL server or database level, diagnostics must be enabled at the database level. There are no diagnostics at the logical SQL server level.</p>
<p>If you’re not there already, navigate in the Azure Portal to your dedicated SQL pool. Select <strong>Diagnostic Settings</strong> from the <strong>Monitoring</strong> section.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005564721/76a487eb-a4e3-42ed-8467-859db330ed08.png" alt /></p>
<p>Next, click the <strong>Add diagnostic setting</strong> button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005565654/f88312cf-0f60-4dd8-bf6d-debf0eb8227c.png" alt /></p>
<p>Provide a name for this diagnostic setting. Check the box next to <strong>Send to Log Analytics workspace</strong>. Select the subscription and workspace to which the DMVs will be written. Select which DMVs you want to log. There is an additional SQLSecurityAuditEvents entry in my screenshot which is there because I already enabled the database audit. We'll ignore that for the time being. Finally, click Save.</p>
<p>Remember, the diagnostic settings each correspond to a different DMV that will be copied to your Log Analytics workspace. If you need additional DMVs you’ll need to roll your own auditing solution at this time.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Diagnostic Setting Label</td><td>System DMV</td></tr>
</thead>
<tbody>
<tr>
<td>SqlRequests</td><td>sys.dm_pdw_sql_requests</td></tr>
<tr>
<td>RequestSteps</td><td>sys.dm_pdw_request_steps</td></tr>
<tr>
<td>ExecRequests</td><td>sys.dm_pdw_exec_requests</td></tr>
<tr>
<td>DmsWorkers</td><td>sys.dm_dms_workers</td></tr>
<tr>
<td>Waits</td><td>sys.dm_pdw_waits</td></tr>
</tbody>
</table>
</div><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005566790/86550911-c2d1-464a-8858-4bc3192da53c.png" alt /></p>
<h1 id="heading-reading-the-logs">Reading the Logs</h1>
<p>Data will take several minutes to show up in Log Analytics. I’ve had the initial population take up to 30 minutes. After that the data should show up much more quickly, within several minutes. Connect to your database and run a query or two to ensure we have some user queries show up in the logs.</p>
<p>For my example I have run the following query:<br />SELECT *, GETDATE(), DB_NAME() FROM dbo.MyTable</p>
<p>To view the logs, you can navigate to your log analytics workspace, or select <strong>Logs</strong> from your dedicated SQL pool’s <strong>Monitoring</strong> section. This can be found directly beneath the Diagnostic Settings option used in the last section.</p>
<h2 id="heading-viewing-the-audit-log">Viewing the Audit Log</h2>
<p>Within the Log Analytics Workspace you may see a group of tables with the prefix Synapse*. These tables correspond to diagnostic settings configured on the Synapse Analytics Workspaces. If you do not have any Synapse Workspaces these tables will likely not show up. More tables may appear if you are using auditing for Azure SQL Database. The audit setup in the first section of this post will be logged to the AzureDiagnostics table.</p>
<p>This sample query pulls a few of the relevant columns from the AzureDiagnostics table by narrowing down the data to the SQLSecurityAuditEvents category which is used for the Audit log. For Synapse Workspace Dedicated SQL Pools, as opposed to the "formerly SQL DW" SQL Pools that are the focus of this post, the data is written to a separate table called SQLSecurityAuditEvents rather than being a category of log within the AzureDiagnostics table.</p>
<pre><code class="lang-sql">AzureDiagnostics
| where Category == "SQLSecurityAuditEvents"
| project
        ResourceGroup,
        LogicalServerName_s,
        database_name_s,
        event_time_t,
        Category,
        action_name_s,
        tobool(is_server_level_audit_s),
        tobool(succeeded_s),
        tostring(session_id_d),
        client_ip_s,
        host_name_s,
        server_principal_name_s,
        tolong(duration_milliseconds_d),
        statement_s,
        TenantId,
        _ResourceId
| project-<span class="hljs-keyword">rename</span>
        ResourceGroup,
        LogicalServerName=LogicalServerName_s,
        DatabaseName=database_name_s,
        EventTime=event_time_t,
        <span class="hljs-keyword">Category</span>,
        ActionName=action_name_s,
        IsServerLevelAudit=is_server_level_audit_s,
        Succeeded=succeeded_s,
        SessionId=session_id_d,
        ClientIp=client_ip_s,
        HostName=host_name_s,
        ServerPrincipalName=server_principal_name_s,
        DurationMs=duration_milliseconds_d,
        <span class="hljs-keyword">Statement</span>=statement_s,
        TenantId,
        _ResourceId
</code></pre>
<p>Here you can see the query I ran in the log with an action of BATCH COMPLETED.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005567853/f62baae0-8646-4297-a19d-206de22d2d73.png" alt /></p>
<h2 id="heading-viewing-the-diagnostic-logs-dmvs">Viewing the Diagnostic Logs (DMVs)</h2>
<p>Where Synapse Workspaces write DMV data to separate tables, for Dedicated SQL Pools (Formerly SQL DW) each of the DMVs enabled in Diagnostic settings gets logged to the same AzureDiagnostics table used in the Auditing section above, but with a category that corresponds to the diagnostic setting/System DMV.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Diagnostic Setting Label</td><td>System DMV</td><td>Log Analytics AzureDiagnostics Category</td></tr>
</thead>
<tbody>
<tr>
<td>SqlRequests</td><td>sys.dm_pdw_sql_requests</td><td>SqlRequests</td></tr>
<tr>
<td>RequestSteps</td><td>sys.dm_pdw_request_steps</td><td>RequestSteps</td></tr>
<tr>
<td>ExecRequests</td><td>sys.dm_pdw_exec_requests</td><td>ExecRequests</td></tr>
<tr>
<td>DmsWorkers</td><td>sys.dm_dms_workers</td><td>DmsWorkers</td></tr>
<tr>
<td>Waits</td><td>sys.dm_pdw_waits</td><td>Waits</td></tr>
</tbody>
</table>
</div><p>This sample query pulls a few of the relevant columns from the AzureDiagnostics table by narrowing the data down to the ExecRequests Category. This data corresponds to the system DMV sys.dm_pdw_exec_requests.</p>
<pre><code class="lang-sql">AzureDiagnostics
| where Category == "ExecRequests"
| project
    ResourceGroup,
    LogicalServerName_s,
    DatabaseId_d,
    StartTime_t,
    EndCompileTime_t,
    Category,
    Status_s,
    RequestId_s,
    Command_s
| summarize
    ResourceGroup = any(ResourceGroup),
    LogicalServerName = any(LogicalServerName_s),
    DatabaseId = any(DatabaseId_d),
    StartTime = max(StartTime_t),
    EndCompileTime = max(EndCompileTime_t),
    Category = any(Category),
    Status = min(Status_s),
    Command = any(Command_s),
    record_count = count()
    by RequestId_s
</code></pre>
<p>Here you can see the query I ran focused on the ExecRequests category.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005568816/d60f8f2b-7797-403d-be7f-98697fc59742.png" alt /></p>
<h1 id="heading-wrapping-it-up">Wrapping it up</h1>
<p>There is a lot more that can be accomplished with KQL queries in Log Analytics. You may even take the queries found in the accompanying <a target="_blank" href="https://bradleyschacht.com/log-analytics-with-azure-synapse-analytics/">Azure Synapse Analytics Dedicated SQL Pools (Gen 2)</a> post and combine them to give a single view of all your dedicate SQL pools.</p>
<p>The key take learning from this walkthrough is:</p>
<ol>
<li>Auditing and Diagnostics are different options and enabled in different locations.</li>
<li>Auditing writes all the data to a single table no matter the action.</li>
<li>Diagnostics pull a few key DMVs from Synapse and write them to the log. Each DMV is written to the same table in Log Analytics each with a different category.</li>
<li>Something not discussed is that there is the potential on highly used systems for some audit or diagnostic records could be missed.</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[How to Resolve Remove-AzKeyVaultKey : Operation returned an invalid status code 'Forbidden' Error]]></title><description><![CDATA[I've come across another error message in my seemingly never-ending battle with Azure Key Vault. A while back I couldn't delete a resource group because of Key Vault soft-delete. Then I couldn't recreate a Key Vault with the same name again because o...]]></description><link>https://test.bradleyschacht.com/how-to-resolve-remove-azkeyvaultkey-operation-returned-an-invalid-status-code-forbidden-error</link><guid isPermaLink="true">https://test.bradleyschacht.com/how-to-resolve-remove-azkeyvaultkey-operation-returned-an-invalid-status-code-forbidden-error</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Tue, 28 Jan 2020 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I've come across another error message in my seemingly never-ending battle with Azure Key Vault. A while back I couldn't delete a resource group because of Key Vault soft-delete. Then I couldn't recreate a Key Vault with the same name again because of soft-delete. Which brings us to today's post where I had to go to PowerShell and purge a key that but ran into an issue because of soft-delete.</p>
<p>Maybe my issue isn't with Key Vault so much as it is with soft-delete.</p>
<p>While doing some testing for <a target="_blank" href="https://bradleyschacht.com/bring-your-own-key-to-azure-sql-database-managed-instance-tde">TDE protectors on Managed Instance</a> I had to remove a key and recreate it for part of my test setup. The key I deleted earlier in the day was named ManagedInstance. So when I went to create a new key called ManagedInstance in the Azure Portal I received an error message. No big deal, I had this one in the bag. Go to PowerShell, find the key, remove the key, go back to the portal and try again. Unfortunately, I hit a snag. Let's walk through the code and see where I went wrong.</p>
<p>To remove a soft-deleted key you must first locate the key's name or Id. To do this we will use the Get-AzKeyVaultKey cmdlet with the parameter -InRemovedState to show all the deleted, but not really deleted (aka soft-deleted) keys.</p>
<pre><code class="lang-powershell"><span class="hljs-built_in">Get-AzKeyVaultKey</span> <span class="hljs-literal">-VaultName</span> <span class="hljs-string">"bschacht-kv"</span> <span class="hljs-literal">-InRemovedState</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005546932/c5dfa4bf-dfeb-444f-bcc8-6b4fe1c470b8.png" alt /></p>
<p>Make note of the name or Id and move on to the next cmdlet and we will be done...or we should have been done anyway. We will use Remove-AzKeyVaultKey, specify the key name to be removed, make note that this key is in a removed state and run the cmdlet. Except here is where I ran into the somewhat unhelpful error message Remove-AzKeyVaultKey : Operation returned an invalid status code 'Forbidden'.</p>
<pre><code class="lang-powershell"><span class="hljs-built_in">Remove-AzKeyVaultKey</span> <span class="hljs-literal">-VaultName</span> <span class="hljs-string">"bschacht-kv"</span> <span class="hljs-literal">-Name</span> <span class="hljs-string">"ManagedInstance"</span> <span class="hljs-literal">-InRemovedState</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005547701/e82d62eb-401a-47cd-bfba-d4c1e30023bd.png" alt /></p>
<p>It turns out this error message stems from the user running the command (myself in this case) doesn't not have purge permissions explicitly granted in the Key Vault. Running this cmdlet requires the purge permission, no inherited RBAC or explicitly granted RBAC roles no matter how high up the food chain (Contributor, Owner, etc.) will give you the ability to remove a soft-deleted key. You must go to the Azure Portal, navigate to your Key Vault, go to Access Policies, and grant the user running this cmdlet the Purge permission for keys which is in a special section on the dropdown menu called "Privileged Key Operations".</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005548760/80bebee8-04d1-453b-9da2-2574e56b8405.png" alt /></p>
<p>Now, let's run the Remove-AzKeyVaultKey cmdlet again, verify that we are sure we want to remove the key permanently, and no response means success!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005549806/22d119b4-2cca-4680-826c-63879b123aef.png" alt /></p>
<p>There you have it. In the end it was a very simple fix. Unfortunately that error message seems to be less than well documented. Thankfully, if you go look at the <a target="_blank" href="https://docs.microsoft.com/en-us/powershell/module/az.keyvault/remove-azkeyvaultkey">documentation for the cmdlet</a> under example 3 (which, let's be honest, who does that unless they run into a problem and have to go looking for an answer) you will in fact see the purge permission noted. Too bad I don't read instructions. I just go run things and see what happens. It's a great way to learn...as long as you aren't doing it in production.</p>
]]></content:encoded></item><item><title><![CDATA[Bring Your Own Key to Azure SQL Database Managed Instance TDE]]></title><description><![CDATA[Last year Azure SQL Database Managed Instance saw the introduction of bring your own key (BYOK) functionality for transparent data encryption (TDE). This functionality has been in the singleton database version of Azure SQL Database for a while longe...]]></description><link>https://test.bradleyschacht.com/bring-your-own-key-to-azure-sql-database-managed-instance-tde</link><guid isPermaLink="true">https://test.bradleyschacht.com/bring-your-own-key-to-azure-sql-database-managed-instance-tde</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Fri, 24 Jan 2020 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Last year Azure SQL Database Managed Instance saw the introduction of bring your own key (BYOK) functionality for transparent data encryption (TDE). This functionality has been in the singleton database version of Azure SQL Database for a while longer and you can <a target="_blank" href="https://bradleyschacht.com/bring-your-own-key-to-azure-sql-database-tde-new-ui/">read about how to use that here</a>. The experience between the two is very similar, but let's focus on the Managed Instance side of things today.</p>
<p>A few prerequisites for today:</p>
<ul>
<li>Azure SQL Managed Instance (any service tier, any size)</li>
<li>A database (any user database will do, even an empty one)</li>
<li>Azure Key Vault (with soft-delete enabled)</li>
<li>Storage Account (optional, if you want to test the backup/restore process)</li>
</ul>
<h2 id="heading-switching-to-bring-your-own-key">Switching to Bring Your Own Key</h2>
<p>Bringing your own key for TDE is actually not a requirement to use Managed Instance. By default, the service will manage its own TDE key. However, that comes with a few limitations. The main one being you cannot create user initiated backups when using the service-managed key. The built-in backup/restore functionality still works just fine with service-managed keys though.</p>
<p>The key settings can be found by navigating the <a target="_blank" href="http://portal.azure.com">Azure Portal</a> to your Managed Instance and clicking on the <strong>Transparent Data Encryption</strong> option in the service navigation panel. Then change the</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005526186/e5f13104-1c66-4644-95fc-55dd97ba8521.png" alt /></p>
<p>The next step is to identify the key that will be used for encrypting the databases. This can be done in one of two ways: choosing a Key Vault and Key from inside the tenant or specifying a key identifier URL for a particular key. The second option is particularly useful if the user doing the configuration does not have access to the list of Key Vaults/Keys but is given a key identifier that should be used. The two configuration options can be seen in the following screenshot.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005527168/8ac4b3de-7f4f-4a90-9b8a-af34dc87fb08.png" alt /></p>
<h4 id="heading-important-notes">Important Notes</h4>
<p>A few important pieces of information to note on from these settings.</p>
<p>First, the Managed Instance must be granted access through a Key Vault access policy. If that has not already been completed an attempt will be made to add the Managed Instance with the appropriate permissions (Get, Wrap Key, Unwrap Key). The access policy is defined and enforced at the vault level, not the individual key, secret, or certificate level. So an instance with Get access to one key in this vault will have Get access to all the keys in this vault.</p>
<p>The second piece of important information is the check box labeled <strong>Make the selected key the default TDE protector.</strong> By checking that box, all databases will be encrypted using the selected key. The situation may arise where you would like to simply restore a database protected with a particular key, but you do not wish to encrypt the databases on the server with that key. In that scenario, you will want to add the key to the Managed Instance, but NOT select the option to make it the default TDE protector.</p>
<p>Next, the Managed Instance and Key Vault must be in the same Active Directory tenant. At this time it is not supported to backup keys from one subscription and move them to another subscription, the keys must remain in the same subscription but can be moved to another vault someplace else in the same geography (moving between Key Vaults in North America that reside in the same subscription is supported, moving between a Key Vault in North America and one in Europe is not supported even if they are in the same subscription.</p>
<p>Finally, changing the default TDE protector does not encrypt existing backups with the new key. So it is important for business continuity that you retain the prior TDE key(s) in order to be able to restore backups. If you switch from customer-managed key back to service-managed key you must retain the copy of your key in Key Vault at least until the system's point-in-time restore window has rolled off for the customer-managed keys (i.e. retain the customer-managed key for 7-35 days depending on your configuration after switching back to service-managed key).</p>
<p>There is one and only one key that will protect the databases on an instance.</p>
<ul>
<li>Key marked as "Make the selected key the default TDE protector."<ul>
<li>Can restore databases encrypted with this key.</li>
<li>Will be the key used to encrypt the user databases on the instance.</li>
<li>A database restored with this key will also be encrypted with this key.</li>
</ul>
</li>
<li>Key NOT marked as "Make the selected key the default TDE protector."<ul>
<li>Can restored databases encrypted with this key.</li>
<li>A database restored with this key will be encrypted with the key marked as the protector after the restore process is completed.</li>
</ul>
</li>
</ul>
<h2 id="heading-see-it-in-action-changing-to-customer-managed-key">See it in Action - Changing to Customer-Managed Key</h2>
<p>As a starting point I have a Managed Instance with a single database, TDETesting, that is encrypted with the service-managed key.</p>
<p>We can use a simple T-SQL query to get the encryptor thumbprint. This same query will help us identify when the key has changed.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span>
    DB_NAME(database_id) <span class="hljs-keyword">AS</span> database_name,
    encryption_state,
    <span class="hljs-keyword">CASE</span> encryption_state
        <span class="hljs-keyword">WHEN</span> <span class="hljs-number">0</span> <span class="hljs-keyword">THEN</span> <span class="hljs-string">'No Encryption Key Present. Database Not Encrypted.'</span>
        <span class="hljs-keyword">WHEN</span> <span class="hljs-number">1</span> <span class="hljs-keyword">THEN</span> <span class="hljs-string">'Database Unencrypted'</span>
        <span class="hljs-keyword">WHEN</span> <span class="hljs-number">2</span> <span class="hljs-keyword">THEN</span> <span class="hljs-string">'Database Encryption in Progress'</span>
        <span class="hljs-keyword">WHEN</span> <span class="hljs-number">3</span> <span class="hljs-keyword">THEN</span> <span class="hljs-string">'Database Encrypted'</span>
        <span class="hljs-keyword">WHEN</span> <span class="hljs-number">4</span> <span class="hljs-keyword">THEN</span> <span class="hljs-string">'Encryption Key Change in Progress'</span>
        <span class="hljs-keyword">WHEN</span> <span class="hljs-number">5</span> <span class="hljs-keyword">THEN</span> <span class="hljs-string">'Database Decryption in Progress'</span>
        <span class="hljs-keyword">WHEN</span> <span class="hljs-number">6</span> <span class="hljs-keyword">THEN</span> <span class="hljs-string">'Certificate or Key Change in Progress'</span>
        <span class="hljs-keyword">ELSE</span> <span class="hljs-string">'Unknown Status'</span>
        <span class="hljs-keyword">END</span> <span class="hljs-keyword">AS</span> encryption_state_descriptoin,
    encryptor_thumbprint
<span class="hljs-keyword">FROM</span> sys.dm_database_encryption_keys
</code></pre>
<p>We can see that based on the query results the current thumbprint is 0x051082BA88D2882F551C530B74EB6F4380843029.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005528289/52d2e56e-4c33-43cf-9a5e-58553b7c0083.png" alt /><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005529319/ac42ea18-fcbe-447b-a022-92b6a2df4ee6.png" alt /></p>
<p>Before the switching to the customer-managed key, this is what the access policy settings look like on my Key Vault. The only user that has rights to do anything is myself.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005530186/b703b971-753e-4287-b659-73beead179ec.png" alt /></p>
<p>From my Managed Instance I will switch to customer-managed key.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005531166/d6800595-db21-4bec-a80e-771143c6b6d9.png" alt /></p>
<p>Select my Key Vault.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005532261/f56d3b0e-5299-4347-902a-31e059b34cf1.png" alt /></p>
<p>And on the select a key blade, I will choose create a new key as I do not already have a key to use.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005533212/909e020c-84d7-473a-97f7-2b6e5ad5a059.png" alt /></p>
<p>I will keep the option on generate to create a key and provide a name. I'm going to use ManagedInstance, but there is not a specific name that is required. Then Click create.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005534035/fb827614-f26c-48e8-be43-074001ddd4d5.png" alt /></p>
<p>With all the options configured click Save.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005535102/3d08dd69-e2eb-453d-8fc5-aabee4dd8f22.png" alt /></p>
<p>After the settings are applied we can see the change in access policy on the Key Vault has added my Managed Instance with Get, Wrap, and Unwrap permissions.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005535983/8995a373-d063-43b1-9122-a0ac4c652367.png" alt /></p>
<p>Additionally, running our T-SQL script we can see the encryptor thumbprint has now changed from 0x051082BA88D2882F551C530B74EB6F4380843029 to 0x71ABFFF1EAA10687BD43878C75E7F2D1744E285C.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005537102/79f81736-7660-4aa9-9a3c-0ebc615981ab.png" alt /></p>
<p>With the customer-managed key in place, we can now run a create a user backup of the database.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">BACKUP</span> <span class="hljs-keyword">DATABASE</span> TDETesting <span class="hljs-keyword">TO</span> <span class="hljs-keyword">URL</span> = <span class="hljs-string">'https://bschachtstor.blob.core.windows.net/backup/TDETesting.bak'</span> <span class="hljs-keyword">WITH</span> COPY_ONLY
</code></pre>
<p>If we then look at the files in that backup, we will see that it is encrypted with the same thumbprint as our database showed after switching to customer-managed keys.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">RESTORE</span> FILELISTONLY <span class="hljs-keyword">FROM</span> <span class="hljs-keyword">URL</span> = <span class="hljs-string">'https://bschachtstor.blob.core.windows.net/backup/TDETesting.bak'</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005537957/6543ab60-410a-44b0-aa90-74078eed6bf0.png" alt /></p>
<h2 id="heading-see-it-in-action-restoring-a-backup">See it in Action - Restoring a Backup</h2>
<p>What happens when we need to restore a database that has been backed up under a different key? In this particular case I have a backup that was created under a different customer-managed key. This screenshot shows a different thumbprint than the system or current customer-managed key, 0x190256228610BBE409C0345597D49ABB5A40EFA6.</p>
<p>System key thumbprint: 0x051082BA88D2882F551C530B74EB6F4380843029<br />Current key thumbprint: 0x71ABFFF1EAA10687BD43878C75E7F2D1744E285C<br />Backup key thumbprint: 0x190256228610BBE409C0345597D49ABB5A40EFA6</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005539107/91026e93-f908-426e-a1c0-75d65c7bac7f.png" alt /></p>
<p>In the Azure Portal, I changed the key to the new ManagedInstance-AlternateKey that I added to my Key Vault. However, I did not choose the <strong>Make the selected key the default TDE protector</strong> option as I want to continue to encrypt my databases with the key used previously in this example but restore databases that are encrypted with the ManagedInstance-AlternateKey.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005540041/968896f7-b232-498d-ac15-397d6fd914e4.png" alt /></p>
<p>After saving the change I can now run the restore of my database that is encrypted with the ManagedInstance-AlternateKey (thumbprint 0x190256228610BBE409C0345597D49ABB5A40EFA6). After the restore completes we can see that the database encryptor has been switched to the thumbprint 0x71ABFFF1EAA10687BD43878C75E7F2D1744E285C that is used on my existing database. As mentioned previously, the current implementation is such that all databases are encrypted with the same key. So while the key ending in EFA6 is required for the restore process the database is then encrypted with the TDE protector key ending in 285C.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005541047/e3ca6cc1-1309-43a4-b5b4-6556a890a1f0.png" alt /></p>
<h2 id="heading-what-keys-are-associated-with-my-managed-instance">What Keys Are Associated with my Managed Instance?</h2>
<p>We have seen how we can assign a customer-managed key to Managed Instance, add an additional key for restore purposes, how to see which key is encrypting the database, and how to restore backups encrypted with non-TDE Protector keys. There can be confusion as to what keys are available though because the Azure Portal only shows the last key assigned. In our demo walkthrough that wasn't even the TDE Protector key. How then do we find what keys are available to our managed instance for restore commands and what key is the current TDE Protector?</p>
<p>For that we go to PowerShell.</p>
<p>Get-AzSqlInstanceKeyVaultKey will give a list of all keys currently associated with your managed instance. In order for a backup file to be restored to your Managed Instance the key with which the backup was encrypted must be listed. In my example there is a service-managed key and two customer-managed keys with the thumbprints from earlier in this post.</p>
<pre><code class="lang-powershell"><span class="hljs-built_in">Get-AzSqlInstanceKeyVaultKey</span> <span class="hljs-literal">-ResourceGroupName</span> <span class="hljs-string">"ManagedInstance-RG"</span> <span class="hljs-literal">-InstanceName</span> <span class="hljs-string">"bschacht-sqlmi01"</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005542080/f22e0d85-51a3-424b-809e-ac267665a70e.png" alt /></p>
<p>However, there is no indication of the current TDE Protector. For that we will go to a different PowerShell cmdlet, Get-AzSqlInstanceTransparentDataEncryptionProtector.</p>
<pre><code class="lang-powershell"><span class="hljs-built_in">Get-AzSqlInstanceTransparentDataEncryptionProtector</span> <span class="hljs-literal">-ResourceGroupName</span> <span class="hljs-string">"ManagedInstance-RG"</span> <span class="hljs-literal">-InstanceName</span> <span class="hljs-string">"bschacht-sqlmi01"</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005543155/99e38b9a-4542-4375-80ce-b89ebecf44c4.png" alt /></p>
<p>Removing a key is also a simple operation with the cmdlet Remove-AzSqlInstanceKeyVaultKey.</p>
<pre><code class="lang-powershell"><span class="hljs-built_in">Remove-AzSqlInstanceKeyVaultKey</span> <span class="hljs-literal">-ResourceGroupName</span> <span class="hljs-string">"ManagedInstance-RG"</span> <span class="hljs-literal">-InstanceName</span> <span class="hljs-string">"bschacht-sqlmi01"</span> <span class="hljs-literal">-KeyId</span> https://bschacht<span class="hljs-literal">-kv</span>.vault.azure.net/keys/ManagedInstance<span class="hljs-literal">-AlternateKey</span>/<span class="hljs-number">2603353</span>efae04fbab840385dd43a590b
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005544042/52f8cf71-96e5-4c9b-a01d-b537210c7af5.png" alt /></p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>What other questions do you have about using TDE with Azure SQL Database Managed Instance? Let me know in the comments and I'll see if I can work through some examples with you.</p>
]]></content:encoded></item><item><title><![CDATA[Building an Azure Sandbox - Part 1 - The Basics]]></title><description><![CDATA[I recently posted that I was doing my annual Azure sandbox rebuild but this time I wanted to do things a little differently...all in PowerShell. Unlike previous years when I would remove most of the resources, this year I removed all of the resources...]]></description><link>https://test.bradleyschacht.com/building-an-azure-sandbox-part-1-the-basics</link><guid isPermaLink="true">https://test.bradleyschacht.com/building-an-azure-sandbox-part-1-the-basics</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Mon, 25 Nov 2019 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I recently posted that I was doing my <a target="_blank" href="https://bradleyschacht.com/building-an-azure-sandbox/">annual Azure sandbox rebuild</a> but this time I wanted to do things a little differently...all in PowerShell. Unlike previous years when I would remove most of the resources, this year I removed all of the resources. As in I log into the Azure Portal and it says no resources to display. No databases, no networks, not even an empty resource group.</p>
<p>As I work through this process I am going to post the scripts that I use. These are by no means meant to take back and use to build your enterprise environment. There are many not so best practices in the scripts, lots of copy and paste where there should be variables, no logic to check if resources exist or remove if they do exist, and a bunch of things that could likely be done more efficiently.</p>
<h2 id="heading-getting-started">Getting Started</h2>
<p>All you need to get started is a PowerShell window. I'm using <a target="_blank" href="https://bradleyschacht.com/using-visual-studio-code/">Visual Studio Code</a> but this could just as easily been done with the PowerShell ISE. Visual Studio Code is a great cross platform tool that can be <a target="_blank" href="http://aka.ms/vscode">downloaded here</a>.</p>
<p>Once your favorite code editor is open it's time to install the Az module which is used for interacting with Azure. If you've used PowerShell for Azure in the past you may remember the AzureRM (Azure Resource Manager) module. This is the next evolution of the AzureRM module which has been deprecated. Make sure you are running your application as an administrator and run Install-Module Az.</p>
<pre><code class="lang-powershell"><span class="hljs-built_in">Install-Module</span> Az
</code></pre>
<p>The Az module cmdlets follow a pretty general format.</p>
<ul>
<li><strong>Get-Something</strong> will pull back all of that particular resource. For instance, Get-ResourceGroup will list all the resource groups. Get-AzVirtualNetwork will return all the virtual networks. It's an easy way to validate what you have just created or modified. Most of these commands are going to require you to specify at least a resource group.</li>
<li><strong>New-Something</strong> will create a new resource. For instance, New-AzVirtualNetwork will create a new virtual network. Almost all of these commands require a name for the resource, the location to which the resource will be deployed (Azure region), and the resource group in which to create the resource.</li>
<li><strong>Remove-Something</strong> will remove the specified resource. Again, most of these commands will require at least a name and a resource group to be specified.</li>
<li><strong>Set-Something</strong> will apply a change to a resource. For instance, Set-AzNetworkSecurityGroup will apply a change made to an NSG object. The change isn't actually committed and reflected in the resource until the Set command is run.</li>
</ul>
<p>Next we will connect to our Azure account and tell our session which subscription (assuming there is more than one available) to use. We will log in, list the subscriptions, the current context, and if necessary, change subscriptions.</p>
<pre><code class="lang-powershell"><span class="hljs-comment">#Connect to Azure account.</span>
Login<span class="hljs-literal">-AzAccount</span>
<span class="hljs-comment">#List all the subscriptions and see the current subscription context.</span>
<span class="hljs-built_in">Get-AzSubscription</span>
<span class="hljs-built_in">Get-AzContext</span>
<span class="hljs-comment">#Set the context to the appropriate subscription.</span>
<span class="hljs-built_in">Select-AzSubscription</span> <span class="hljs-literal">-SubscriptionId</span> <span class="hljs-string">"########-####-####-####-#########"</span> | <span class="hljs-built_in">Set-AzContext</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005522327/563e7d8d-463e-429f-af0e-69ad683e7830.png" alt /></p>
<h2 id="heading-lets-break-some-stuff">Let's Break Some Stuff</h2>
<p>What kind of learning exercise would this be if we didn't try to break some things. Just for the heck of it, let's unregister all of the providers. Providers tell us what resources we are able to spin up inside a given subscription. It's basically like a master switch at the subscription level for enabling and disabling different Azure features. For instance, if you don't register the Microsoft.DataFactory resource provider then you won't be able to create a new Azure Data Factory. The options will still show up in the portal, it will just give an error if you try to create one.</p>
<pre><code class="lang-powershell"><span class="hljs-comment">#Just because I like to break things to see what happens. Let's unregister all the resource providers.</span>
<span class="hljs-built_in">Get-AzResourceProvider</span> | <span class="hljs-built_in">Unregister-AzResourceProvider</span>
<span class="hljs-comment">#Interestingly enough, there were a handful that I was unable to disable.</span>
<span class="hljs-built_in">Get-AzResourceProvider</span> | <span class="hljs-built_in">Format-Table</span>
</code></pre>
<p>Fortunately and unfortunately this didn't quite break things. I was really hoping that I was going to start getting error messages when attempting to add a storage account that said I needed to go register the provider. What happens, in reality, is that if you have the permissions to enable a particular provider it will automatically register when a new provider is needed. For my little test this meant that adding new resources automatically registered the necessary providers because I'm an Owner (aka administrator) on my subscription. Test somewhat failed but still an interesting experiment. I went and looked what providers were registered after a few later commands, but in practice I kept writing code, running it, and forgetting to go check the provider list.</p>
<h2 id="heading-resource-groups">Resource Groups</h2>
<p>A vital starting point for the remainder of this series is creation of Resource Groups. These are simply logical containers where you can set restrictions if you so choose. Limit the resources that can be used, the location where they can be deployed, and set permissions that will cascade to the resources therein. We will start by setting up a few different resource groups that will be used in the future.</p>
<pre><code class="lang-powershell"><span class="hljs-comment">#Create a few core resource groups.</span>
<span class="hljs-built_in">New-AzResourceGroup</span> <span class="hljs-literal">-Name</span> <span class="hljs-string">"ManagedInstance-RG"</span> <span class="hljs-literal">-Location</span> <span class="hljs-string">"eastus2"</span>
<span class="hljs-built_in">New-AzResourceGroup</span> <span class="hljs-literal">-Name</span> <span class="hljs-string">"PlatformServices-RG"</span> <span class="hljs-literal">-Location</span> <span class="hljs-string">"eastus2"</span>
<span class="hljs-built_in">New-AzResourceGroup</span> <span class="hljs-literal">-Name</span> <span class="hljs-string">"SqlDatabase-RG"</span> <span class="hljs-literal">-Location</span> <span class="hljs-string">"eastus2"</span>
<span class="hljs-built_in">New-AzResourceGroup</span> <span class="hljs-literal">-Name</span> <span class="hljs-string">"Storage-RG"</span> <span class="hljs-literal">-Location</span> <span class="hljs-string">"eastus2"</span>
<span class="hljs-built_in">New-AzResourceGroup</span> <span class="hljs-literal">-Name</span> <span class="hljs-string">"VirtualMachine-RG"</span> <span class="hljs-literal">-Location</span> <span class="hljs-string">"eastus2"</span>
<span class="hljs-built_in">New-AzResourceGroup</span> <span class="hljs-literal">-Name</span> <span class="hljs-string">"VirtualNetwork-RG"</span> <span class="hljs-literal">-Location</span> <span class="hljs-string">"eastus2"</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005523228/f98d00f5-9db4-4538-9fa4-6166c29cbb15.png" alt /></p>
<h2 id="heading-what-location-should-i-use">What location should I use?</h2>
<p>Location. Location. Location. It's said of real estate all the time and the Azure cloud is no different. Every single resource that is created will ask you for a location which ties back to an Azure region. In general, you'll want to choose the closest region and use the same region for all your resources. The challenge, however, is that not all services are available in all regions. Certain VM sizes are only in certain places. Services light up in some regions ahead of others depending on hardware availability. There will be times when everything can't sit in the same region so you'll want to choose another one that's close by as a secondary or one across the country that will be used for DR or bringing the solution closer to a geographically distributed usergroup.</p>
<p>How do you know what location options there are? How do you know what the right name is to use for the location East US 2, or West Europe? As with all things...run a PowerShell command.</p>
<pre><code class="lang-powershell"><span class="hljs-built_in">Get-AzLocation</span>
</code></pre>
<p>This command will provide a list of regions and the services available in each region. The location attribute is the value that should be placed into other cmdlets when prompted for the "location" parameter.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>At this point our shell is ready. Our code editor is configured. We've installed the necessary module to interact with Azure. We've connected to our subscription and created resource groups to hold everything that will be built in the coming posts.</p>
<p>I would encourage you to have the Azure Portal open at the same time you are running the PowerShell commands. Run a command, try to pull back the changes in PowerShell, and also go check the portal to see what has been created. Does it match up with what you expected to see? If not, do some research and try to figure out why and if there is anything you can do to control the created resources. Maybe that's a disk automatically created with a name you don't like, a virtual cluster, a resource group, etc. This is the time to learn it so when you're creating scripts to deploy to production you know exactly what the code is going to do.</p>
]]></content:encoded></item><item><title><![CDATA[Using Visual Studio Code]]></title><description><![CDATA[I'm a creature of habit. I have my routine when I get to my hotel room on business trips. I have a way I like my email and notes organized. I don't want fruits or veggies on my pizza. And I like tools that I've always used. Don't mess with my tools. ...]]></description><link>https://test.bradleyschacht.com/using-visual-studio-code</link><guid isPermaLink="true">https://test.bradleyschacht.com/using-visual-studio-code</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Tue, 19 Nov 2019 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I'm a creature of habit. I have my routine when I get to my hotel room on business trips. I have a way I like my email and notes organized. I don't want fruits or veggies on my pizza. And I like tools that I've always used. Don't mess with my tools. I know my shortcut keys in SQL Server Management Studio. I work well in the PowerShell ISE. I know my way around Visual Studio.</p>
<p>Fortunately and unfortunately we live in a time when technology is constantly changing and that means we need tools that are able to adapt and keep up with that change. I've used Visual Studio Code for a while just to edit scripts but never really for my day to day code development. I figured that if I'm going to be <a target="_blank" href="https://bradleyschacht.com/building-an-azure-sandbox/">rebuilding my Azure sandbox</a>, I may as well do it all in PowerShell. Since the PowerShell ISE is no longer being updated I also figured that I should make the move over to Visual Studio Code for as much of my work as I can. Just this week, Microsoft announced that <a target="_blank" href="https://visualstudio.microsoft.com/services/visual-studio-online/">Visual Studio was going online</a> so this is a perfect time to try and force myself into the VS Code world.</p>
<p>So here I go. Into VS Code. I will try my best to change with the times and move over to new software and new tools that promise a great big beautiful tomorrow. Maybe this will finally get me to use <a target="_blank" href="https://docs.microsoft.com/en-us/sql/azure-data-studio/download?view=sql-server-ver15">Azure Data Studio</a> full time (or close to full time) too considering Data Studio is built on top of VS Code.</p>
<p>I'll try to keep this post up to date with the things I'm doing along the way over these couple weeks while I do my sandbox rebuild. It will also be my reference in the future for "what the junk is happening and why can't I do what I want to do?!".</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005519756/9f9a023a-01d7-4c23-97f3-e9b7f64c21c7.png" alt /></p>
<h2 id="heading-thoughts-with-brad">Thoughts with Brad</h2>
<p>I'm in a whole new world. I feel a bit lost right now. Things look pretty. I know this will do everything I want it to do but nothing does quite what I want it to do out of the box. I've gotten far to used to SQL Server Management Studio. Here we go.</p>
<p>I'm noticing many of the shortcuts that I'm used to are there but are just a little different. For instance, Alt + Shift + Up/Down Arrow is now Ctrl + Alt + Shift + Up/Down Arrow.</p>
<p>I may be starting to get the hang of this. I've got a couple extensions. I've got some keyboard shortcuts. I've customized some settings. I still don't feel quite as at home as I do in other tools. For some reason it feels like VS Code isn't quite as polished and as nice of a UI or user experience as other tools. I guess that's what happens when you use a single tool to rule them all though.</p>
<p>I decided to hide the minimap. I don't know that it's super useful for me, but I am sure some will love it. Added that to the settings file.</p>
<p>I'm considering trying out the dark mode for a few days. I generally have my settings for Windows, Visual Studio, Management Studio, on the Light themes that are now shipping. A LOT of people are dark mode fans though, so maybe I'll try it and see if I can get used to it. In the past I haven't really given it a fair shot. We shall see. Not right now though.</p>
<p>Hmmm. This has already come in handy. If you highlight some text then press either " (quote) or ' (apostrophe) on your keyboard it will wrap everything that is highlighted in single or double quotes. Nice little time saver. Nifty.</p>
<h2 id="heading-extensions">Extensions</h2>
<p>Extension are proving to be quite useful! I knew I was going to need things like the SQL tooling and PowerShell, but there are a lot of neat extensions out there. I'm hoping that everything just works when I start to do this all in Visual Studio online.</p>
<p><strong>PowerShell</strong><br />Allows me to develop PowerShell scripts right inside VS Code. Adds PowerShell language support and allows me to debug code right inside VS Code too. I may have to check out PowerShell Pro Tools at some point in the future too as I do miss the module explorer from the PowerShell ISE where it was searchable, showed parameters, and had descriptions. I want to see if the Pro Tools one is any better than the one in the basic PowerShell extension.</p>
<p><strong>Theme by Language</strong><br />Changes the color theme based on the language selected in a given editor tab. This is really useful for making PowerShell look like PowerShell but have the other tabs use the default theme. This helps me feel at home when I'm writing code across multiple languages at the same time. <strong>Update:</strong> A day or so later I actually got rid of this extension. I think it's an awesome extension and works quite well and if you want to have a more familiar interface by all means use it. I'm trying to go as stock as possible to start with though, and I want to be able to see what my customers are going to see when they fire up the tool and use it. I'll definitely remember this one for the future and will likely add it back in not too far down the road.</p>
<p><strong>Zoom Bar</strong><br />It's the small things in life that are important. I like having a little icon on the status bar at the bottom of the screen to reset the zoom or select a custom zoom level. This is a minor one that I added because of unfamiliar behavior with the scroll to zoom feature. Not sure if it will stay with me long term or not. The one time I used it may be the only time. I'll reevaluate in a week or so. <strong>Update:</strong> I still have the extension enabled, but I haven't really gotten any use out of it since I found the setting to enable Ctrl + scroll to change the zoom.</p>
<p><strong>SQL Server (mssql)</strong><br />I'm to the point in my development environment configuration that I need to start doing some SQL work. Where else do I turn but the SQL Server extension. This experience will follow me in some ways over to Azure Data Studio, but for the moment I'm going to stick around in VS Code and kick the tires on this extension to see where it takes me.</p>
<h2 id="heading-settings">Settings</h2>
<p>All the user defined settings are stored in a file called settings.json that you can pull up and easily edit. Alternatively, you can edit the settings through the GUI. This can be edited by pressing Ctrl + Shift + P then typing in Preferences: Open Settings (JSON). If it doesn't come up then you'll need to navigate to the folder where that is stored and open the file.</p>
<p>C:\Users\UserNameHere\AppData\Roaming\Code\User\settings.json</p>
<pre><code>{
    <span class="hljs-string">"editor.mouseWheelZoom"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-string">"workbench.colorTheme"</span>: <span class="hljs-string">"Default Light+"</span>,
    <span class="hljs-string">"powershell.integratedConsole.focusConsoleOnExecute"</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-string">"terminal.integrated.shell.windows"</span>: <span class="hljs-string">"C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"</span>,
    <span class="hljs-string">"window.menuBarVisibility"</span>: <span class="hljs-string">"default"</span>,
    <span class="hljs-string">"workbench.statusBar.visible"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-string">"workbench.activityBar.visible"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-string">"editor.minimap.enabled"</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-string">"window.zoomLevel"</span>: <span class="hljs-number">0</span>
}
</code></pre><h2 id="heading-shortcut-keys">Shortcut Keys</h2>
<p>Keyboard shortcuts are stored in a file similar to the settings.</p>
<p>C:\Users\UserNameHere\AppData\Roaming\Code\User\keybindings.json</p>
<p><strong>Ctrl + Shift + P</strong>: Show all command</p>
<p><strong>Ctrl + P</strong>: Go to file</p>
<p><strong>Ctrl + Alt + Shift + Up/Down Arrow</strong>: Select and insert the same thing on multiple lines at the same time. Big time saver. Interestingly enough, to use the mouse you have to omit the CTRL key. It's ALT + Shift + Mouse Click.</p>
<p><strong>Ctrl + J</strong>: Hides the lower panel.</p>
<p><strong>Ctrl + K M:</strong> Change language on current tab. (Ctrl + K, release all keys, then press M)</p>
<p><strong>F8</strong>: Run currently selected code (On PowerShell after the extension is installed)</p>
<p><strong>Ctrl + B</strong>: Show or hide the sidebar.</p>
]]></content:encoded></item><item><title><![CDATA[Building an Azure Sandbox]]></title><description><![CDATA[It's that time of the year again. No, not fall, although I do love the weather change that's around the corner. It's time for me to rebuild my Azure environment!
Each year I try to wipe out as much of my Azure environment and rebuild it as I possibly...]]></description><link>https://test.bradleyschacht.com/building-an-azure-sandbox</link><guid isPermaLink="true">https://test.bradleyschacht.com/building-an-azure-sandbox</guid><dc:creator><![CDATA[Bradley Schacht]]></dc:creator><pubDate>Wed, 06 Nov 2019 00:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1716516409920/q_IcUXJVN.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It's that time of the year again. No, not fall, although I do love the weather change that's around the corner. It's time for me to rebuild my Azure environment!</p>
<p>Each year I try to wipe out as much of my Azure environment and rebuild it as I possibly can. I like to keep up on product updates that I may have missed, try out new services that I haven't gotten around to just yet, learn new PowerShell commands, and if I'm being honest, organize my environment because I'm a little crazy about things being tidy. Most of the time I do this in July as that's the "slow" time of the year for Microsoft. I'm a little late because there is no real slow time but with Ignite being this week as I get started I thought it would be good timing. Most of the time I remove most of my environment and rebuild. I'll update servers that I want to keep around, I'll clean up my storage account, etc. This year I took a slightly different approach...</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716005516477/b6d028f9-6a88-47fe-beee-b2f1b1405ca2.png" alt /></p>
<p>I just deleted everything. All of it.</p>
<p>Sometimes you just need to get a fresh start. With this fresh start I thought I would maybe try something new too. I am going to see about rebuilding my entire environment using PowerShell and I'm going to post the journey here. I don't have access to everything that my customers use (I'm not an admin on Microsoft's Azure AD, for instance) but I have enough to be able to post about some of the pitfalls that you may face. This will hopefully also serve as a guide for others to build out a sandbox environment for your own learning purposes.</p>
<p>You don't need to do everything the same way I'm going to do it. I may not use best practices everywhere because I either don't have access or I'm just taking shortcuts, so don't take what I'm doing here and apply it to your production environments at all. I may get part of the way down the road and decide I want to change something too.</p>
<p>Check back with me over the next few weeks as I build things out. Topics will include, but will not be limited to, but also may change, but also might shift around:</p>
<ol>
<li>Networking</li>
<li>IaaS Domain<ol>
<li>Domain Controller</li>
<li>Workstation</li>
<li>SQL VM(s)</li>
</ol>
</li>
<li>SQL<ol>
<li>Single Database</li>
<li>Managed Instance</li>
</ol>
</li>
<li>Storage Accounts</li>
<li>Various Data PaaS services for random demos</li>
</ol>
<p>I have decided I'm going to work on getting more familiar with Visual Studio Code through this whole process as well. I use it for an editor but I don't use it for PowerShell at all, and I don't use it to connect to or run SQL. I'm very comfortable in the PowerShell ISE and SQL Server Management Studio but I want to use the newer tools more, so I'm forcing myself to learn them now! Also, with the announcement of Visual Studio Online this week, it's a great time to get started in VS Code or just spin up an environment online and get started!</p>
<p>Regardless of which route you decide to go, if you follow me on this Visual Studio adventure as opposed to the PowerShell/PowerShell ISE route, then you will want to install the PowerShell extension. There is also a function that annoys the mess out of me where if you run a line of code the cursor automatically goes down to the console rather than staying up on your script. So I always have to then click back up top. No thank you. So I added a line to my settings.json file to make sure that doesn't happen.</p>
<pre><code class="lang-bash">    <span class="hljs-string">"powershell.integratedConsole.focusConsoleOnExecute"</span>: <span class="hljs-literal">false</span>
</code></pre>
<p>I think that about covers it for today. Check back soon to see what kind of things I'm building and follow along in your environment!</p>
]]></content:encoded></item></channel></rss>