<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Matthew Gale</title>
    <description>The latest articles on DEV Community by Matthew Gale (@mdgale).</description>
    <link>https://dev.to/mdgale</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F242915%2F65de6792-dc10-446a-916e-d4c59ed262fc.png</url>
      <title>DEV Community: Matthew Gale</title>
      <link>https://dev.to/mdgale</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mdgale"/>
    <language>en</language>
    <item>
      <title>Application and Webserver Logging in Spring Boot 3.1</title>
      <dc:creator>Matthew Gale</dc:creator>
      <pubDate>Fri, 08 Sep 2023 18:15:35 +0000</pubDate>
      <link>https://dev.to/mdgale/application-and-webserver-logging-in-spring-boot-31-5d69</link>
      <guid>https://dev.to/mdgale/application-and-webserver-logging-in-spring-boot-31-5d69</guid>
      <description>&lt;p&gt;Whenever I start a new Spring Boot project, I have to relearn how logging works to configure it. After so many years and new versions of frameworks, I decided to go deep and break down logging in Spring boot in the modern age and tease apart the various logging libraries and configurations to set the record straight.&lt;/p&gt;

&lt;h2&gt;
  
  
  In a run-of-the-mill Spring boot app, you'd like:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Application logs for Spring Boot 3.1 (using the default &lt;code&gt;Logback&lt;/code&gt; via &lt;code&gt;SLF4J&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Webserver access logs (using the default embedded Tomcat v10)&lt;/li&gt;
&lt;li&gt;All logs going to the same sink (locally, that’s STDOUT)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The minimal configuration you need:&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependencies
&lt;/h3&gt;

&lt;p&gt;In your &lt;code&gt;pom.xml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;ch.qos.logback&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;logback-access&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.4.11&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;ch.qos.logback&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;logback-core&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.4.11&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependencies&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  A Configuration File
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;src/main/resources/&lt;/code&gt; create a &lt;code&gt;logback-access.xml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This example is very close to the default pattern from Spring Boot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;appender&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"STDOUT"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ch.qos.logback.core.ConsoleAppender"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;encoder&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"ch.qos.logback.access.PatternLayoutEncoder"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;pattern&amp;gt;&lt;/span&gt;%t{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}  INFO %-5.5(0) --- [%15.15I] %-40.40(org.apache.tomcat) : %requestURL %statusCode&lt;span class="nt"&gt;&amp;lt;/pattern&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/encoder&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/appender&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;appender-ref&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"STDOUT"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  A Bean
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Configuration&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Bean&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;TomcatServletWebServerFactory&lt;/span&gt; &lt;span class="nf"&gt;tomcatServletWebServerFactory&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;TomcatServletWebServerFactory&lt;/span&gt; &lt;span class="n"&gt;tomcatServletWebServerFactory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TomcatServletWebServerFactory&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;LogbackValve&lt;/span&gt; &lt;span class="n"&gt;logbackValve&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LogbackValve&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;logbackValve&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setFilename&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"logback-access.xml"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;tomcatServletWebServerFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addContextValves&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logbackValve&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;tomcatServletWebServerFactory&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this together, Tomcat access logs will log alongside your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  But what even is all of this? Why is this so cumbersome?
&lt;/h2&gt;

&lt;p&gt;To refresh, java has a TON of logging frameworks. To name a few popular ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;java.util.logging (aka JUL)&lt;/li&gt;
&lt;li&gt;Log4j&lt;/li&gt;
&lt;li&gt;Logback&lt;/li&gt;
&lt;li&gt;Log4j2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which one you pick is up to you, what’s important here is how Spring Boot detects what you want and uses it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SLF4J&lt;/code&gt; (Simple Logging Facade) is a popular abstraction library over the most used logging frameworks- it allows you (or in this case, Spring) to interact with a facade instead of the underlying logging library, so you can pick whichever logging library appeals to you at no additional development effort.&lt;/p&gt;

