title: Performance issue using Row Level Security using lookup table
body: <p>I have implemented Row Level Security using on SQL Server 2016. I think I have a failry complex setup, but our security requirement is complex.</p>
  
  <p>This is in the context of a data warehouse. I have basic fact and dimension tables. I applied row level security to one of my dimension table with the following setup:</p>
  
  <blockquote>
    <p><strong>Table 1</strong> : dimDataSources (standard physical table)<br>
    <strong>Table 2</strong> : dimDataSources_Secured (Memory Optimized table)</p>
  </blockquote>
  
  <p>I created a Security Policy on the <code>dimDataSources_Secured</code> (In-Memory) that uses a Natively Compiled function. That function read another Memory Optimized table that contains lookup values and Active Directory Groups that can read the record.
  The function use the <code>is_member()</code> function to return 1 for all records that are allowed for my groups.</p>
  
  <p>So the context seems a bit complex but so far it works.
  But... now I get to use this in jonctions with fact table and we get performance hit. Here, I am not applying row level security directly on the fact table... only on the dimension table.</p>
  
  <p>So my problem is if I run this:</p>
  
  <pre><code>SELECT SUM(Sales) FROM factSales
  </code></pre>
  
  <p>It returns quickly, let's say 2 seconds.</p>
  
  <p>If I run the same query but with a join on the secured table (or view), it will take 5-6 times longer:</p>
  
  <pre><code>SELECT SUM(Sales) FROM factSales f
  INNER JOIN dimDataSources_Secured d ON f.DataSourceKey = d.DataSourceKey
  </code></pre>
  
  <p>This retrieves only the source I have access to based on my AD groups.
  When the execution plan changes, it seems like it retrieves the fact table data quickly, but then will do a nested loop lookup on the In-Memory table to get the allowed records.</p>
  
  <p>Is that behavior caused by the usage of the Filter Predicate functions?
  Anyone had good or bad experiences using Row Level Security?
  Is it mature enough to put in production?
  Is it a good candidate for data warehousing (i.e. processing big volumes of data)?</p>
  
  <p>It is hard to put more details on my actual function and queries without writing a novel. I'm mostly looking for guidelines or alternatives.</p>