&lt;p&gt;However: &lt;code&gt;Log4j2&lt;/code&gt; has diverged from the contract &lt;code&gt;SLF4J&lt;/code&gt; expects, and &lt;a href="https://logging.apache.org/log4j/2.x/log4j-slf4j-impl.html"&gt;without an adapter&lt;/a&gt; &lt;code&gt;SLF4J&lt;/code&gt; can’t service &lt;code&gt;Log4j2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A small detail to mention: the authors of &lt;code&gt;SLF4J&lt;/code&gt; are also the authors of &lt;code&gt;Logback&lt;/code&gt;, and so the usage of them together is often assumed, unless otherwise stated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Logging in Spring
&lt;/h3&gt;

&lt;p&gt;To make configuration easier, Spring has created a library called &lt;code&gt;spring-jcl&lt;/code&gt; (Jakarta Commons Logging) that searches your classpath and attempts to automatically configure your logging based on what it finds. &lt;code&gt;spring-jcl&lt;/code&gt; has a &lt;a href="https://docs.spring.io/spring-framework/reference/core/spring-jcl.html#:~:text=of%20the%20Log4j%202.x%20API%20and%20the%20SLF4J%201.7%20API%20in%20the%20classpath%20and%20uses%20the%20first%20one%20of%20those%20found%20as%20the%20logging%20implementation%2C%20falling%20back%20to%20the%20Java%20platform%E2%80%99s%20core%20logging%20facilities%20(also%20known%20as%20JUL%20or%20java.util.logging)%20if%20neither%20Log4j%202.x%20nor%20SLF4J%20is%20available."&gt;preferred order&lt;/a&gt; to which logging frameworks it will select depending on what it finds, but the Spring Boot starter is set up to use &lt;code&gt;Logback&lt;/code&gt; via &lt;code&gt;SLF4J&lt;/code&gt;. You can use any logger you’d like though, you just have to configure it.&lt;/p&gt;

&lt;p&gt;If you use &lt;a href="https://projectlombok.org/"&gt;lombok&lt;/a&gt;, you can use its &lt;a href="https://projectlombok.org/features/log"&gt;logging annotations&lt;/a&gt; to choose which logger you’d like use in any given class. For example, in the default config for Spring Boot, you can use &lt;code&gt;@Slf4j&lt;/code&gt; to use &lt;code&gt;Logback&lt;/code&gt;. If you’re configured for &lt;code&gt;Log4j&lt;/code&gt; via &lt;code&gt;SLF4J&lt;/code&gt;, you could use &lt;code&gt;@Slf4j&lt;/code&gt; or use &lt;code&gt;@Log4j&lt;/code&gt; if you’d like to use the bare logger.&lt;/p&gt;

&lt;p&gt;As an aside, recall that because &lt;code&gt;SLF4J&lt;/code&gt; and &lt;code&gt;Logback&lt;/code&gt; are often synonymous, there’s no need for a &lt;code&gt;@Logback&lt;/code&gt; helper from &lt;code&gt;lombok&lt;/code&gt;- &lt;code&gt;@Slf4j&lt;/code&gt; would usually use &lt;code&gt;Logback&lt;/code&gt; anyway!&lt;/p&gt;

&lt;h3&gt;
  
  
  Logging in Tomcat
&lt;/h3&gt;

&lt;p&gt;Because we embed Tomcat in our applications now, it’s easy to forget that Tomcat is a web server with a servlet container, so it’s actions and concerns are very different than our application code.&lt;/p&gt;

&lt;p&gt;For example, if you attempt to visit an unknown route (resulting in a 404), that request never makes it to the application container. Tomcat is aware of the known routes, and rejects the request before it makes it to your application. That 404 is recorded in Tomcat’s access logs, which by default go to a file- so if we want access logs alongside our application logs, we need to configure Tomcat to use a different appender, which means informing it about which logging framework we’re using so it can direct its logs there.&lt;/p&gt;

&lt;p&gt;Tomcat is configurable in that during initialization, you can pass it a logging pipeline (a series of &lt;code&gt;org.apache.catalina.Valve&lt;/code&gt; s) to handle your logs, and in our case, direct the flow of logs to an appender we configure and control.&lt;/p&gt;

&lt;p&gt;Sticking with the default &lt;code&gt;Logback&lt;/code&gt; for Spring Boot, a project exists from the &lt;code&gt;Logback&lt;/code&gt; team called &lt;code&gt;ogback-access&lt;/code&gt; that comes with a valve (&lt;code&gt;ch.qos.logback.access.tomcat.LogbackValve&lt;/code&gt;) we can use to direct the log stream. A quirk to be aware of is that while &lt;code&gt;logback-access&lt;/code&gt; might have many classnames identical to ones in &lt;code&gt;logback-core&lt;/code&gt;, their behaviour is different and they are not interchangeable: &lt;code&gt;logback-access&lt;/code&gt; is more HTTP specific. The documentation for &lt;code&gt;logback-access&lt;/code&gt; is &lt;a href="https://logback.qos.ch/access.html#:~:text=%3C/Ref%3E-,Logback%2Daccess%20configuration,-Although%20similar%2C%20the"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>logs</category>
    </item>
    <item>
      <title>We’re not all DBAs: Indexes For Developers</title>
      <dc:creator>Matthew Gale</dc:creator>
      <pubDate>Thu, 24 Oct 2019 16:14:52 +0000</pubDate>
      <link>https://dev.to/mdgale/we-re-not-all-dbas-indexes-for-developers-557f</link>
      <guid>https://dev.to/mdgale/we-re-not-all-dbas-indexes-for-developers-557f</guid>
      <description>&lt;p&gt;We know they speed up queries, but what’s going on under the hood? How do they work?&lt;/p&gt;

&lt;p&gt;An index is a structure (commonly a B-Tree, but not required) that we attach to a table that keeps certain columns of that table organized and in memory. Indexes are a solution to the age old problem that going to disk is slow- by caching data in memory you save yourself time reading a records from disk that will mostly be discarded. It’s more efficient to keep common queryable columns in a searchable in-memory store with a reference to where on disk the rest of that row can be found. Having an indexed column lets you find what you need quickly and go to disk specifically for what you &lt;strong&gt;need&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;There are lots of explanations of B-Trees- &lt;a href="https://use-the-index-luke.com/sql/anatomy/the-tree"&gt;Markus Winand&lt;/a&gt; has a beautiful explanation. I also give a hearty shout out to Markus in general, &lt;a href="https://use-the-index-luke.com"&gt;his site&lt;/a&gt; and &lt;a href="https://sql-performance-explained.com/"&gt;book&lt;/a&gt; are &lt;strong&gt;full&lt;/strong&gt; of great content and his explanations are amazing- highly recommended.&lt;/p&gt;

&lt;p&gt;As a developer needing to work with and manipulate databases constantly, there’s a few useful points on indexes that tend to be forgotten. Let’s consider a few.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An indexed column’s values don’t have to be unique. &lt;strong&gt;Cardinality,&lt;/strong&gt; in database jargon, refers to “how unique” the values in an index are; high cardinality means the underlying values have little repetition. When evaluating a column to decide if we want to put an index on it, high cardinality (low repetition) is good for selectivity, but a column doesn’t need to have perfect cardinality to be a candidate. Indexes are able to handle non-unique values by scanning sequentially through the leaves of the underlying tree. The linkage between tree leaves helps prevent unnecessary operations stemming from jumping around through the internals of the tree, making it less costly to navigate through the entries in the index. Scanning data in this way makes doing an equality check (&lt;code&gt;val = ‘matt’&lt;/code&gt;) with multiple results a more lightweight operation. We can leverage this structure to scan through B-Tree indexes too- things like range scans (&lt;code&gt;val &amp;gt; X and val &amp;lt;= Y&amp;lt;&lt;/code&gt;) and even some regexes (&lt;code&gt;first_name like ‘matt%’&lt;/code&gt;). Careful though- even when you’re reading from an index in a range, there can still be a lot of data to read, making your query slow.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When columns are unique, during creation of an index, we can add the constraint that the index be unique, and that allows the optimizer leverage the uniqueness for lookup performance.   &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Multi-column indexes. Firstly, if you didn’t know you could do this- now you do! The underlying behavior and implementation of these indexes vary by DBMS, but across the board, multi-column indexes are versatile in that they can be used to query across all or a subset of columns in the index. To &lt;strong&gt;greatly&lt;/strong&gt; simplify (this varies by DBMS), you can think of think of a table with 3 columns: col1, col2 and col3. When the multi column index is created, the values of all 3 columns are combined into a three part “value”: col1|col2|col3 and sorted- when a query is done, we traverse the tree by comparing against each “section” of the value one at a time and navigate the tree that way. With this arrangement, by supplying 3 values, we can traverse the tree as quickly as we would with a single column index, but giving us greater selectivity since querying by just one column might yield a ton of data to be returned. I mentioned that multi-column indexes support subsets of columns- queries can make use of a multi-column index if we query by only col1, col1 and col2, or all three- each column we add to the query increases the effectiveness of the index lookup because we are adding selectivity and so, less rows to pull back from disk. In some schema designs, multi-column indexes can be a performance boost because we’re able to eliminate so many rows by being selective in our seeking.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Index only scans. With multi-column indexes, it’s possible that the data you’re looking for are held by an index and, therefore, in memory. With the data so available, there’s no need to go to disk if the index can simply give us the data we need. Say you had a table with columns &lt;code&gt;first_name&lt;/code&gt;, &lt;code&gt;last_name&lt;/code&gt; and &lt;code&gt;age&lt;/code&gt; in an index and you wanted to find the age for people named “Matt Gale”. Your query could look like &lt;code&gt;select age from person where first_name = ‘Matt’ and last_name = ‘Gale’&lt;/code&gt;. In this case there would be no need to go to disk because age is part of the index, so the optimizer just returns &lt;code&gt;age&lt;/code&gt; values directly from the index. This can be a really nice resource saver if you can exploit it.   &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In my experience building applications, Object Relational Mappings (ORMs) tend to grab too many columns during a query and developers don’t give much thought to lookups by more than just a single value and so favour single column indexes as a result. To be able to leverage index only scans, look into lazy loading more of your columns to see if you can squeeze some performance out of your queries.&lt;/p&gt;

&lt;p&gt;Something to always keep in mind when doing any query against a database is &lt;em&gt;how much data will I get back from this query&lt;/em&gt;? Queries can be slow because of lack of proper indexes, but also because the volume of disk accesses required. &lt;/p&gt;

&lt;p&gt;For example, let’s say you have a large table with an index on a boolean column (very low cardinality). If you tried to search for rows matching ‘false’ your time spent doing disk access is going to be &lt;strong&gt;huge&lt;/strong&gt; (you’re returning half the table!) relative to the tiny amount of time spent looking values up in an index. This is an example of a situation where indexing is not what will save you time, you need to be more selective in the rows you want to get back. Indexes are an important part of database performance but they are not the only thing to consider.&lt;/p&gt;

&lt;p&gt;I hope this gives a bit of insight! We don’t all have to be DBAs to write sufficiently fast queries and we shouldn’t need to be. As developers, getting familiar with the core structures of a database is a sufficiently pragmatic way to spot and improve performance. With that, go forth and write fast queries!&lt;/p&gt;

</description>
      <category>sql</category>
      <category>index</category>
      <category>backend</category>
      <category>performance</category>
    </item>
    <item>
      <title>SQL In The Real World: Setting Expectations For Your First Job</title>
      <dc:creator>Matthew Gale</dc:creator>
      <pubDate>Fri, 11 Oct 2019 15:48:26 +0000</pubDate>
      <link>https://dev.to/mdgale/sql-in-the-real-world-setting-expectations-for-your-first-job-2cp5</link>
      <guid>https://dev.to/mdgale/sql-in-the-real-world-setting-expectations-for-your-first-job-2cp5</guid>
      <description>&lt;p&gt;I’ve noticed an influx of fresh grads from bootcamps and universities who are nervous about SQL “in the real world”.  New developers fear they don’t know or understand SQL well enough to get through an interview, let alone perform well in the job. To a newcomer, SQL feels vast and illogical compared to other programming they’re used to. They know SQL is important, but it isn’t emphasized in coursework or training to a point where they feel confident in being evaluated.&lt;/p&gt;

&lt;p&gt;I understand how you feel and I’m here to help. I’ve interviewed dozens of developers fresh out of school over the years. I’ve worked as an enterprise backend developer for my entire career and I know the profile I want fresh developers coming into my team to have on day one. I want to set some reasonable expectations for you for what you should know walking into your first set of interviews, and your first days on the job.&lt;/p&gt;

&lt;p&gt;No one expects you to know everything. And an entry level interview shouldn’t try blow your mind with all the things that you don’t know. You’ll be evaluated on practical, applicable knowledge. Here are the 4 questions I ask to the juniors who land in my lap with a bit of explanation as to why I value them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Given a sample schema, write a basic SQL query.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Show me you can use a JOIN and a WHERE clause- being able to write a straightforward SQL query using SELECT, FROM, and WHERE to get a look at the data. I typically ask you to join one table to another, using maybe one or more join types- so you should know the differences between them: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;join (aka inner join)&lt;/li&gt;
&lt;li&gt;left join (aka left outer join)&lt;/li&gt;
&lt;li&gt;right join (aka right outer join)&lt;/li&gt;
&lt;li&gt;full join (aka full outer join)&lt;/li&gt;
&lt;li&gt;cross join&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re still joins, there are some great, well travelled articles and diagrams on &lt;a href="https://blog.codinghorror.com/a-visual-explanation-of-sql-joins/"&gt;join types from Jeff Atwood&lt;/a&gt; or this &lt;a href="https://twitter.com/b0rk/status/1177611875535790087"&gt;nice explanation from Julia Evans&lt;/a&gt;, read up on them and practise a few problems on &lt;a href="https://www.hackerrank.com/domains/sql"&gt;HackerRank&lt;/a&gt; and &lt;a href="https://leetcode.com/problemset/all/?search=sql"&gt;LeetCode&lt;/a&gt;. You want to be at a point where if you saw that a left join was something you wanted to do, you’d understand the syntax and the usage to make that happen.&lt;/p&gt;

&lt;p&gt;Bonus points! What are indexes and how do they work? I want to be clear that this is only bonus. Not knowing about indexes is not something I would ever eliminate a candidate for, but they will definitely win you respect in an interview if you understand their role and can apply them. Mentioning query performance and index usage when formulating a queries in interview questions definitely shows you’re thinking of one of the biggest practical aspects of databases&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Model me a “many to many” relationship.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I would never tell you to jump through a hoop if I wasn’t so positive you’d be asked this question. It’s a popular question for a reason- it demonstrates to me that you can think relationally, and have a little bit of design sense when it comes to crafting and making changes to a DB schema. This is a very common problem, and there is a common solution all developers working with a relational database should know.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the difference between &lt;code&gt;= NULL&lt;/code&gt; and &lt;code&gt;IS NULL&lt;/code&gt;?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is one of those general usability aspects of SQL that all developers should have in their tool belt. Now that I’ve drawn your attention to it, learn it and have it at your disposal to know that it needs to be applied.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What’s a prepared statement and why do we use them?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I don’t expect an extremely technical answer here in terms of what happens at the database level, but one term I would expect to hear from you is “SQL injection”. It’s important to know that we shouldn’t just do string substitution for parameters in queries or bare string queries against a database- we need to protect ourselves from malicious input.&lt;/p&gt;

&lt;p&gt;That’s it! Hopefully you feel a little less daunted.&lt;/p&gt;

&lt;p&gt;All-in-all, don’t live and die by the coding interview prep sites- you can spend weeks on HackerRank and LeetCode going through problems of increasing difficulty and it can turn into a rabbit hole of “how much is enough”. Practising will make you stronger and I advise it, but also remember that in the workplace, schemas are not clean and contrived like they are on these practise sites- they’re flawed and imperfect. Designing and dealing with these beasts will be its own adventure that you won’t need to tackle under time pressure or with another developer evaluating you over your shoulder.&lt;/p&gt;

&lt;p&gt;My advice is to get comfortable with the basics- when you have these, as an interviewer and coworker, I can work with you through most problems and we can have a discussion about them, which helps me understand you and vice versa to get to the end goal- you shipping code.&lt;/p&gt;

</description>
      <category>sql</category>
      <category>beginners</category>
      <category>database</category>
    </item>
  </channel>
</rss>
