SQL Database Azure
SQL Database Azure
SQL DB Documentation
Overview
About SQL DB
Quickstart
Create DB - Portal
Create DB - Azure CLI
Create DB - PowerShell
Manage
SSMS
VS Code
Connect
.NET
PHP
Node.js
Java
Python
Ruby
Tutorials
Design a database
Migrate a database
Samples
Azure CLI
PowerShell
Concepts
DBs and servers
Databases
Servers
Elastic pools
Resources
Service tiers
DTUs and eDTUs
DTU benchmark
Limits
PaaS or IaaS
Features
Tools
Partition data
Sharded databases
Elastic client library
Shard maps
Query routing
Manage credentials
Shard querying
Elastic tools
Move sharded data
Elastic tools FAQ
Manage multiple DBs
Elastic queries
Horizontal data
Vertical data
Transactions
Elastic jobs
Security
Overview
Access control
Firewall rules
Azure AD
Logins and users
Multi-factor auth
Auditing
Auditing and TDS
Threat detection
TDE with SQL DB
Always encrypted
Data masking
Business continuity
Overview
Database backups
Backup retention
Database recovery
Geo-replication
Logins
App design
Elastic pools
App upgrades
Development
Overview
Connectivity
App design - SaaS
Security - SaaS
Ports - ADO.NET
Authenticate App
Error messages
Dapper
JSON data
In-memory
Temporal tables
Retention policies
Database migration
SQL Server DB
T-SQL changes
Data movement
Copy a DB
Import a DB
Export a DB
Monitor and tune
Single databases
Database advisor
Query insight
Operate query store
DMVs
Perf guidance
Batching
Extended events
Compatibility levels
How-to guides
Manage elastic pools
Portal
PowerShell
Transact-SQL
C
DB Access
SQL Server
Azure AD
Secure data
Azure AD auth
Encrypt - cert store
Encrypt - key vault
Configure masking
Recover single table
Configure vault for backups
Geo-replicate data
Portal
T-SQL - Configure
T-SQL - Failover
Recover - outage
Perform drills
Move data
Load data with BCP
Load data with ADF
Sync data
Connect applications
C and C ++
Excel
Guidance
Issues
Create DB with C
Configure In-Memory
Manage multiple DBs
Create sharded app
Move sharded data
Security configuration
Add a shard
Fix shard map problems
Migrate sharded DB
Create counters
Use entity framework
Upgrade clients
Install elastic job
Create job - Portal
Create job - PowerShell
Create job - Sample app
Uninstall elastic job
Query horizontal data
Query vertical data
Monitor and tune
Use Database Advisor
Use QPI
Evaluate and tune
Create alerts
Monitor in-memory
Extended events - event file
Extended events - ring buffer
Manage
Azure Automation
Azure RemoteApp
SSMS - MFA
Reference
PowerShell
PowerShell (Elastic DB)
Azure CLI 2.0
.NET
Java
Node.js
Python
Ruby
PHP
T-SQL
REST
SQL Server tools
SQL Server Management Studio (SSMS)
SQL Server Data Tools (SSDT)
BCP
SQLCMD
SqlPackage
SQL Database Management Library package
SQL Server drivers
ADO.NET
JDBC
ODBC
Resources
FAQ
Public data sets
Troubleshoot connectivity
Pricing
MSDN forum
Stack Overflow
Videos
Service updates
Architecture guidance
Customer implementations
Sample applications
Tailspin Surveys
Contoso Clinic
Elastic pool telemetry
Elastic pool custom dashboard
SQL Database Documentation
Azure SQL Database is a relational database-as-a service using the Microsoft SQL Server Engine. SQL Database is a high-
performance, reliable, and secure database you can use to build data-driven applications and websites in the programming
language of your choice, without needing to manage infrastructure. Learn how to use SQL Database with our quickstarts, tutorials,
and samples.
Quickstarts
Create a SQL DB using:
Azure Portal
Azure CLI
Azure PowerShell
Tutorials
Build and deploy SQL Database applications.
Design a database
Migrate a database
Samples
Find scripts to manage common tasks.
Azure CLI
Azure PowerShell
Reference
Command- Line
Azure PowerShell
Azure PowerShell (Elastic DB)
Azure CLI 2.0
Languages
.NET
Java
Node.js
Python
Ruby
PHP
T-SQL
REST
REST API Reference
SQL Database is a relational database service in the Microsoft cloud based on the market-leading Microsoft SQL
Server engine and capable of handling mission-critical workloads. SQL Database delivers predictable performance
at multiple service levels, dynamic scalability with no downtime, built-in business continuity, and data protection
— all with near-zero administration. These capabilities allow you to focus on rapid app development and
accelerating your time to market, rather than allocating precious time and resources to managing virtual machines
and infrastructure. Because SQL Database is based on the SQL Server engine, SQL Database supports existing SQL
Server tools, libraries, and APIs. As a result, it is easy for you to develop new solutions, to move your existing SQL
Server solutions, and to extend your existing SQL Server solutions to the Microsoft cloud without having to learn
new skills.
This article is an introduction to SQL Database core concepts and features related to performance, scalability, and
manageability, with links to explore details. See these quick starts to get you started:
Create a SQL database in the Azure portal
Create a SQL database with the Azure CLI
Create a SQL database using PowerShell
For a set of Azure CLI and PowerShell samples, see:
Azure CLI samples for Azure SQL Database
Azure PowerShell samples for Azure SQL Database
See Business Continuity for details about the different business continuity features available for different service
tiers.
Next steps
Now that you've read an introduction to SQL Database and answered the question "What is SQL Database?",
you're ready to:
See the pricing page for single database and elastic pools cost comparisons and calculators.
Learn about elastic pools.
Get started by creating your first database.
Build your first app in C#, Java, Node.js, PHP, Python, or Ruby: Connection libraries for SQL Database and SQL
Server
Create an Azure SQL database in the Azure portal
4/17/2017 • 5 min to read • Edit Online
This quick start tutorial walks through how to create a SQL database in Azure. Azure SQL Database is a
“Database-as-a-Service” offering that enables you to run and scale highly available SQL Server databases in the
cloud. This quick start shows you how to get started by creating a SQL database using the Azure portal.
If you don't have an Azure subscription, create a free account before you begin.
3. Fill out the SQL Database form with the following information, as shown on the preceding image:
Database name: mySampleDatabase
Resource group: myResourceGroup
Source source: Sample (AdventureWorksLT)
IMPORTANT
You must select the sample database on this form because it is used in the remainder of this quick start.
4. Click Server and then fill out the New server form specifying a globally unique server name, provide a
name for the server admin login, and then specify the password of your choice.
IMPORTANT
The server admin login and password that you specify here are required to log in to the server and its databases
later in this quick start. Remember or record this information for later use.
NOTE
SQL Database communicates over port 1433. If you are trying to connect from within a corporate network, outbound
traffic over port 1433 may not be allowed by your network's firewall. If so, you will not be able to connect to your Azure
SQL Database server unless your IT department opens port 1433.
1. After the deployment completes, click SQL databases from the left-hand menu and then click
mySampleDatabase on the SQL databases page. The overview page for your database opens, showing
you the fully qualified server name (such as mynewserver20170411.database.windows.net) and
provides options for further configuration.
IMPORTANT
You will need this fully qualified server name to connect to your server and its databases in subsequent quick
starts.
2. Click Set server firewall on the toolbar as shown in the previous image. The Firewall settings page for
the SQL Database server opens.
3. Click Add client IP on the toolbar to add your current IP address to a new firewall rule. A firewall rule
can open port 1433 for a single IP address or a range of IP addresses.
4. Click Save. A server-level firewall rule is created for your current IP address opening port 1433 on the
logical server.
IMPORTANT
By default, access through the SQL Database firewall is enabled for all Azure services. Click OFF on this page to disable for
all Azure services.
2. Click Query editor (preview), click the Preview terms checkbox, and then click OK. The Query editor
page opens.
3. Click Login and then, when prompted, select SQL server authentication and then provide the server
admin login and password that you created earlier.
6. Click Run and then review the query results in the Results pane.
Clean up resources
Other quick starts in this collection build upon this quick start. If you plan to continue on to work with
subsequent quick starts, do not clean up the resources created in this quick start. If you do not plan to continue,
use the following steps to delete all resources created by this quick start in the Azure portal.
1. From the left-hand menu in the Azure portal, click Resource groups and then click myResourceGroup.
2. On your resource group page, click Delete, type myResourceGroup in the text box, and then click Delete.
Next steps
To connect and query using SQL Server Management Studio, see Connect and query with SSMS
To connect and query using Visual Studio Code, see Connect and query with Visual Studio Code.
To connect and query using .NET, see Connect and query with .NET.
To connect and query using PHP, see Connect and query with PHP.
To connect and query using Node.js, see Connect and query with Node.js.
To connect and query using Java, see Connect and query with Java.
To connect and query using Python, see Connect and query with Python.
To connect and query using Ruby, see Connect and query with Ruby.
Create a single Azure SQL database using the Azure
CLI
4/18/2017 • 3 min to read • Edit Online
The Azure CLI is used to create and manage Azure resources from the command line or in scripts. This guide
details using the Azure CLI to deploy an Azure SQL database in an Azure resource group in an Azure SQL
Database logical server.
To complete this quick start, make sure you have installed the latest Azure CLI 2.0.
If you don't have an Azure subscription, create a free account before you begin.
Log in to Azure
Log in to your Azure subscription with the az login command and follow the on-screen directions.
az login
Define variables
Define variables for use in the scripts in this quick start.
NOTE
SQL Database communicates over port 1433. If you are trying to connect from within a corporate network, outbound traffic
over port 1433 may not be allowed by your network's firewall. If so, you will not be able to connect to your Azure SQL
Database server unless your IT department opens port 1433.
Clean up resources
Other quick starts in this collection build upon this quick start. If you plan to continue on to work with subsequent
quick starts or with the tutorials, do not clean up the resources created in this quick start. If you do not plan to
continue, use the following command to delete all resources created by this quick start.
Next steps
To connect and query using SQL Server Management Studio, see Connect and query with SSMS
To connect and query using Visual Studio Code, see Connect and query with Visual Studio Code.
To connect and query using .NET, see Connect and query with .NET.
To connect and query using PHP, see Connect and query with PHP.
To connect and query using Node.js, see Connect and query with Node.js.
To connect and query using Java, see Connect and query with Java.
To connect and query using Python, see Connect and query with Python.
To connect and query using Ruby, see Connect and query with Ruby.
Create a single Azure SQL database using PowerShell
4/18/2017 • 3 min to read • Edit Online
PowerShell is used to create and manage Azure resources from the command line or in scripts. This guide details
using PowerShell to deploy an Azure SQL database in an Azure resource group in an Azure SQL Database logical
server.
To complete this tutorial, make sure you have installed the latest Azure PowerShell.
If you don't have an Azure subscription, create a free account before you begin.
Log in to Azure
Log in to your Azure subscription using the Add-AzureRmAccount command and follow the on-screen directions.
Add-AzureRmAccount
Create variables
Define variables for use in the scripts in this quick start.
NOTE
SQL Database communicates over port 1433. If you are trying to connect from within a corporate network, outbound traffic
over port 1433 may not be allowed by your network's firewall. If so, you will not be able to connect to your Azure SQL
Database server unless your IT department opens port 1433.
Clean up resources
Other quick starts in this collection build upon this quick start. If you plan to continue on to work with subsequent
quick starts or with the tutorials, do not clean up the resources created in this quick start. If you do not plan to
continue, use the following command to delete all resources created by this quick start.
Next steps
To connect and query using SQL Server Management Studio, see Connect and query with SSMS
To connect and query using Visual Studio Code, see Connect and query with Visual Studio Code.
To connect and query using .NET, see Connect and query with .NET.
To connect and query using PHP, see Connect and query with PHP.
To connect and query using Node.js, see Connect and query with Node.js.
To connect and query using Java, see Connect and query with Java.
To connect and query using Python, see Connect and query with Python.
To connect and query using Ruby, see Connect and query with Ruby.
Azure SQL Database: Use SQL Server Management
Studio to connect and query data
4/19/2017 • 3 min to read • Edit Online
SQL Server Management Studio (SSMS) is a management tool used to create and manage SQL Server resources
from the user interface or in scripts. This quick start demonstrates how to use SSMS to connect to an Azure SQL
database, and then use Transact-SQL statements to query, insert, update, and delete data in the database.
This quick start uses as its starting point the resources created in one of these quick starts:
Create DB - Portal
Create DB - CLI
Before you start, make sure you have installed the newest version of SSMS.
4. If you have forgotten the login information for your Azure SQL Database server, navigate to the SQL
Database server page to view the server admin name and, if necessary, reset the password.
IMPORTANT
An Azure SQL Database logical server listens on port 1433. If you are attempting to connect to an Azure SQL Database
logical server from within a corporate firewall, this port must be open in the corporate firewall for you to successfully
connect.
3. Click Options in the Connect to server dialog box. In the Connect to database section, enter
mySampleDatabase to connect to this database.
Query data
Use the following code to query for the top 20 products by category using the SELECT Transact-SQL statement.
1. In Object Explorer, right-click mySampleDatabase and click New Query. A blank query window opens that
is connected to your database.
2. In the query window, enter the following query:
3. On the toolbar, click Execute to retrieve data from the Product and ProductCategory tables.
Insert data
Use the following code to insert a new product into the SalesLT.Product table using the INSERT Transact-SQL
statement.
1. In the query window, replace the previous query with the following query:
2. On the toolbar, click Execute to insert a new row in the Product table.
Update data
Use the following code to update the new product that you previously added using the UPDATE Transact-SQL
statement.
1. In the query window, replace the previous query with the following query:
UPDATE [SalesLT].[Product]
SET [ListPrice] = 125
WHERE Name = 'myNewProduct';
2. On the toolbar, click Execute to update the specified row in the Product table.
Delete data
Use the following code to delete the new product that you previously added using the DELETE Transact-SQL
statement.
1. In the query window, replace the previous query with the following query:
2. On the toolbar, click Execute to delete the specified row in the Product table.
Next steps
For information about SSMS, see Use SQL Server Management Studio.
To connect and query using Visual Studio Code, see Connect and query with Visual Studio Code.
To connect and query using .NET, see Connect and query with .NET.
To connect and query using PHP, see Connect and query with PHP.
To connect and query using Node.js, see Connect and query with Node.js.
To connect and query using Java, see Connect and query with Java.
To connect and query using Python, see Connect and query with Python.
To connect and query using Ruby, see Connect and query with Ruby.
Azure SQL Database: Use Visual Studio Code to
connect and query data
4/19/2017 • 4 min to read • Edit Online
Visual Studio Code is a graphical code editor for Linux, macOS, and Windows that supports extensions, including
the mssql extension for querying Microsoft SQL Server, Azure SQL Database, and SQL Data Warehouse. This
quick start demonstrates how to use Visual Studio Code to connect to an Azure SQL database, and then use
Transact-SQL statements to query, insert, update, and delete data in the database.
This quick start uses as its starting point the resources created in one of these quick starts:
Create DB - Portal
Create DB - CLI
Before you start, make sure you have installed the newest version of Visual Studio Code and loaded the mssql
extension. For installation guidance for the mssql extension, see Install VS Code and see mssql for Visual Studio
Code.
Configure VS Code
Mac OS
For macOS, you need to install OpenSSL which is a prerequiste for DotNet Core that mssql extention uses. Open
your terminal and enter the following commands to install brew and OpenSSL.
Linux (Ubuntu)
No special configuration needed.
Windows
No special configuration needed.
IMPORTANT
Before continuing, make sure that you have your server, database, and login information ready. Once you begin entering
the connection profile information, if you change your focus from Visual Studio Code, you have to restart creating the
connection profile.
SETTING DESCRIPTION
Password (SQL Login) Enter the password for your server admin account
[Optional] Enter a name for this profile Enter a connection profile name, such as
mySampleDatabase.
5. Press the ESC key to close the info message that informs you that the profile is created and connected.
6. Verify your connection in the status bar.
Query data
Use the following code to query for the top 20 products by category using the SELECT Transact-SQL statement.
1. In the Editor window, enter the following query in the empty query window:
Insert data
Use the following code to insert a new product into the SalesLT.Product table using the INSERT Transact-SQL
statement.
1. In the Editor window, delete the previous query and enter the following query:
Update data
Use the following code to update the new product that you previously added using the UPDATE Transact-SQL
statement.
1. In the Editor window, delete the previous query and enter the following query:
UPDATE [SalesLT].[Product]
SET [ListPrice] = 125
WHERE Name = 'myNewProduct';
Next steps
To connect and query using SQL Server Management Studio, see Connect and query with SSMS
To connect and query using .NET, see Connect and query with .NET.
To connect and query using PHP, see Connect and query with PHP.
To connect and query using Node.js, see Connect and query with Node.js.
To connect and query using Java, see Connect and query with Java.
To connect and query using Python, see Connect and query with Python.
To connect and query using Ruby, see Connect and query with Ruby.
Azure SQL Database: Use .NET (C#) to connect and
query data
4/20/2017 • 5 min to read • Edit Online
This quick start demonstrates how to use C# and ADO.NET to connect to an Azure SQL database, and then use
Transact-SQL statements to query, insert, update, and delete data in the database from the Windows, Mac OS,
and Ubuntu Linux platforms.
This quick start uses as its starting point the resources created in one of these quick starts:
Create DB - Portal
Create DB - CLI
Install .NET
The steps in this section assume that you are familar with developing using .NET and are new to working with
Azure SQL Database. If you are new to developing with .NET, go the Build an app using SQL Server and select C#
and then select your operating system.
Windows .NET framework and .NET core
Visual Studio 2017 Community is a fully-featured, extensible, free IDE for creating modern applications for
Android, iOS, Windows, as well as web & database applications and cloud services. You can install either the full
.NET framework or just .NET core. The code snippets in the quick start work with either. If you already have Visual
Studio installed on your machine, skip the next few steps.
1. Download the installer.
2. Run the installer and follow the installation prompts to complete the installation.
Mac OS
Open your terminal and navigate to a directory where you plan on creating your .NET Core project. Enter the
following commands to install brew, OpenSSL, and .NET Core.
Install .NET Core on macOS. Download the official installer. This installer will install the tools and put them on
your PATH so you can run dotnet from the Console
Linux (Ubuntu)
Open your terminal and navigate to a directory where you plan on creating your .NET Core project. Enter the
following commands to install .NET Core.
sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/ xenial main" >
/etc/apt/sources.list.d/dotnetdev.list'
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 417A0893
sudo apt-get update
sudo apt-get install dotnet-dev-1.0.1
4. If you have forgotten the login information for your Azure SQL Database server, navigate to the SQL
Database server page to view the server admin name and, if necessary, reset the password.
5. Click Show database connection strings.
6. Review the completeADO.NET connection string.
Add System.Data.SqlClient
When using .NET core, add System.Data.SqlClient to your project's csproj file as a dependency.
<ItemGroup>
<PackageReference Include="System.Data.SqlClient" Version="4.3.0" />
</ItemGroup>
Select data
1. In your development environment, open a blank code file.
2. Add using System.Data.SqlClient to your code file (System.Data.SqlClient namespace).
3. Use the following code to query for the top 20 products by category with the SqlCommand.ExecuteReader
command with a SELECT Transact-SQL statement. Add the appropriate values for your server, database,
user and password.
using System;
using System.Data;
using System.Data.SqlClient;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
try
{
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder.DataSource = "your_server.database.windows.net";
builder.UserID = "your_user";
builder.Password = "your_password";
builder.InitialCatalog = "your_database";
connection.Open();
StringBuilder sb = new StringBuilder();
sb.Append("SELECT TOP 20 pc.Name as CategoryName, p.name as ProductName ");
sb.Append("FROM [SalesLT].[ProductCategory] pc ");
sb.Append("JOIN [SalesLT].[Product] p ");
sb.Append("ON pc.productcategoryid = p.productcategoryid;");
String sql = sb.ToString();
Insert data
Use the following code to insert a new product into the SalesLT.Product table using the
SqlCommand.ExecuteNonQuery with an INSERT Transact-SQL statement. Add the appropriate values for your
server, database, user and password.
using System;
using System.Data;
using System.Data.SqlClient;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
try
{
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder.DataSource = "your_server.database.windows.net";
builder.UserID = "your_user";
builder.Password = "your_password";
builder.InitialCatalog = "your_database";
connection.Open();
StringBuilder sb = new StringBuilder();
sb.Append("INSERT INTO [SalesLT].[Product] ([Name], [ProductNumber], [Color], [StandardCost], [ListPrice], [SellStartDate]) ");
sb.Append("VALUES (@Name, @ProductNumber, @Color, @StandardCost, @ListPrice, @SellStartDate);");
String sql = sb.ToString();
using (SqlCommand command = new SqlCommand(sql, connection))
{
command.Parameters.AddWithValue("@Name", "BrandNewProduct");
command.Parameters.AddWithValue("@ProductNumber", "200989");
command.Parameters.AddWithValue("@Color", "Blue");
command.Parameters.AddWithValue("@StandardCost", 75);
command.Parameters.AddWithValue("@ListPrice", 80);
command.Parameters.AddWithValue("@SellStartDate", "7/1/2016");
int rowsAffected = command.ExecuteNonQuery();
Console.WriteLine(rowsAffected + " row(s) inserted");
}
}
}
catch (SqlException e)
{
Console.WriteLine(e.ToString());
}
}
}
}
Update data
Use the following code to update the new product that you previously added using the
SqlCommand.ExecuteNonQuery with an UPDATE Transact-SQL statement. Add the appropriate values for your
server, database, user and password.
using System;
using System.Data;
using System.Data.SqlClient;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
try
{
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder.DataSource = "your_server.database.windows.net";
builder.UserID = "your_user";
builder.Password = "your_password";
builder.InitialCatalog = "your_database";
connection.Open();
StringBuilder sb = new StringBuilder();
sb.Append("UPDATE [SalesLT].[Product] SET ListPrice = @ListPrice WHERE Name = @Name;");
String sql = sb.ToString();
using (SqlCommand command = new SqlCommand(sql, connection))
{
command.Parameters.AddWithValue("@Name", "BrandNewProduct");
command.Parameters.AddWithValue("@ListPrice", 500);
int rowsAffected = command.ExecuteNonQuery();
Console.WriteLine(rowsAffected + " row(s) updated");
}
}
}
catch (SqlException e)
{
Console.WriteLine(e.ToString());
}
}
}
}
Delete data
Use the following code to delete the new product that you previously added using the
SqlCommand.ExecuteNonQuery with a DELETE Transact-SQL statement . Add the appropriate values for your
server, database, user and password.
using System;
using System.Data;
using System.Data.SqlClient;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
try
{
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder.DataSource = "your_server.database.windows.net";
builder.UserID = "your_user";
builder.Password = "your_password";
builder.InitialCatalog = "your_database";
connection.Open();
StringBuilder sb = new StringBuilder();
sb.Append("DELETE FROM SalesLT.Product WHERE Name = @Name;");
String sql = sb.ToString();
using (SqlCommand command = new SqlCommand(sql, connection))
{
command.Parameters.AddWithValue("@Name", "BrandNewProduct");
int rowsAffected = command.ExecuteNonQuery();
Console.WriteLine(rowsAffected + " row(s) deleted");
}
}
}
catch (SqlException e)
{
Console.WriteLine(e.ToString());
}
}
}
}
Next steps
For .NET documentation, see .NET documentation.
To connect and query using SQL Server Management Studio, see Connect and query with SSMS
To connect and query using Visual Studio, see Connect and query with Visual Studio Code.
To connect and query using PHP, see Connect and query with PHP.
To connect and query using Node.js, see Connect and query with Node.js.
To connect and query using Java, see Connect and query with Java.
To connect and query using Python, see Connect and query with Python.
To connect and query using Ruby, see Connect and query with Ruby.
Azure SQL Database: Use PHP to connect and query
data
4/20/2017 • 5 min to read • Edit Online
This quick start demonstrates how to use PHP to connect to an Azure SQL database, and then use Transact-SQL
statements to query, insert, update, and delete data in the database from Mac OS, Ubuntu Linux, and Windows
platforms.
This quick start uses as its starting point the resources created in one of these quick starts:
Create DB - Portal
Create DB - CLI
Linux (Ubuntu)
Enter the following commands to install the Microsoft ODBC Driver for Linux and the Microsoft PHP Drivers
for SQL Server.
sudo su
curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list > /etc/apt/sources.list.d/mssql.list
exit
sudo apt-get update
sudo apt-get install msodbcsql mssql-tools unixodbc-dev gcc g++ php-dev
sudo pecl install sqlsrv pdo_sqlsrv
sudo echo "extension= pdo_sqlsrv.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`
sudo echo "extension= sqlsrv.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`
Windows
Install PHP 7.1.1 (x64) from WebPlatform Installer
Install the Microsoft ODBC Driver 13.1.
Download the non-thread safe dll's for the Microsoft PHP Driver for SQL Server and place the binaries in the
PHP\v7.x\ext folder.
Next edit your php.ini (C:\Program Files\PHP\v7.1\php.ini) file by adding the reference to the dll. For
example:
extension=php_sqlsrv.dll
extension=php_pdo_sqlsrv.dll
At this point you should have the dll's registered with PHP.
4. If you have forgotten the login information for your Azure SQL Database server, navigate to the SQL
Database server page to view the server admin name and, if necessary, reset the password.
Select data
Use the following code to query for the top 20 products by category using the sqlsrv_query() function with a
SELECT Transact-SQL statement. The sqlsrv_query function is used to retrieve a result set from a query against a
SQL database. This function accepts a query and returns a result set that can be iterated over with the use of
sqlsrv_fetch_array(). Replace the server, database, username, and password parameters with the values that you
specified when you created the database with the AdventureWorksLT sample data.
<?php
$serverName = "your_server.database.windows.net";
$connectionOptions = array(
"Database" => "your_database",
"Uid" => "your_username",
"PWD" => "your_password"
);
//Establishes the connection
$conn = sqlsrv_connect($serverName, $connectionOptions);
$tsql= "SELECT TOP 20 pc.Name as CategoryName, p.name as ProductName
FROM [SalesLT].[ProductCategory] pc
JOIN [SalesLT].[Product] p
ON pc.productcategoryid = p.productcategoryid";
$getResults= sqlsrv_query($conn, $tsql);
echo ("Reading data from table" . PHP_EOL);
if ($getResults == FALSE)
echo (sqlsrv_errors());
while ($row = sqlsrv_fetch_array($getResults, SQLSRV_FETCH_ASSOC)) {
echo ($row['CategoryName'] . " " . $row['ProductName'] . PHP_EOL);
}
sqlsrv_free_stmt($getResults);
?>
Insert data
Use the following code to insert a new product into the SalesLT.Product table using the sqlsrv_query() function
and the INSERT Transact-SQL statement. Replace the server, database, username, and password parameters with
the values that you specified when you created the database with the AdventureWorksLT sample data.
<?php
$serverName = "your_server.database.windows.net";
$connectionOptions = array(
"Database" => "your_database",
"Uid" => "your_username",
"PWD" => "your_password"
);
//Establishes the connection
$conn = sqlsrv_connect($serverName, $connectionOptions);
$tsql= "INSERT INTO SalesLT.Product (Name, ProductNumber, Color, StandardCost, ListPrice, SellStartDate) VALUES (?,?,?,?,?,?);";
$params = array("BrandNewProduct", "200989", "Blue", 75, 80, "7/1/2016");
$getResults= sqlsrv_query($conn, $tsql, $params);
if ($getResults == FALSE)
echo print_r(sqlsrv_errors(), true);
else{
$rowsAffected = sqlsrv_rows_affected($getResults);
echo ($rowsAffected. " row(s) inserted" . PHP_EOL);
sqlsrv_free_stmt($getResults);
}
?>
Update data
Use the following code to update data in your Azure SQL database using the sqlsrv_query() function and the
UPDATE Transact-SQL statement. Replace the server, database, username, and password parameters with the
values that you specified when you created the database with the AdventureWorksLT sample data.
<?php
$serverName = "your_server.database.windows.net";
$connectionOptions = array(
"Database" => "your_database",
"Uid" => "your_username",
"PWD" => "your_password"
);
//Establishes the connection
$conn = sqlsrv_connect($serverName, $connectionOptions);
$tsql= "UPDATE SalesLT.Product SET ListPrice =? WHERE Name = ?";
$params = array(50,"BrandNewProduct");
$getResults= sqlsrv_query($conn, $tsql, $params);
if ($getResults == FALSE)
echo print_r(sqlsrv_errors(), true);
else{
$rowsAffected = sqlsrv_rows_affected($getResults);
echo ($rowsAffected. " row(s) updated" . PHP_EOL);
sqlsrv_free_stmt($getResults);
}
?>
Delete data
Use the following code to delete the new product that you previously added using the sqlsrv_query() function
and the DELETE Transact-SQL statement. Replace the server, database, username, and password parameters with
the values that you specified when you created the database with the AdventureWorksLT sample data.
<?php
$serverName = "your_server.database.windows.net";
$connectionOptions = array(
"Database" => "your_database",
"Uid" => "your_username",
"PWD" => "your_password"
);
//Establishes the connection
$conn = sqlsrv_connect($serverName, $connectionOptions);
$tsql= "DELETE FROM SalesLT.Product WHERE Name = ?";
$params = array("BrandNewProduct");
$getResults= sqlsrv_query($conn, $tsql, $params);
if ($getResults == FALSE)
echo print_r(sqlsrv_errors(), true);
else{
$rowsAffected = sqlsrv_rows_affected($getResults);
echo ($rowsAffected. " row(s) deleted" . PHP_EOL);
sqlsrv_free_stmt($getResults);
}
Next steps
More information on the Microsoft PHP Driver for SQL Server.
File issues/ask questions.
To connect and query using SQL Server Management Studio, see Connect and query with SSMS
To connect and query using Visual Studio, see Connect and query with Visual Studio Code.
To connect and query using .NET, see Connect and query with .NET.
To connect and query using Node.js, see Connect and query with Node.js.
To connect and query using Java, see Connect and query with Java.
To connect and query using Python, see Connect and query with Python.
To connect and query using Ruby, see Connect and query with Ruby.
Azure SQL Database: Use Node.js to connect and
query data
4/20/2017 • 5 min to read • Edit Online
This quick start demonstrates how to connect to an Azure SQL database using Node.js and then use Transact-
SQL statements to query, insert, update, and delete data in the database from Windows, Ubuntu Linux, and Mac
platforms.
This quick start uses as its starting point the resources created in any of these guides:
Create DB - Portal
Create DB - CLI
Install Node.js
The steps in this section assume that you are familar with developing using Node.js and are new to working with
Azure SQL Database. If you are new to developing with Node.js, go the Build an app using SQL Server and select
Node.js and then select your operating system.
Mac OS
Enter the following commands to install brew, an easy-to-use package manager for Mac OS X and Node.js.
Linux (Ubuntu)
Enter the following commands to install Node.js and npm the package manager for Node.js.
Windows
Visit the Node.js downloads page and select your desired Windows installer option.
4. If you have forgotten the login information for your Azure SQL Database server, navigate to the SQL
Database server page to view the server admin name and, if necessary, reset the password.
Select data
Use the following code to query your Azure SQL database for the top 20 products by category. First import the
driver Connect and Request classes from the tedious driver library. Afterwards create the configuration object
and replace the username, password, server and database variables with the values that you specified when
you created the database with the AdventureWorksLT sample data. Create a Connection object using the specified
config object. After that, define callback for the connect event of the connection object to execute the
queryDatabase() function.
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
function queryDatabase(){
console.log('Reading rows from the Table...');
request.on('row', function(columns) {
columns.forEach(function(column) {
console.log("%s\t%s", column.metadata.colName, column.value);
});
});
connection.execSql(request);
}
function insertIntoDatabase(){
console.log("Inserting a brand new product into database...");
request = new Request(
"INSERT INTO SalesLT.Product (Name, ProductNumber, Color, StandardCost, ListPrice, SellStartDate) OUTPUT INSERTED.ProductID
VALUES ('BrandNewProduct', '200989', 'Blue', 75, 80, '7/1/2016')",
function(err, rowCount, rows) {
console.log(rowCount + ' row(s) inserted');
}
);
connection.execSql(request);
}
function updateInDatabase(){
console.log("Updating the price of the brand new product in database...");
request = new Request(
"UPDATE SalesLT.Product SET ListPrice = 50 WHERE Name = 'BrandNewProduct'",
function(err, rowCount, rows) {
console.log(rowCount + ' row(s) updated');
}
);
connection.execSql(request);
}
function deleteFromDatabase(){
console.log("Deleting the brand new product in database...");
request = new Request(
"DELETE FROM SalesLT.Product WHERE Name = 'BrandNewProduct'",
function(err, rowCount, rows) {
console.log(rowCount + ' row(s) returned');
}
);
connection.execSql(request);
}
Next Steps
More information on the Microsoft Node.js Driver for SQL Server
To connect and query using SQL Server Management Studio, see Connect and query with SSMS
To connect and query using Visual Studio, see Connect and query with Visual Studio Code.
To connect and query using .NET, see Connect and query with .NET.
To connect and query using PHP, see Connect and query with PHP.
To connect and query using Java, see Connect and query with Java.
To connect and query using Python, see Connect and query with Python.
To connect and query using Ruby, see Connect and query with Ruby.
Azure SQL Database: Use Java to connect and query
data
4/20/2017 • 5 min to read • Edit Online
This quick start demonstrates how to use Java to connect to an Azure SQL database, and then use Transact-SQL
statements to query, insert, update, and delete data in the database from Mac OS, Ubuntu Linux, and Windows
platforms.
This quick start uses as its starting point the resources created in one of these quick starts:
Create DB - Portal
Create DB - CLI
Linux (Ubuntu)
Open your terminal and navigate to a directory where you plan on creating your Java project. Enter the following
commands to install Maven.
Windows
Install Maven using the official installer. Maven can be used to help manage dependencies, build, test and run
your Java project.
Add the Microsoft JDBC Driver for SQL Server to the dependencies in pom.xml.
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>6.1.0.jre8</version>
</dependency>
Select data
Use the following code to query for the top 20 products by category using the connection class with a SELECT
Transact-SQL statement. Replace the hostHame, dbName, user, and password parameters with the values that
you specified when you created the database with the AdventureWorksLT sample data.
package com.sqldbsamples;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.DriverManager;
// Connect to database
String hostName = "your_server.database.windows.net";
String dbName = "your_database";
String user = "your_username";
String password = "your_password";
String url =
String.format("jdbc:sqlserver://%s.database.windows.net:1433;database=%s;user=%s;password=%s;encrypt=true;hostNameInCertificate=*.d
atabase.windows.net;loginTimeout=30;", hostName, dbName, user, password);
Connection connection = null;
try {
connection = DriverManager.getConnection(url);
String schema = connection.getSchema();
System.out.println("Successful connection - Schema: " + schema);
Insert data
Use the following code to insert a new product into the SalesLT.Product table using the Prepared Statements
class with an INSERT Transact-SQL statement. Replace the hostHame, dbName, user, and password parameters
with the values that you specified when you created the database with the AdventureWorksLT sample data.
package com.sqldbsamples;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.DriverManager;
// Connect to database
String hostName = "your_server.database.windows.net";
String dbName = "your_database";
String user = "your_username";
String password = "your_password";
String url =
String.format("jdbc:sqlserver://%s.database.windows.net:1433;database=%s;user=%s;password=%s;encrypt=true;hostNameInCertificate=*.d
atabase.windows.net;loginTimeout=30;", hostName, dbName, user, password);
Connection connection = null;
try {
connection = DriverManager.getConnection(url);
String schema = connection.getSchema();
System.out.println("Successful connection - Schema: " + schema);
Update data
Use the following code to update the new product that you previously added using the Prepared Statements
class with an UPDATE Transact-SQL statement to update data in your Azure SQL database. Replace the
hostHame, dbName, user, and password parameters with the values that you specified when you created the
database with the AdventureWorksLT sample data.
package com.sqldbsamples;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.DriverManager;
// Connect to database
String hostName = "your_server.database.windows.net";
String dbName = "your_database";
String user = "your_username";
String password = "your_password";
String url =
String.format("jdbc:sqlserver://%s.database.windows.net:1433;database=%s;user=%s;password=%s;encrypt=true;hostNameInCertificate=*.d
atabase.windows.net;loginTimeout=30;", hostName, dbName, user, password);
Connection connection = null;
try {
connection = DriverManager.getConnection(url);
String schema = connection.getSchema();
System.out.println("Successful connection - Schema: " + schema);
Delete data
Use the following code to delete the new product that you previously added using the Prepared Statements with
a DELETE Transact-SQL statement . Replace the hostHame, dbName, user, and password parameters with the
values that you specified when you created the database with the AdventureWorksLT sample data.
package com.sqldbsamples;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.DriverManager;
// Connect to database
String hostName = "your_server.database.windows.net";
String dbName = "your_database";
String user = "your_username";
String password = "your_password";
String url =
String.format("jdbc:sqlserver://%s.database.windows.net:1433;database=%s;user=%s;password=%s;encrypt=true;hostNameInCertificate=*.d
atabase.windows.net;loginTimeout=30;", hostName, dbName, user, password);
Connection connection = null;
try {
connection = DriverManager.getConnection(url);
String schema = connection.getSchema();
System.out.println("Successful connection - Schema: " + schema);
Next steps
GitHub repository for Microsoft JDBC Driver for SQL Server.
File issues/ask questions.
To connect and query using SQL Server Management Studio, see Connect and query with SSMS
To connect and query using Visual Studio, see Connect and query with Visual Studio Code.
To connect and query using .NET, see Connect and query with .NET.
To connect and query using PHP, see Connect and query with PHP.
To connect and query using Node.js, see Connect and query with Node.js.
To connect and query using Python, see Connect and query with Python.
To connect and query using Ruby, see Connect and query with Ruby.
Azure SQL Database: Use Python to connect and
query data
4/20/2017 • 4 min to read • Edit Online
This quick start demonstrates how to use Python to connect to an Azure SQL database, and then use Transact-
SQL statements to query, insert, update, and delete data in the database from Mac OS, Ubuntu Linux, and
Windows platforms.
This quick start uses as its starting point the resources created in one of these quick starts:
Create DB - Portal
Create DB - CLI
Linux (Ubuntu)
Open your terminal and navigate to a directory where you plan on creating your python script. Enter the
following commands to install the Microsoft ODBC Driver for Linux and pyodbc. pyodbc uses the Microsoft
ODBC Driver on Linux to connect to SQL Databases.
sudo su
curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list > /etc/apt/sources.list.d/mssql.list
exit
sudo apt-get update
sudo apt-get install msodbcsql mssql-tools unixodbc-dev
sudo pip install pyodbc==3.1.1
Windows
Install the Microsoft ODBC Driver 13.1 (upgrade the driver if prompted). Pyodbc uses the Microsoft ODBC Driver
on Linux to connect to SQL Databases.
Then install pyodbc using pip.
pip install pyodbc==3.1.1
4. If you have forgotten the login information for your Azure SQL Database server, navigate to the SQL
Database server page to view the server admin name and, if necessary, reset the password.
Select Data
Use the following code to query for the top 20 products by category using the pyodbc.connect function with a
SELECT Transact-SQL statement. The cursor.execute function is used to retrieve a result set from a query against
SQL Database. This function accepts a query and returns a result set that can be iterated over with the use of
cursor.fetchone(). Replace the server, database, username, and password parameters with the values that you
specified when you created the database with the AdventureWorksLT sample data.
import pyodbc
server = 'your_server.database.windows.net'
database = 'your_database'
username = 'your_username'
password = 'your_password'
driver= '{ODBC Driver 13 for SQL Server}'
cnxn =
pyodbc.connect('DRIVER='+driver+';PORT=1433;SERVER='+server+';PORT=1443;DATABASE='+database+';UID='+username+';PWD='+
password)
cursor = cnxn.cursor()
cursor.execute("SELECT TOP 20 pc.Name as CategoryName, p.name as ProductName FROM [SalesLT].[ProductCategory] pc JOIN [SalesLT].
[Product] p ON pc.productcategoryid = p.productcategoryid")
row = cursor.fetchone()
while row:
print str(row[0]) + " " + str(row[1])
row = cursor.fetchone()
Insert data
Use the following code to insert a new product into the SalesLT.Product table using the cursor.execute function
and the INSERT Transact-SQL statement. Replace the server, database, username, and password parameters with
the values that you specified when you created the database with the AdventureWorksLT sample data.
import pyodbc
server = 'your_server.database.windows.net'
database = 'your_database'
username = 'your_username'
password = 'your_password'
driver= '{ODBC Driver 13 for SQL Server}'
cnxn =
pyodbc.connect('DRIVER='+driver+';PORT=1433;SERVER='+server+';PORT=1443;DATABASE='+database+';UID='+username+';PWD='+
password)
cursor = cnxn.cursor()
with cursor.execute("INSERT INTO SalesLT.Product (Name, ProductNumber, Color, StandardCost, ListPrice, SellStartDate) OUTPUT
INSERTED.ProductID VALUES ('BrandNewProduct', '200989', 'Blue', 75, 80, '7/1/2016')"):
print ('Successfuly Inserted!')
cnxn.commit()
Update data
Use the following code to update the new product that you previously added using the cursor.execute function
and the UPDATE Transact-SQL statement. Replace the server, database, username, and password parameters
with the values that you specified when you created the database with the AdventureWorksLT sample data.
import pyodbc
server = 'your_server.database.windows.net'
database = 'your_database'
username = 'your_username'
password = 'your_password'
driver= '{ODBC Driver 13 for SQL Server}'
cnxn =
pyodbc.connect('DRIVER='+driver+';PORT=1433;SERVER='+server+';PORT=1443;DATABASE='+database+';UID='+username+';PWD='+
password)
cursor = cnxn.cursor()
tsql = "UPDATE SalesLT.Product SET ListPrice = ? WHERE Name = ?"
with cursor.execute(tsql,50,'BrandNewProduct'):
print ('Successfuly Updated!')
cnxn.commit()
Delete data
Use the following code to delete the new product that you previously added using the cursor.execute function
and the DELETE Transact-SQL statement. Replace the server, database, username, and password parameters with
the values that you specified when you created the database with the AdventureWorksLT sample data.
import pyodbc
server = 'your_server.database.windows.net'
database = 'your_database'
username = 'your_username'
password = 'your_password'
driver= '{ODBC Driver 13 for SQL Server}'
cnxn =
pyodbc.connect('DRIVER='+driver+';PORT=1433;SERVER='+server+';PORT=1443;DATABASE='+database+';UID='+username+';PWD='+
password)
cursor = cnxn.cursor()
tsql = "DELETE FROM SalesLT.Product WHERE Name = ?"
with cursor.execute(tsql,'BrandNewProduct'):
print ('Successfuly Deleted!')
cnxn.commit()
Next steps
More information on the Microsoft Python Driver for SQL Server.
Visit the Python Developer Center.
To connect and query using SQL Server Management Studio, see Connect and query with SSMS
To connect and query using Visual Studio, see Connect and query with Visual Studio Code.
To connect and query using .NET, see Connect and query with .NET.
To connect and query using PHP, see Connect and query with PHP.
To connect and query using Node.js, see Connect and query with Node.js.
To connect and query using Java, see Connect and query with Java.
To connect and query using Ruby, see Connect and query with Ruby.
Azure SQL Database: Use Ruby to connect and
query data
4/20/2017 • 5 min to read • Edit Online
This quick start demonstrates how to use Ruby to connect to an Azure SQL database, and then use Transact-SQL
statements to query, insert, update, and delete data in the database from Mac OS and Ubuntu Linux platforms.
This quick start uses as its starting point the resources created in one of these quick starts:
Create DB - Portal
Create DB - CLI
Linux (Ubuntu)
Open your terminal and navigate to a directory where you plan on creating your Ruby script. Enter the following
commands to install the FreeTDS and TinyTDS.
wget ftp://ftp.freetds.org/pub/freetds/stable/freetds-1.00.27.tar.gz
tar -xzf freetds-1.00.27.tar.gz
cd freetds-1.00.27
./configure --prefix=/usr/local --with-tdsver=7.3
make
make install
gem install tiny_tds
Select data
Use the following code to query for the top 20 products by category using the TinyTDS::Client function with a
SELECT Transact-SQL statement. The TinyTDS::Client function accepts a query and returns a result set. The results
set is iterated over by using result.each do |row|. Replace the server, database, username, and password
parameters with the values that you specified when you created the database with the AdventureWorksLT
sample data.
require 'tiny_tds'
server = 'your_server.database.windows.net'
database = 'your_database'
username = 'your_username'
password = 'your_password'
client = TinyTds::Client.new username: username, password: password,
host: server, port: 1433, database: database, azure: true
Insert data
Use the following code to insert a new product into the SalesLT.Product table using the TinyTDS::Client function
with an INSERT Transact-SQL statement. Replace the server, database, username, and password parameters with
the values that you specified when you created the database with the AdventureWorksLT sample data.
Tis example demonstrates how to execute an INSERT statement safely, pass parameters which protect your
application from SQL injection vulnerability, and retrieve the auto-generated Primary Key value.
To use TinyTDS with Azure, it is recommended that you execute several SET statements to change how the
current session handles specific information. Recommended SET statements are provided in the code sample.
For example, SET ANSI_NULL_DFLT_ON will allow new columns created to allow null values even if the nullability
status of the column is not explicitly stated.
To align with the Microsoft SQL Server datetime format, use the strftime function to cast to the corresponding
datetime format.
require 'tiny_tds'
server = 'your_server.database.windows.net'
database = 'your_database'
username = 'your_username'
password = 'your_password'
client = TinyTds::Client.new username: username, password: password,
host: server, port: 1433, database: database, azure: true
Update data
Use the following code to update the new product that you previously added using the TinyTDS::Client function
with a UPDATE Transact-SQL statement. Replace the server, database, username, and password parameters with
the values that you specified when you created the database with the AdventureWorksLT sample data.
require 'tiny_tds'
server = 'your_server.database.windows.net'
database = 'your_database'
username = 'your_username'
password = 'your_password'
client = TinyTds::Client.new username: username, password: password,
host: server, port: 1433, database: database, azure: true
Delete data
Use the following code to delete the new product that you previously added using the TinyTDS::Client function
with a DELETE Transact-SQL statement. Replace the server, database, username, and password parameters with
the values that you specified when you created the database with the AdventureWorksLT sample data.
require 'tiny_tds'
server = 'your_server.database.windows.net'
database = 'your_database'
username = 'your_username'
password = 'your_password'
client = TinyTds::Client.new username: username, password: password,
host: server, port: 1433, database: database, azure: true
Next Steps
Github repository for TinyTDS.
File issues/ask questions.
More information on the Ruby Driver for SQL Server.
To connect and query using SQL Server Management Studio, see Connect and query with SSMS
To connect and query using Visual Studio, see Connect and query with Visual Studio Code.
To connect and query using .NET, see Connect and query with .NET.
To connect and query using PHP, see Connect and query with PHP.
To connect and query using Node.js, see Connect and query with Node.js.
To connect and query using Java, see Connect and query with Java.
To connect and query using Python, see Connect and query with Python.
Design your first Azure SQL database
4/21/2017 • 8 min to read • Edit Online
In this tutorial, you build a database for a university to track student grades and courses enrollment. This tutorial
demonstrates how to use the Azure portal and SQL Server Management Studio (SSMS) to create an Azure SQL
database on an Azure SQL Database logical server, add tables to the database, load data into the tables, and query
the database. It also demonstrates how to use SQL Database point in time restore capabilities to restore the
database to an earlier point in time.
To complete this tutorial, make sure you have installed the newest version of SQL Server Management Studio
(SSMS).
3. Fill out the SQL Database form with the following information, as shown on the preceding image:
Database name: mySampleDatabase
Resource group: myResourceGroup
Source: Blank database
4. Click Server to create and configure a new server for your new database. Fill out the New server form
specifying a globally unique server name, provide a name for the Server admin login, and then specify the
password of your choice.
5. Click Select.
6. Click Pricing tier to specify the service tier and performance level for your new database. For this tutorial,
select 20 DTUs and 250 GB of storage.
7. Click Apply.
8. Click Create to provision the database. Provisioning takes about a minute and a half to complete.
9. On the toolbar, click Notifications to monitor the deployment process.
Create a server-level firewall rule
Azure SQL Databases are protected by a firewall. By default, all connections to the server and the databases inside
the server are rejected. Follow these steps to create a SQL Database server-level firewall rule for your server to
allow connections from your client's IP address.
1. After the deployment completes, click SQL databases from the left-hand menu and click your new database,
mySampleDatabase, on the SQL databases page. The overview page for your database opens, showing
you the fully qualified server name (such as mynewserver-20170313.database.windows.net) and
provides options for further configuration.
2. Click Set server firewall on the toolbar as shown in the previous image. The Firewall settings page for the
SQL Database server opens.
3. Click Add client IP on the toolbar and then click Save. A server-level firewall rule is created for your current
IP address.
4. Click OK and then click the X to close the Firewall settings page.
You can now connect to the database and its server using SQL Server Management Studio or another tool of your
choice.
NOTE
SQL Database communicates over port 1433. If you are trying to connect from within a corporate network, outbound traffic
over port 1433 may not be allowed by your network's firewall. If so, you will not be able to connect to your Azure SQL
Database server unless your IT department opens port 1433.
1. Click Options in the Connect to server dialog box. In the Connect to database section, enter
mySampleDatabase to connect to this database.
NOTE
You can also use the table designer in SQL Server Management Studio to create and design your tables.
1. In Object Explorer, right-click mySampleDatabase and click New Query. A blank query window opens that
is connected to your database.
2. In the query window, execute the following query to create four tables in your database:
-- Create Person table
You have now loaded sample data into the tables you created earlier.
-- Find the students taught by Dominick Pope who have a grade higher than 75%
SELECT person.FirstName,
person.LastName,
course.Name,
credit.Grade
FROM Person AS person
INNER JOIN Student AS student ON person.PersonId = student.PersonId
INNER JOIN Credit AS credit ON student.StudentId = credit.StudentId
INNER JOIN Course AS course ON credit.CourseId = course.courseId
WHERE course.Teacher = 'Dominick Pope'
AND Grade > 75
-- Find all the courses in which Noe Coleman has ever enrolled
SELECT course.Name,
course.Teacher,
credit.Grade
FROM Course AS course
INNER JOIN Credit AS credit ON credit.CourseId = course.CourseId
INNER JOIN Student AS student ON student.StudentId = credit.StudentId
INNER JOIN Person AS person ON person.PersonId = student.PersonId
WHERE person.FirstName = 'Noe'
AND person.LastName = 'Coleman'
3. Click OK to restore the database to restore to a point in time before the tables were added. Restoring a
database to a different point in time creates a duplicate database in the same server as the original database
as of the point in time you specify, provided that it is within the retention period for your service tier.
Next Steps
For PowerShell samples for common tasks, see SQL Database PowerShell samples
Migrate your SQL Server database to Azure SQL
Database
4/21/2017 • 8 min to read • Edit Online
In this tutorial, you migrate an existing SQL Server database to Azure SQL Database using the Microsoft Data
Migration Assistant and go through the required steps from preparing for migration to performing the actual data
migration, and connecting to the migrated database after completed migration.
IMPORTANT
To fix compatibility issues, use Visual Studio Data Tools.
If you don't have an Azure subscription, create a free account before you begin.
To complete this tutorial, make sure you have:
The newest version of SQL Server Management Studio (SSMS). Installing SSMS also installs the newest version
of SQLPackage, a command-line utility that can be used to automate a range of database development tasks.
The Data Migration Assistant (DMA).
A database to migrate. This tutorial uses the SQL Server 2008R2 AdventureWorks OLTP database on an
instance of SQL Server 2008R2 or newer, but you can use any database of your choice.
3. On the Options page, click Next. The Select sources page opens.
4. On the Select sources page, enter the name of SQL Server instance containing the server you plan to
migrate. Change the other values on this page if necessary. Click Connect.
5. In the Add sources portion of the Select sources page, select the checkboxes for the databases to be tested
for compatibility. Click Add.
8. Review the results, beginning with SQL Server feature parity. Specifically review the information about
unsupported and partially supported features, and the provided information about recommended actions.
9. Click Compatibility issues. Specifically review the information about migration blockers, behavior changes,
and deprecated features for each compatibility level. For the AdventureWorks2008R2 database, review the
changes to Full-Text Search since SQL Server 2008 and the changes to SERVERPROPERTY('LCID') since SQL
Server 2000. For details on these changes, links for more information is provided. Many search options and
settings for Full-Text Search have changed
IMPORTANT
After you migrate your database to Azure SQL Database, you can choose to operate the database at its current
compatibility level (level 100 for the AdventureWorks2008R2 database) or at a higher level. For more information on
the implications and options for operating a database at a specific compatibility level, see ALTER DATABASE
Compatibility Level. See also ALTER DATABASE SCOPED CONFIGURATION for information about additional
database-level settings related to compatibility levels.
10. Optionally, click Export report to save the report as a JSON file.
11. Close the Data Migration Assistant.
3. On the Everything page, click SQL server (logical server) and then click Create on the SQL Server
(logical server) page.
4. Fill out the SQL server (logical server) form with the following information, as shown on the preceding
image:
Server name: Specify a globally unique server name
Server admin login: Provide a name for the Server admin login
Password: Specify the password of your choice
Resource group: Select Create new and specify myResourceGroup
Location: Select a data center location
5. Click Create to provision the logical server. Provisioning takes a few minutes.
4. Click OK.
You can now connect to all databases on this server using SQL Server Management Studio or another tool of your
choice from this IP address using the server admin account created previously.
NOTE
SQL Database communicates over port 1433. If you are trying to connect from within a corporate network, outbound traffic
over port 1433 may not be allowed by your network's firewall. If so, you will not be able to connect to your Azure SQL
Database server unless your IT department opens port 1433.
Next steps
For an overview of migration, see Database migration.
For a discussion of T-SQL differences, see Resolving Transact-SQL differences during migration to SQL
Database.
To connect and query using Visual Studio Code, see Connect and query with Visual Studio Code.
To connect and query using .NET, see Connect and query with .NET.
To connect and query using PHP, see Connect and query with PHP.
To connect and query using Node.js, see Connect and query with Node.js.
To connect and query using Java, see Connect and query with Java.
To connect and query using Python, see Connect and query with Python.
To connect and query using Ruby, see Connect and query with Ruby.
Azure CLI samples for Azure SQL Database
3/29/2017 • 1 min to read • Edit Online
The following table includes links to sample Azure CLI scripts for Azure SQL Database.
Create a single database and configure a firewall rule Creates a single Azure SQL database and configures a server-
level firewall rule.
Create elastic pools and move pooled databases Creates elastic pools, and moves pooled Azure SQL databases,
and changes performance levels.
Scale a single database Scales a single Azure SQL database to a different performance
level after querying the size information for the database.
The following table includes links to sample Azure PowerShell scripts for Azure SQL Database.
Create a single database and configure a firewall rule Creates a single Azure SQL database and configures a server-
level firewall rule.
Create elastic pools and move pooled databases Creates elastic pools, and moves pooled databases, and
changes performance levels.
Configure and failover a single database using Active Geo- Configures Active Geo-Replication for a single Azure SQL
Replication database and fails it over to the secondary replica.
Configure and failover a pooled database using Active Geo- Configures Active Geo-Replication for an Azure SQL database
Replication in an elastic pool and fails it over to the secondary replica.
Scale a single database Monitors the performance metrics of an Azure SQL database,
scales it to a higher performance level and creates an alert rule
on one of the performance metrics.
Scale an elastic pool Monitors the performance metrics of an elastic pool, scales it
to a higher performance level, and creates an alert rule on one
of the performance metrics.
Configure auditing and threat-detection Configures auditing and threat detection policies for an Azure
SQL database.
Copy a database to new server Creates a copy of an existing Azure SQL database in a new
Azure SQL server.
Import a database from a bacpac file Imports a database to an Azure SQL server from a bacpac file.
Azure SQL database overview
4/14/2017 • 2 min to read • Edit Online
This topic provides an overview of Azure SQL databases. For information about Azure SQL logical servers, see
Logical servers.
Next steps
For information about the Azure SQL Database service, see What is SQL Database?
For information about supported features, see Features
For an overview of Azure SQL logical servers, see SQL Database logical server overview
For information about Transact-SQL support and differences, see Azure SQL Database Transact-SQL differences.
For information about specific resource quotas and limitations based on your service tier. For an overview of
service tiers, see SQL Database service tiers.
For an overview of security, see Azure SQL Database Security Overview.
For information on driver availability and support for SQL Database, see Connection Libraries for SQL Database
and SQL Server.
Azure SQL Database logical servers
4/14/2017 • 3 min to read • Edit Online
This topic provides considerations and guidelines for working with Azure SQL logical servers. For information
about Azure SQL databases, see SQL databases.
Next steps
For information about the Azure SQL Database service, see What is SQL Database?
For information about supported features, see Features
For an overview of Azure SQL databases, see SQL database overview
For information about Transact-SQL support and differences, see Azure SQL Database Transact-SQL
differences.
For information about specific resource quotas and limitations based on your service tier. For an overview of
service tiers, see SQL Database service tiers.
For an overview of security, see Azure SQL Database Security Overview.
For information on driver availability and support for SQL Database, see Connection Libraries for SQL Database
and SQL Server.
Elastic pools help you manage and scale multiple
SQL databases
4/19/2017 • 14 min to read • Edit Online
SQL Database elastic pools are a simple, cost-effective solution for managing and scaling multiple databases
that have varying and unpredictable usage demands. The databases in an elastic pool are on a single Azure
SQL Database server and share a set number of resources (elastic Database Transaction Units (eDTUs)) at a
set price. Elastic pools in Azure SQL Database enable SaaS developers to optimize the price performance for a
group of databases within a prescribed budget while delivering performance elasticity for each database.
NOTE
Elastic pools are generally available (GA) in all Azure regions except West India where it is currently in preview. GA of
elastic pools in this region will occur as soon as possible.
Elastic pools enable the developer to purchase elastic Database Transaction Units (eDTUs) for a pool shared
by multiple databases to accommodate unpredictable periods of usage by individual databases. The eDTU
requirement for a pool is determined by the aggregate utilization of its databases. The number of eDTUs
available to the pool is controlled by the developer budget. The developer simply adds databases to the pool,
sets the minimum and maximum eDTUs for the databases, and then sets the eDTU of the pool based on their
budget. A developer can use pools to seamlessly grow their service from a lean startup to a mature business
at ever-increasing scale.
Within the pool, individual databases are given the flexibility to auto-scale within set parameters. Under
heavy load, a database can consume more eDTUs to meet demand. Databases under light loads consume
less, and databases under no load consume no eDTUs. Provisioning resources for the entire pool rather than
for single databases simplifies your management tasks. Plus you have a predictable budget for the pool.
Additional eDTUs can be added to an existing pool with no database downtime, except that the databases
may need to be moved to provide the additional compute resources for the new eDTU reservation. Similarly,
if extra eDTUs are no longer needed they can be removed from an existing pool at any point in time. And you
can add or subtract databases to the pool. If a database is predictably under-utilizing resources, move it out.
You can create and manage an elastic pool using the Azure portal, PowerShell, Transact-SQL, C#, and the
REST API.
For the five-minute period illustrated, DB1 peaks up to 90 DTUs, but its overall average usage is less than five
DTUs. An S3 performance level is required to run this workload in a single database, but this leaves most of
the resources unused during periods of low activity.
A pool allows these unused DTUs to be shared across multiple databases, and so reduces the DTUs needed
and overall cost.
Building on the previous example, suppose there are additional databases with similar utilization patterns as
DB1. In the next two figures below, the utilization of four databases and 20 databases are layered onto the
same graph to illustrate the non-overlapping nature of their utilization over time:
The aggregate DTU utilization across all 20 databases is illustrated by the black line in the preceding figure.
This shows that the aggregate DTU utilization never exceeds 100 DTUs, and indicates that the 20 databases
can share 100 eDTUs over this time period. This results in a 20x reduction in DTUs and a 13x price reduction
compared to placing each of the databases in S3 performance levels for single databases.
This example is ideal for the following reasons:
There are large differences between peak utilization and average utilization per database.
The peak utilization for each database occurs at different points in time.
eDTUs are shared between many databases.
The price of a pool is a function of the pool eDTUs. While the eDTU unit price for a pool is 1.5x greater than
the DTU unit price for a single database, pool eDTUs can be shared by many databases and fewer total
eDTUs are needed. These distinctions in pricing and eDTU sharing are the basis of the price savings
potential that pools can provide.
The following rules of thumb related to database count and database utilization help to ensure that a pool
delivers reduced cost compared to using performance levels for single databases.
Minimum number of databases
If the sum of the DTUs of performance levels for single databases is more than 1.5x the eDTUs needed for the
pool, then an elastic pool is more cost effective. For available sizes, see eDTU and storage limits for elastic
pools and elastic databases.
Example
At least two S3 databases or at least 15 S0 databases are needed for a 100 eDTU pool to be more cost-
effective than using performance levels for single databases.
Maximum number of concurrently peaking databases
By sharing eDTUs, not all databases in a pool can simultaneously use eDTUs up to the limit available when
using performance levels for single databases. The fewer databases that concurrently peak, the lower the pool
eDTU can be set and the more cost-effective the pool becomes. In general, not more than 2/3 (or 67%) of the
databases in the pool should simultaneously peak to their eDTU limit.
Example
To reduce costs for three S3 databases in a 200 eDTU pool, at most two of these databases can
simultaneously peak in their utilization. Otherwise, if more than two of these four S3 databases
simultaneously peak, the pool would have to be sized to more than 200 eDTUs. If the pool is resized to more
than 200 eDTUs, more S3 databases would need to be added to the pool to keep costs lower than
performance levels for single databases.
Note this example does not consider utilization of other databases in the pool. If all databases have some
utilization at any given point in time, then less than 2/3 (or 67%) of the databases can peak simultaneously.
DTU utilization per database
A large difference between the peak and average utilization of a database indicates prolonged periods of low
utilization and short periods of high utilization. This utilization pattern is ideal for sharing resources across
databases. A database should be considered for a pool when its peak utilization is about 1.5 times greater
than its average utilization.
Example
An S3 database that peaks to 100 DTUs and on average uses 67 DTUs or less is a good candidate for sharing
eDTUs in a pool. Alternatively, an S1 database that peaks to 20 DTUs and on average uses 13 DTUs or less is a
good candidate for a pool.
Max In- N/A N/A N/A N/A N/A N/A N/A N/A
Memory
OLTP
storage
per pool*
Max In-Memory 1 GB 2 GB 4 GB 10 GB 12 GB
OLTP storage
per pool*
Max In-Memory 16 GB 20 GB 24 GB 28 GB 32 GB
OLTP storage
per pool*
Max In-Memory 1 GB 2 GB 4 GB 10 GB
OLTP storage per
pool*
IMPORTANT
* Pooled databases share pool storage, so data storage in an elastic pool is limited to the smaller of the remaining pool
storage or max storage per database.
If all DTUs of an elastic pool are used, then each database in the pool receives an equal amount of resources
to process queries. The SQL Database service provides resource sharing fairness between databases by
ensuring equal slices of compute time. Elastic pool resource sharing fairness is in addition to any amount of
resource otherwise guaranteed to each database when the DTU min per database is set to a non-zero value.
PROPERTY DESCRIPTION
PROPERTY DESCRIPTION
Max eDTUs per database The maximum number of eDTUs that any database in the
pool may use, if available based on utilization by other
databases in the pool. Max eDTU per database is not a
resource guarantee for a database. This setting is a global
setting that applies to all databases in the pool. Set max
eDTUs per database high enough to handle peaks in
database utilization. Some degree of overcommitting is
expected since the pool generally assumes hot and cold
usage patterns for databases where all databases are not
simultaneously peaking. For example, suppose the peak
utilization per database is 20 eDTUs and only 20% of the
100 databases in the pool are peak at the same time. If the
eDTU max per database is set to 20 eDTUs, then it is
reasonable to overcommit the pool by 5 times, and set the
eDTUs per pool to 400.
Min eDTUs per database The minimum number of eDTUs that any database in the
pool is guaranteed. This setting is a global setting that
applies to all databases in the pool. The min eDTU per
database may be set to 0, and is also the default value. This
property is set to anywhere between 0 and the average
eDTU utilization per database. The product of the number
of databases in the pool and the min eDTUs per database
cannot exceed the eDTUs per pool. For example, if a pool
has 20 databases and the eDTU min per database set to
10 eDTUs, then the eDTUs per pool must be at least as
large as 200 eDTUs.
Max data storage per database The maximum storage for a database in a pool. Pooled
databases share pool storage, so database storage is
limited to the smaller of remaining pool storage and max
storage per database. Max storage per database refers to
the maximum size of the data files and does not include
the space used by log files.
Elastic jobs
With a pool, management tasks are simplified by running scripts in elastic jobs. An elastic job eliminates
most of tedium associated with large numbers of databases. To begin, see Getting started with Elastic jobs.
For more information about other database tools for working with multiple databases, see Scaling out with
Azure SQL Database.
Next steps
You can create and manage an elastic pool using the Azure portal, PowerShell, Transact-SQL, C#, and the
REST API.
For a video, see Microsoft Virtual Academy video course on Azure SQL Database elastic capabilities
To learn more about design patterns for SaaS applications using elastic pools, see Design Patterns for
Multi-tenant SaaS Applications with Azure SQL Database.
SQL Database options and performance:
Understand what's available in each service tier
4/20/2017 • 14 min to read • Edit Online
Azure SQL Database offers four service tiers: Basic, Standard, Premium, and Premium RS. Each service
tier has multiple performance levels to handle different workloads. Higher performance levels provide
additional resources designed to deliver increasingly higher throughput. You can change service tiers and
performance levels dynamically without downtime. Basic, Standard, and Premium service tiers all have an
uptime SLA of 99.99%, flexible business continuity options, security features, and hourly billing. The
Premium RS tier provides the same performance levels, security features and business continuity features as
the Premium tier albeit at a reduced SLA.
IMPORTANT
Premium RS databases run with a lower number of redundant copies than Premium or Standard databases. So, in the
event of a service failure, you may need to recover your database from a backup with up to a 5-minute lag.
You can create single databases with dedicated resources within a service tier at a specific performance level.
You can also create databases within an elastic pool in which the resources are shared across multiple
databases. The resources available for single databases are expressed in terms of Database Transaction Units
(DTUs) and for elastic pools in terms of elastic Database Transaction Units (eDTUs). For more on DTUs and
eDTUs, see What is a DTU?
SERVICE TIER
FEATURES BASIC STANDARD PREMIUM PREMIUM RS
IMPORTANT
Individual databases of up to 4 TB is public preview for customers using P11 and P15 performance levels at no
additional charge. Premium pools with more than 750 GB of storage are also currently available. These additional
storage options are currently available in the following regions: US East2, West US, West Europe, South East Asia,
Japan East, Australia East, Canada Central, and Canada East. See Current 4 TB limitations
Once you have determined the minimum service tier, you are ready to determine the performance level for
the database (the number of DTUs). The standard S2 and S3 performance levels are often a good starting
point. For databases with high CPU or IO requirements, the Premium performance levels are the right
starting point. Premium offers more CPU and starts at 10x more IO compared to the highest Standard
performance level.
Max DTUs 5
Max in- 1 GB 2 GB 4 GB 8 GB 14 GB 32 GB
memory
OLTP
storage
Max in-memory 1 GB 2 GB 4 GB 8 GB
OLTP storage
* Max database size refers to the maximum size of the data in the database.
NOTE
For a detailed explanation of all other rows in this service tiers table, see Service tier capabilities and limits.
Changing the service tier and/or performance level of a database creates a replica of the original database at
the new performance level, and then switches connections over to the replica. No data is lost during this
process but during the brief moment when we switch over to the replica, connections to the database are
disabled, so some transactions in flight may be rolled back. This window varies, but is on average under 4
seconds, and in more than 99% of cases is less than 30 seconds. If there are large numbers of transactions in
flight at the moment connections are disabled, this window may be longer.
The duration of the entire scale-up process depends on both the size and service tier of the database before
and after the change. For example, a 250 GB database that is changing to, from, or within a Standard service
tier, should complete within 6 hours. For a database of the same size that is changing performance levels
within the Premium service tier, it should complete within 3 hours.
To downgrade a database, the database should be smaller than the maximum allowed size of the target
service tier.
When upgrading a database with Geo-Replication enabled, you must first upgrade its secondary
databases to the desired performance tier before upgrading the primary database.
When downgrading from a Premium service tier, you must first terminate all Geo-Replication
relationships. You can follow the steps described in the Recover from an outage topic to stop the
replication process between the primary and the active secondary databases.
The restore service offerings are different for the various service tiers. If you are downgrading you may
lose the ability to restore to a point in time, or have a lower backup retention period. For more
information, see Azure SQL Database Backup and Restore.
The new properties for the database are not applied until the changes are complete.
Max In- N/A N/A N/A N/A N/A N/A N/A N/A
Memory
OLTP
storage
per pool*
Max In-Memory 1 GB 2 GB 4 GB 10 GB 12 GB
OLTP storage
per pool*
POOL SIZE
(EDTUS) 125 250 500 1000 1500
Max In-Memory 16 GB 20 GB 24 GB 28 GB 32 GB
OLTP storage
per pool*
Max In-Memory 1 GB 2 GB 4 GB 10 GB
OLTP storage per
pool*
IMPORTANT
* Pooled databases share pool storage, so data storage in an elastic pool is limited to the smaller of the remaining
pool storage or max storage per database.
Each database within a pool also adheres to the single database characteristics for that tier. For example, the
Basic pool has a limit for max sessions per pool of 4800 - 28800, but an individual database within a Basic
pool has a database limit of 300 sessions.
Upgrading an existing P11 or P15 database can only be performed by a server-level principal login or by
members of the dbmanager database role. If executed in a supported region the configuration will be
updated immediately. This can be checked using the SELECT DATABASEPROPERTYEX or by inspecting the
database size in the Azure portal. The database will remain online during the upgrade process. However, you
will not be able to utilize the full 4 TB of storage until the actual database files have been upgraded to the
new maxsize. The length of time required depends upon on the size of the database being upgraded.
Error messages
When creating or upgrading an P11/P15 database in an unsupported region, the create or upgrade
operation will fail with the following error message: P11 and P15 database with up to 4TB of storage are
available in US East 2, West US, South East Asia, West Europe, Canada East, Canada Central, Japan
East, and Australia East.
Next steps
Learn the details of elastic pools and price and performance considerations for elastic pools.
Learn how to Monitor, manage, and resize elastic pools and Monitor the performance of single
databases.
Now that you know about the SQL Database tiers, try them out with a free account and learn how to
create your first SQL database.
For migration scenarios, use the DTU Calculator to approximate the number of DTUs needed.
Explaining Database Transaction Units (DTUs) and
elastic Database Transaction Units (eDTUs)
4/19/2017 • 5 min to read • Edit Online
This article explains Database Transaction Units (DTUs) and elastic Database Transaction Units (eDTUs) and what
happens when you hit the maximum DTUs or eDTUs.
DTUs are most useful for understanding the relative amount of resources between Azure SQL Databases at
different performance levels and service tiers. For example, doubling the DTUs by increasing the performance
level of a database equates to doubling the set of resource available to that database. For example, a Premium
P11 database with 1750 DTUs provides 350x more DTU compute power than a Basic database with 5 DTUs.
To gain deeper insight into the resource (DTU) consumption of your workload, use Azure SQL Database Query
Performance Insight to:
Identify the top queries by CPU/Duration/Execution count that can potentially be tuned for improved
performance. For example, an I/O intensive query might benefit from the use of in-memory optimization
techniques to make better use of the available memory at a certain service tier and performance level.
Drill down into the details of a query, view its text and history of resource utilization.
Access performance tuning recommendations that show actions performed by SQL Database Advisor.
You can change service tiers at any time with minimal downtime to your application (generally averaging under
four seconds). For many businesses and apps, being able to create databases and dial performance up or down on
demand is enough, especially if usage patterns are relatively predictable. But if you have unpredictable usage
patterns, it can make it hard to manage costs and your business model. For this scenario, you use an elastic pool
with a certain number of eDTUs that are shared among multiple database in the pool.
A pool is given a set number of eDTUs, for a set price. Within the elastic pool, individual databases are given the
flexibility to auto-scale within the configured boundaries. Under heavy load, a database can consume more eDTUs
to meet demand while databases under light loads consume less, up to the point that databases under no load
consume no eDTUs. By provisioning resources for the entire pool, rather than per database, management tasks
are simplified and you have a predictable budget for the pool.
Additional eDTUs can be added to an existing pool with no database downtime and with no impact on the
databases in the pool. Similarly, if extra eDTUs are no longer needed, they can be removed from an existing pool
at any point in time. You can add or subtract databases to the pool, or limit the amount of eDTUs a database can
use under heavy load to reserve eDTUs for other databases. If a database is predictably under-utilizing resources,
you can move it out of the pool and configure it as a single database with predictable amount of resources it
requires.
Next steps
See Service tier for information on the DTUs and eDTUs available for single databases and for elastic pools.
See Azure SQL Database resource limits for information on limit on resources other than CPU, memory, data
I/O, and transaction log I/O.
See SQL Database Query Performance Insight to understand your (DTUs) consumption.
See SQL Database benchmark overview to understand the methodology behind the OLTP benchmark
workload used to determine the DTU blend.
Azure SQL Database benchmark overview
4/14/2017 • 7 min to read • Edit Online
Overview
Microsoft Azure SQL Database offers three service tiers with multiple performance levels. Each performance level
provides an increasing set of resources, or ‘power’, designed to deliver increasingly higher throughput.
It is important to be able to quantify how the increasing power of each performance level translates into increased
database performance. To do this Microsoft has developed the Azure SQL Database Benchmark (ASDB). The
benchmark exercises a mix of basic operations found in all OLTP workloads. We measure the throughput achieved
for databases running in each performance level.
The resources and power of each service tier and performance level are expressed in terms of Database
Transaction Units (DTUs). DTUs provide a way to describe the relative capacity of a performance level based on a
blended measure of CPU, memory, and read and write rates offered by each performance level. Doubling the DTU
rating of a database equates to doubling the database power. The benchmark allows us to assess the impact on
database performance of the increasing power offered by each performance level by exercising actual database
operations, while scaling database size, number of users, and transaction rates in proportion to the resources
provided to the database.
By expressing the throughput of the Basic service tier using transactions per-hour, the Standard service tier using
transactions per-minute, and the Premium service tier using transactions per-second, it makes it easier to quickly
relate the performance potential of each service tier to the requirements of an application.
Benchmark summary
ASDB measures the performance of a mix of basic database operations which occur most frequently in online
transaction processing (OLTP) workloads. Although the benchmark is designed with cloud computing in mind, the
database schema, data population, and transactions have been designed to be broadly representative of the basic
elements most commonly used in OLTP workloads.
Schema
The schema is designed to have enough variety and complexity to support a broad range of operations. The
benchmark runs against a database comprised of six tables. The tables fall into three categories: fixed-size, scaling,
and growing. There are two fixed-size tables; three scaling tables; and one growing table. Fixed-size tables have a
constant number of rows. Scaling tables have a cardinality that is proportional to database performance, but
doesn’t change during the benchmark. The growing table is sized like a scaling table on initial load, but then the
cardinality changes in the course of running the benchmark as rows are inserted and deleted.
The schema includes a mix of data types, including integer, numeric, character, and date/time. The schema includes
primary and secondary keys, but not any foreign keys - that is, there are no referential integrity constraints
between tables.
A data generation program generates the data for the initial database. Integer and numeric data is generated with
various strategies. In some cases, values are distributed randomly over a range. In other cases, a set of values is
randomly permuted to ensure that a specific distribution is maintained. Text fields are generated from a weighted
list of words to produce realistic looking data.
The database is sized based on a “scale factor.” The scale factor (abbreviated as SF) determines the cardinality of
the scaling and growing tables. As described below in the section Users and Pacing, the database size, number of
users, and maximum performance all scale in proportion to each other.
Transactions
The workload consists of nine transaction types, as shown in the table below. Each transaction is designed to
highlight a particular set of system characteristics in the database engine and system hardware, with high contrast
from the other transactions. This approach makes it easier to assess the impact of different components to overall
performance. For example, the transaction “Read Heavy” produces a significant number of read operations from
disk.
Workload mix
Transactions are selected at random from a weighted distribution with the following overall mix. The overall mix
has a read/write ratio of approximately 2:1.
TRANSACTION TYPE % OF MIX
Read Lite 35
Read Medium 20
Read Heavy 5
Update Lite 20
Update Heavy 3
Insert Lite 3
Insert Heavy 2
Delete 2
CPU Heavy 10
Scaling rules
The number of users is determined by the database size (in scale-factor units). There is one user for every five
scale-factor units. Because of the pacing delay, one user can generate at most one transaction per second, on
average.
For example, a scale-factor of 500 (SF=500) database will have 100 users and can achieve a maximum rate of 100
TPS. To drive a higher TPS rate requires more users and a larger database.
The table below shows the number of users actually sustained for each service tier and performance level.
Basic 5 720 MB
SERVICE TIER (PERFORMANCE LEVEL) USERS DATABASE SIZE
Standard (S0) 10 1 GB
Measurement duration
A valid benchmark run requires a steady-state measurement duration of at least one hour.
Metrics
The key metrics in the benchmark are throughput and response time.
Throughput is the essential performance measure in the benchmark. Throughput is reported in transactions per
unit-of-time, counting all transaction types.
Response time is a measure of performance predictability. The response time constraint varies with class of
service, with higher classes of service having a more stringent response time requirement, as shown below.
Conclusion
The Azure SQL Database Benchmark measures the relative performance of Azure SQL Database running across the
range of available service tiers and performance levels. The benchmark exercises a mix of basic database
operations which occur most frequently in online transaction processing (OLTP) workloads. By measuring actual
performance, the benchmark provides a more meaningful assessment of the impact on throughput of changing
the performance level than is possible by just listing the resources provided by each level such as CPU speed,
memory size, and IOPS. In the future, we will continue to evolve the benchmark to broaden its scope and expand
the data provided.
Resources
Introduction to SQL Database
Service tiers and performance levels
Performance guidance for single databases
Azure SQL Database resource limits
4/19/2017 • 8 min to read • Edit Online
Overview
Azure SQL Database manages the resources available to a database using two different mechanisms: Resources
Governance and Enforcement of Limits. This topic explains these two main areas of resource management.
Resource governance
One of the design goals of the Basic, Standard, Premium, and Premium RS service tiers is for Azure SQL Database
to behave as if the database is running on its own machine, isolated from other databases. Resource governance
emulates this behavior. If the aggregated resource utilization reaches the maximum available CPU, Memory, Log
I/O, and Data I/O resources assigned to the database, resource governance queues queries in execution and
assign resources to the queued queries as they free up.
As on a dedicated machine, utilizing all available resources results in a longer execution of currently executing
queries, which can result in command timeouts on the client. Applications with aggressive retry logic and
applications that execute queries against the database with a high frequency can encounter errors messages when
trying to execute new queries when the limit of concurrent requests has been reached.
Recommendations:
Monitor the resource utilization and the average response times of queries when nearing the maximum utilization
of a database. When encountering higher query latencies you generally have three options:
1. Reduce the number of incoming requests to the database to prevent timeout and the pile up of requests.
2. Assign a higher performance level to the database.
3. Optimize queries to reduce the resource utilization of each query. For more information, see the Query
Tuning/Hinting section in the Azure SQL Database Performance Guidance article.
Enforcement of limits
Resources other than CPU, Memory, Log I/O, and Data I/O are enforced by denying new requests when limits are
reached. When a database reaches the configured maximum size limit, inserts and updates that increase data size
fail, while selects and deletes continue to work. Clients receive an error message depending on the limit that has
been reached.
For example, the number of connections to a SQL database and the number of concurrent requests that can be
processed are restricted. SQL Database allows the number of connections to the database to be greater than the
number of concurrent requests to support connection pooling. While the number of connections that are available
can easily be controlled by the application, the number of parallel requests is often times harder to estimate and
to control. Especially during peak loads when the application either sends too many requests or the database
reaches its resource limits and starts piling up worker threads due to longer running queries, errors can be
encountered.
Max DTUs 5
Max in- 1 GB 2 GB 4 GB 8 GB 14 GB 32 GB
memory OLTP
storage
PERFORMANCE
LEVEL P1 P2 P4 P6 P11 P15
Max in-memory 1 GB 2 GB 4 GB 8 GB
OLTP storage
* Max database size refers to the maximum size of the data in the database.
IMPORTANT
Customers using P11 and P15 performance levels can use up to 4 TB of included storage at no additional charge. This 4 TB
option is currently available in the following regions: US East2, West US, West Europe, South East Asia, Japan East, Australia
East, Canada Central, and Canada East.
Elastic pools
Elastic pools share resources across databases in the pool. The following table describes the characteristics of
Basic, Standard, Premium, and Premium RS elastic pools.
Basic elastic pool limits
POOL SIZE
(EDTUS) 50 100 200 300 400 800 1200 1600
Max In- N/A N/A N/A N/A N/A N/A N/A N/A
Memory
OLTP
storage
per pool*
Max In-Memory 1 GB 2 GB 4 GB 10 GB 12 GB
OLTP storage per
pool*
Max In-Memory 16 GB 20 GB 24 GB 28 GB 32 GB
OLTP storage per
pool*
Max In-Memory 1 GB 2 GB 4 GB 10 GB
OLTP storage per
pool*
IMPORTANT
* Pooled databases share pool storage, so data storage in an elastic pool is limited to the smaller of the remaining pool
storage or max storage per database.
For an expanded definition of each resource listed in the previous tables, see the descriptions in Service tier
capabilities and limits. For an overview of service tiers, see Azure SQL Database Service Tiers and Performance
Levels.
Other SQL Database limits
AREA LIMIT DESCRIPTION
Databases using Automated export per 10 Automated export allows you to create
subscription a custom schedule for backing up your
SQL databases. The preview of this
feature will end on March 1, 2017.
DTUs per server 45000 45000 DTUs are allowed per server for
provisioning standalone databases and
elastic pools. The total number of
standalone databases and pools
allowed per server is limited only by the
number of server DTUs.
IMPORTANT
Azure SQL Database Automated Export is now in preview and will be retired on March 1, 2017. Starting December 1st,
2016, you will no longer be able to configure automated export on any SQL database. All your existing automated export
jobs will continue to work until March 1st, 2017. After December 1st, 2016, you can use long-term backup retention or
Azure Automation to archive SQL databases periodically using PowerShell periodically according to a schedule of your
choice. For a sample script, you can download the sample script from GitHub.
Resources
Azure Subscription and Service Limits, Quotas, and Constraints
Azure SQL Database Service Tiers and Performance Levels
Error messages for SQL Database client programs
Choose a cloud SQL Server option: Azure SQL (PaaS)
Database or SQL Server on Azure VMs (IaaS)
4/14/2017 • 13 min to read • Edit Online
Azure has two options for hosting SQL Server workloads in Microsoft Azure:
Azure SQL Database: A SQL database native to the cloud, also known as a platform as a service (PaaS) database
or a database as a service (DBaaS) that is optimized for software-as-a-service (SaaS) app development. It offers
compatibility with most SQL Server features. For more information on PaaS, see What is PaaS.
SQL Server on Azure Virtual Machines: SQL Server installed and hosted in the cloud on Windows Server Virtual
Machines (VMs) running on Azure, also known as an infrastructure as a service (IaaS). SQL Server on Azure
virtual machines is optimized for migrating existing SQL Server applications. All the versions and editions of
SQL Server are available. It offers 100% compatibility with SQL Server, allowing you to host as many databases
as needed and executing cross-database transactions. It offers full control on SQL Server and Windows.
Learn how each option fits into the Microsoft data platform and get help matching the right option to your business
requirements. Whether you prioritize cost savings or minimal administration ahead of everything else, this article
can help you decide which approach delivers against the business requirements you care about most.
As seen in the diagram, each offering can be characterized by the level of administration you have over the
infrastructure (on the X axis), and by the degree of cost efficiency achieved by database level consolidation and
automation (on the Y axis).
When designing an application, four basic options are available for hosting the SQL Server part of the application:
SQL Server on non-virtualized physical machines
SQL Server in on-premises virtualized machines (private cloud)
SQL Server in Azure Virtual Machine (Microsoft public cloud)
Azure SQL Database (Microsoft public cloud)
In the following sections, you learn about SQL Server in the Microsoft public cloud: Azure SQL Database and SQL
Server on Azure VMs. In addition, you explore common business motivators for determining which option works
best for your application.
A closer look at Azure SQL Database and SQL Server on Azure VMs
Azure SQL Database is a relational database-as-a-service (DBaaS) hosted in the Azure cloud that falls into the
industry categories of Software-as-a-Service (SaaS) and Platform-as-a-Service (PaaS). SQL database is built on
standardized hardware and software that is owned, hosted, and maintained by Microsoft. With SQL Database, you
can develop directly on the service using built-in features and functionality. When using SQL Database, you pay-as-
you-go with options to scale up or out for greater power with no interruption.
SQL Server on Azure Virtual Machines (VMs) falls into the industry category Infrastructure-as-a-Service (IaaS)
and allows you to run SQL Server inside a virtual machine in the cloud. Similar to SQL Database, it is built on
standardized hardware that is owned, hosted, and maintained by Microsoft. When using SQL Server on a VM, you
can either pay-as you-go for a SQL Server license already included in a SQL Server image or easily use an existing
license. You can also easily scale-up/down and pause/resume the VM as needed.
In general, these two SQL options are optimized for different purposes:
Azure SQL Database is optimized to reduce overall costs to the minimum for provisioning and managing
many databases. It reduces ongoing administration costs because you do not have to manage any virtual
machines, operating system or database software. You do not have to manage upgrades, high availability, or
backups. In general, Azure SQL Database can dramatically increase the number of databases managed by a
single IT or development resource.
SQL Server running on Azure VMs is optimized for migrating existing applications to Azure or extending
existing on-premises applications to the cloud in hybrid deployments. In addition, you can use SQL Server in a
virtual machine to develop and test traditional SQL Server applications. With SQL Server on Azure VMs, you
have the full administrative rights over a dedicated SQL Server instance and a cloud-based VM. It is a perfect
choice when an organization already has IT resources available to maintain the virtual machines. These
capabilities allow you to build a highly customized system to address your application’s specific performance
and availability requirements.
The following table summarizes the main characteristics of SQL Database and SQL Server on Azure VMs:
Teams that need built-in high Teams that can configure and manage
availability, disaster recovery, and high availability, disaster recovery, and
upgrade for the database. patching for SQL Server. Some provided
automated features dramatically
simplify this.
SQL SERVER IN AN AZURE VIRTUAL
BEST FOR: AZURE SQL DATABASE MACHINE
Teams that do not want to manage the If you need a customized environment
underlying operating system and with full administrative rights.
configuration settings.
Resources: You do not want to employ IT resources You have some IT resources for
for configuration and management of configuration and management. Some
the underlying infrastructure, but want provided automated features
to focus on the application layer. dramatically simplify this.
Total cost of ownership: Eliminates hardware costs and reduces Eliminates hardware costs.
administrative costs.
Business continuity: In addition to built-in fault tolerance SQL Server on Azure VMs lets you set
infrastructure capabilities, Azure SQL up a high availability and disaster
Database provides features, such as recovery solution for your database’s
automated backups, Point-In-Time specific needs. Therefore, you can have
Restore, Geo-Restore, and Active Geo- a system that is highly optimized for
Replication to increase business your application. You can test and run
continuity. For more information, see failovers by yourself when needed. For
SQL Database business continuity more information, see High Availability
overview. and Disaster Recovery for SQL Server
on Azure Virtual Machines.
Hybrid cloud: Your on-premises application can access With SQL Server on Azure VMs, you can
data in Azure SQL Database. have applications that run partly in the
cloud and partly on-premises. For
example, you can extend your on-
premises network and Active Directory
Domain to the cloud via Azure Virtual
Network. In addition, you can store on-
premises data files in Azure Storage
using SQL Server Data Files in Azure.
For more information, see Introduction
to SQL Server 2014 Hybrid Cloud.
Administration
For many businesses, the decision to transition to a cloud service is as much about offloading complexity of
administration as it is cost. With SQL Database, Microsoft administers the underlying hardware. Microsoft
automatically replicates all data to provide high availability, configures and upgrades the database software,
manages load balancing, and does transparent failover if there is a server failure. You can continue to administer
your database, but you no longer need to manage the database engine, server operating system or hardware.
Examples of items you can continue to administer include databases and logins, index and query tuning, and
auditing and security.
With SQL Server on Azure VMs, you have full control over the operating system and SQL Server instance
configuration. With a VM, it’s up to you to decide when to update/upgrade the operating system and database
software and when to install any additional software such as anti-virus. Some automated features are provided to
dramatically simplify patching, backup, and high availability. In addition, you can control the size of the VM, the
number of disks, and their storage configurations. Azure allows you to change the size of a VM as needed. For
information, see Virtual Machine and Cloud Service Sizes for Azure.
Service Level Agreement (SLA )
For many IT departments, meeting up-time obligations of a Service Level Agreement (SLA) is a top priority. In this
section, we look at what SLA applies to each database hosting option.
For SQL Database Basic, Standard, Premium, and Premium RS service tiers Microsoft provides an availability SLA
of 99.99%. For the latest information, see Service Level Agreement. For the latest information on SQL Database
service tiers and the supported business continuity plans, see Service Tiers.
For SQL Server running on Azure VMs, Microsoft provides an availability SLA of 99.95% that covers just the
Virtual Machine. This SLA does not cover the processes (such as SQL Server) running on the VM and requires that
you host at least two VM instances in an availability set. For the latest information, see the VM SLA. For database
high availability (HA) within VMs, you should configure one of the supported high availability options in SQL
Server, such as AlwaysOn Availability Groups. Using a supported high availability option doesn't provide an
additional SLA, but allows you to achieve >99.99% database availability.
Time to market
SQL Database is the right solution for cloud-designed applications when developer productivity and fast time-to-
market are critical. With programmatic DBA-like functionality, it is perfect for cloud architects and developers as it
lowers the need for managing the underlying operating system and database. For example, you can use the REST
API and PowerShell Cmdlets to automate and manage administrative operations for thousands of databases.
Features such as elastic pools allow you to focus on the application layer and deliver your solution to the market
faster.
SQL Server running on Azure VMs is perfect if your existing or new applications require large databases,
interrelated databases, or access to all features in SQL Server or Windows. It is also a good fit when you want to
migrate existing on-premises applications and databases to Azure as-is. Since you do not need to change the
presentation, application, and data layers, you save time and budget on rearchitecting your existing solution.
Instead, you can focus on migrating all your solutions to Azure and in doing some performance optimizations that
may be required by the Azure platform. For more information, see Performance Best Practices for SQL Server on
Azure Virtual Machines.
Summary
This article explored SQL Database and SQL Server on Azure Virtual Machines (VMs) and discussed common
business motivators that might affect your decision. The following is a summary of suggestions for you to consider:
Choose Azure SQL Database if:
You are building new cloud-based applications to take advantage of the cost savings and performance
optimization that cloud services provide. This approach provides the benefits of a fully managed cloud service,
helps lower initial time-to-market, and can provide long-term cost optimization.
You want to have Microsoft perform common management operations on your databases and require stronger
availability SLAs for databases.
Choose SQL Server on Azure VMs if:
You have existing on-premises applications that you want to migrate or extend to the cloud, or if you want to
build enterprise applications larger than 1 TB. This approach provides the benefit of 100% SQL compatibility,
large database capacity, full control over SQL Server and Windows, and secure tunneling to on-premises. This
approach minimizes costs for development and modifications of existing applications.
You have existing IT resources and can ultimately own patching, backups, and database high availability. Notice
that some automated features dramatically simplify these operations.
Next steps
See Your first Azure SQL Database to get started with SQL Database.
See SQL Database pricing.
See Provision a SQL Server virtual machine in Azure to get started with SQL Server on Azure VMs.
Azure SQL Database features
4/14/2017 • 3 min to read • Edit Online
The following tables list the major features of Azure SQL Database and the equivalent features of SQL Server -
and providing information about whether each particular feature is supported and a link to more information
about the feature on each platform. For Transact-SQL differences to consider when migrating an existing
database solution, see Resolving Transact-SQL differences during migration to SQL Database.
We continue to add features to Azure SQL Database. So we encourage you to visit our Service Updates
webpage for Azure, and to use its filters:
Filtered to the SQL Database service.
Filtered to General Availability (GA) announcements for SQL Database features.
R Services Supported
SQL Server Analysis Services (SSAS) Supported Not supported - see Azure Analysis
Services
SQL Server Integration Services (SSIS) Supported Not supported - see Azure Data
Factory
Windows Server Failover Clustering Supported Not supported - See Active Geo-
Replication
Next steps
For information about the Azure SQL Database service, see What is SQL Database?
For information about Transact-SQL support and differences, see Resolving Transact-SQL differences during
migration to SQL Database.
Overview: Tools to manage & develop with Azure
SQL Database
4/14/2017 • 1 min to read • Edit Online
This topic introduces the tools for managing and developing with Azure SQL databases.
IMPORTANT
This documentation set includes QuickStarts, Sample, and How-to guides showing you how to management and develop
with Azure SQL Database using the tools introduced in the following paragraphs. Use the left-hand navigation pane and
filter box to find specific content for the Azure portal, PowerShell, and T-SQL.
Azure portal
The Azure portal is a web-based application where you can create, update, and delete databases and logical
servers and monitor database activity. This tool is great if you're just getting started with Azure, managing a few
databases, or need to do something quickly.
IMPORTANT
Always use the latest version of SQL Server Management Studio.
IMPORTANT
Always use the latest version of SQL Server Data Tools to remain synchronized with updates to Microsoft Azure and SQL
Database.
PowerShell
You can use PowerShell to manage databases and elastic pools, and to automate Azure resource deployments. Microsoft
recommends this tool for managing a large number of databases and automating deployment and resource changes in a
production environment.
Additional resources
Azure Resource Manager
Azure Automation
Azure Scheduler
Scaling out with Azure SQL Database
4/19/2017 • 6 min to read • Edit Online
You can easily scale out Azure SQL databases using the Elastic Database tools. These tools and features let you
use the virtually unlimited database resources of Azure SQL Database to create solutions for transactional
workloads, and especially Software as a Service (SaaS) applications. Elastic Database features are composed of
the following:
Elastic Database client library: The client library is a feature that allows you to create and maintain sharded
databases. See Get started with Elastic Database tools.
Elastic Database split-merge tool: moves data between sharded databases. This is useful for moving data from
a multi-tenant database to a single-tenant database (or vice-versa). See Elastic database Split-Merge tool
tutorial.
Elastic Database jobs (preview): Use jobs to manage large numbers of Azure SQL databases. Easily perform
administrative operations such as schema changes, credentials management, reference data updates,
performance data collection or tenant (customer) telemetry collection using jobs.
Elastic Database query (preview): Enables you to run a Transact-SQL query that spans multiple databases. This
enables connection to reporting tools such as Excel, PowerBI, Tableau, etc.
Elastic transactions: This feature allows you to run transactions that span several databases in Azure SQL
Database. Elastic database transactions are available for .NET applications using ADO .NET and integrate with
the familiar programming experience using the System.Transaction classes.
The graphic below shows an architecture that includes the Elastic Database features in relation to a collection
of databases.
In this graphic, colors of the database represent schemas. Databases with the same color share the same schema.
1. A set of Azure SQL databases are hosted on Azure using sharding architecture.
2. The Elastic Database client library is used to manage a shard set.
3. A subset of the databases are put into an elastic pool. (See What is a pool?).
4. An Elastic Database job runs scheduled or ad-hoc T-SQL scripts against all databases.
5. The split-merge tool is used to move data from one shard to another.
6. The Elastic Database query allows you to write a query that spans all databases in the shard set.
7. Elastic transactions allows you to run transactions that span several databases.
Why use the tools?
Achieving elasticity and scale for cloud applications has been straightforward for VMs and blob storage--simply
add or subtract units, or increase power. But it has remained a challenge for stateful data processing in relational
databases. Challenges emerged in these scenarios:
Growing and shrinking capacity for the relational database part of your workload.
Managing hotspots that may arise affecting a specific subset of data - such as a particularly busy end-
customer (tenant).
Traditionally, scenarios like these have been addressed by investing in larger-scale database servers to support
the application. However, this option is limited in the cloud where all processing happens on predefined
commodity hardware. Instead, distributing data and processing across many identically-structured databases (a
scale-out pattern known as "sharding") provides an alternative to traditional scale-up approaches both in terms
of cost and elasticity.
Sharding
Sharding is a technique to distribute large amounts of identically-structured data across a number of
independent databases. It is especially popular with cloud developers creating Software as a Service (SAAS)
offerings for end customers or businesses. These end customers are often referred to as “tenants”. Sharding may
be required for any number of reasons:
The total amount of data is too large to fit within the constraints of a single database
The transaction throughput of the overall workload exceeds the capabilities of a single database
Tenants may require physical isolation from each other, so separate databases are needed for each tenant
Different sections of a database may need to reside in different geographies for compliance, performance or
geopolitical reasons.
In other scenarios, such as ingestion of data from distributed devices, sharding can be used to fill a set of
databases that are organized temporally. For example, a separate database can be dedicated to each day or week.
In that case, the sharding key can be an integer representing the date (present in all rows of the sharded tables)
and queries retrieving information for a date range must be routed by the application to the subset of databases
covering the range in question.
Sharding works best when every transaction in an application can be restricted to a single value of a sharding
key. That ensures that all transactions will be local to a specific database.
Multi-tenant and single-tenant
Some applications use the simplest approach of creating a separate database for each tenant. This is the single
tenant sharding pattern that provides isolation, backup/restore ability and resource scaling at the granularity
of the tenant. With single tenant sharding, each database is associated with a specific tenant ID value (or
customer key value), but that key need not always be present in the data itself. It is the application’s responsibility
to route each request to the appropriate database - and the client library can simplify this.
Others scenarios pack multiple tenants together into databases, rather than isolating them into separate
databases. This is a typical multi-tenant sharding pattern - and it may be driven by the fact that an application
manages large numbers of very small tenants. In multi-tenant sharding, the rows in the database tables are all
designed to carry a key identifying the tenant ID or sharding key. Again, the application tier is responsible for
routing a tenant’s request to the appropriate database, and this can be supported by the elastic database client
library. In addition, row-level security can be used to filter which rows each tenant can access - for details, see
Multi-tenant applications with elastic database tools and row-level security. Redistributing data among databases
may be needed with the multi-tenant sharding pattern, and this is facilitated by the elastic database split-merge
tool. To learn more about design patterns for SaaS applications using elastic pools, see Design Patterns for Multi-
tenant SaaS Applications with Azure SQL Database.
Move data from multiple to single -tenancy databases
When creating a SaaS application, it is typical to offer prospective customers a trial version of the software. In this
case, it is cost-effective to use a multi-tenant database for the data. However, when a prospect becomes a
customer, a single-tenant database is better since it provides better performance. If the customer had created
data during the trial period, use the split-merge tool to move the data from the multi-tenant to the new single-
tenant database.
Next steps
For a sample app that demonstrates the client library, see Get started with Elastic Datababase tools.
To convert existing databases to use the tools, see Migrate existing databases to scale-out.
To see the specifics of the elastic pool, see Price and performance considerations for an elastic pool, or create a
new pool with elastic pools.
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For
questions, please reach out to us on the SQL Database forum and for feature requests, please add them to the
SQL Database feedback forum.
Building scalable cloud databases
1/17/2017 • 3 min to read • Edit Online
Scaling out databases can be easily accomplished using scalable tools and features for Azure SQL Database. In
particular, you can use the Elastic Database client library to create and manage scaled-out databases. This
feature lets you easily develop sharded applications using hundreds—or even thousands—of Azure SQL
databases. Elastic jobs can then be used to help ease management of these databases.
To install the library, go to Microsoft.Azure.SqlDatabase.ElasticScale.Client.
Documentation
1. Get started with Elastic Database tools
2. Elastic Database features
3. Shard map management
4. Migrate existing databases to scale-out
5. Data dependent routing
6. Multi-shard queries
7. Adding a shard using Elastic Database tools
8. Multi-tenant applications with elastic database tools and row-level security
9. Upgrade client library apps
10. Elastic queries overview
11. Elastic database tools glossary
12. Elastic Database client library with Entity Framework
13. Elastic database client library with Dapper
14. Split-merge tool
15. Performance counters for shard map manager
16. FAQ for Elastic database tools
Client capabilities
Scaling out applications using sharding presents challenges for both the developer as well as the administrator.
The client library simplifies the management tasks by providing tools that let both developers and
administrators manage scaled-out databases. In a typical example, there are many databases, known as "shards,"
to manage. Customers are co-located in the same database, and there is one database per customer (a single-
tenant scheme). The client library includes these features:
Shard Map Management: A special database called the "shard map manager" is created. Shard map
management is the ability for an application to manage metadata about its shards. Developers can use
this functionality to register databases as shards, describe mappings of individual sharding keys or key
ranges to those databases, and maintain this metadata as the number and composition of databases
evolves to reflect capacity changes. Without the elastic database client library, you would need to spend a
lot of time writing the management code when implementing sharding. For details, see Shard map
management.
Data dependent routing: Imagine a request coming into the application. Based on the sharding key
value of the request, the application needs to determine the correct database based on the key value. It
then opens a connection to the database to process the request. Data dependent routing provides the
ability to open connections with a single easy call into the shard map of the application. Data dependent
routing was another area of infrastructure code that is now covered by functionality in the elastic
database client library. For details, see Data dependent routing.
Multi-shard queries (MSQ): Multi-shard querying works when a request involves several (or all) shards. A
multi-shard query executes the same T-SQL code on all shards or a set of shards. The results from the
participating shards are merged into an overall result set using UNION ALL semantics. The functionality as
exposed through the client library handles many tasks, including: connection management, thread
management, fault handling and intermediate results processing. MSQ can query up to hundreds of shards.
For details, see Multi-shard querying.
In general, customers using elastic database tools can expect to get full T-SQL functionality when submitting
shard-local operations as opposed to cross-shard operations that have their own semantics.
Next steps
Try the sample app which demonstrates the client functions.
To install the library, go to Elastic Database Client Library.
For instructions on using the split-merge tool, see the split-merge tool overview.
Elastic database client library is now open sourced!
Use Elastic queries.
The library is available as open source software on GitHub.
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For
questions, please reach out to us on the SQL Database forum and for feature requests, please add them to the
SQL Database feedback forum.
Scale out databases with the shard map manager
1/23/2017 • 13 min to read • Edit Online
To easily scale out databases on SQL Azure, use a shard map manager. The shard map manager is a special
database that maintains global mapping information about all shards (databases) in a shard set. The metadata
allows an application to connect to the correct database based upon the value of the sharding key. In addition,
every shard in the set contains maps that track the local shard data (known as shardlets).
Understanding how these maps are constructed is essential to shard map management. This is done using the
ShardMapManager class, found in the Elastic Database client library to manage shard maps.
Or you can implement a multi-tenant database model using a list mapping to assign multiple tenants to a single
database. For example, DB1 is used to store information about tenant id 1 and 5, and DB2 stores data for tenant
7 and tenant 10.
1 Database_A
3 Database_B
4 Database_C
6 Database_B
... ...
[1,50) Database_A
[50,100) Database_B
[100,200) Database_C
[400,600) Database_C
... ...
Each of the tables shown above is a conceptual example of a ShardMap object. Each row is a simplified example
of an individual PointMapping (for the list shard map) or RangeMapping (for the range shard map) object.
Constructing a ShardMapManager
A ShardMapManager object is constructed using a factory pattern. The
ShardMapManagerFactory.GetSqlShardMapManager method takes credentials (including the server name
and database name holding the GSM) in the form of a ConnectionString and returns an instance of a
ShardMapManager.
Please Note: The ShardMapManager should be instantiated only once per app domain, within the
initialization code for an application. Creation of additional instances of ShardMapManager in the same
appdomain, will result in increased memory and CPU utilization of the application. A ShardMapManager can
contain any number of shard maps. While a single shard map may be sufficient for many applications, there are
times when different sets of databases are used for different schema or for unique purposes; in those cases
multiple shard maps may be preferable.
In this code, an application tries to open an existing ShardMapManager with the TryGetSqlShardMapManager
method. If objects representing a Global ShardMapManager (GSM) do not yet exist inside the database, the
client library creates them there using the CreateSqlShardMapManager method.
// Try to get a reference to the Shard Map Manager
// via the Shard Map Manager database.
// If it doesn't already exist, then create it.
ShardMapManager shardMapManager;
bool shardMapManagerExists = ShardMapManagerFactory.TryGetSqlShardMapManager(
connectionString,
ShardMapManagerLoadPolicy.Lazy,
out shardMapManager);
if (shardMapManagerExists)
{
Console.WriteLine("Shard Map Manager already exists");
}
else
{
// Create the Shard Map Manager.
ShardMapManagerFactory.CreateSqlShardMapManager(connectionString);
Console.WriteLine("Created SqlShardMapManager");
shardMapManager = ShardMapManagerFactory.GetSqlShardMapManager(
connectionString,
ShardMapManagerLoadPolicy.Lazy);
// The connectionString contains server name, database name, and admin credentials
// for privileges on both the GSM and the shards themselves.
}
As an alternative, you can use Powershell to create a new Shard Map Manager. An example is available here.
/// <summary>
/// Creates a new Range Shard Map with the specified name, or gets the Range Shard Map if it already exists.
/// </summary>
public static RangeShardMap<T> CreateOrGetRangeShardMap<T>(ShardMapManager shardMapManager, string shardMapName)
{
// Try to get a reference to the Shard Map.
RangeShardMap<T> shardMap;
bool shardMapExists = shardMapManager.TryGetRangeShardMap(shardMapName, out shardMap);
if (shardMapExists)
{
ConsoleUtils.WriteInfo("Shard Map {0} already exists", shardMap.Name);
}
else
{
// The Shard Map does not exist, so create it
shardMap = shardMapManager.CreateRangeShardMap<T>(shardMapName);
ConsoleUtils.WriteInfo("Created Shard Map {0}", shardMap.Name);
}
return shardMap;
}
if (!sm.TryGetShard(new ShardLocation(
shardServer,
"sample_shard_1"),
out shard1))
{
Shard1 = sm.CreateShard(new ShardLocation(
shardServer,
"sample_shard_1"));
}
RangeMapping<long> rmpg=null;
As an alternative you can use PowerShell scripts to achieve the same result. Some of the sample PowerShell
examples are available here.
Once shard maps have been populated, data access applications can be created or adapted to work with the
maps. Populating or manipulating the maps need not occur again until map layout needs to change.
sm.DeleteMapping(sm.MarkMappingOffline(sm.GetMappingForKey(25)));
Adding a shard
Applications often need to simply add new shards to handle data that is expected from new keys or key ranges,
for a shard map that already exists. For example, an application sharded by Tenant ID may need to provision a
new shard for a new tenant, or data sharded monthly may need a new shard provisioned before the start of each
new month.
If the new range of key values is not already part of an existing mapping and no data movement is necessary, it
is very simple to add the new shard and associate the new key or range to that shard. For details on adding new
shards, see Adding a new shard.
For scenarios that require data movement, however, the split-merge tool is needed to orchestrate the data
movement between shards in combination with the necessary shard map updates. For details on using the split-
merge yool, see Overview of split-merge
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For
questions, please reach out to us on the SQL Database forum and for feature requests, please add them to the
SQL Database feedback forum.
Data dependent routing
4/13/2017 • 5 min to read • Edit Online
Data dependent routing is the ability to use the data in a query to route the request to an appropriate
database. This is a fundamental pattern when working with sharded databases. The request context may also be
used to route the request, especially if the sharding key is not part of the query. Each specific query or transaction
in an application using data dependent routing is restricted to accessing a single database per request. For the
Azure SQL Database Elastic tools, this routing is accomplished with the ShardMapManager class in ADO.NET
applications.
The application does not need to track various connection strings or DB locations associated with different slices
of data in the sharded environment. Instead, the Shard Map Manager opens connections to the correct databases
when needed, based on the data in the shard map and the value of the sharding key that is the target of the
application’s request. The key is typically the customer_id, tenant_id, date_key, or some other specific identifier
that is a fundamental parameter of the database request).
For more information, see Scaling Out SQL Server with Data Dependent Routing.
Use lowest privilege credentials possible for getting the shard map
If an application is not manipulating the shard map itself, the credentials used in the factory method should have
just read-only permissions on the Global Shard Map database. These credentials are typically different from
credentials used to open connections to the shard map manager. See also Credentials used to access the Elastic
Database client library.
The key parameter is used as a lookup key into the shard map to determine the appropriate database for the
request.
The connectionString is used to pass only the user credentials for the desired connection. No database
name or server name are included in this connectionString since the method will determine the database and
server using the ShardMap.
The connectionOptions should be set to ConnectionOptions.Validate if an environment where shard
maps may change and rows may move to other databases as a result of split or merge operations. This
involves a brief query to the local shard map on the target database (not to the global shard map) before the
connection is delivered to the application.
If the validation against the local shard map fails (indicating that the cache is incorrect), the Shard Map Manager
will query the global shard map to obtain the new correct value for the lookup, update the cache, and obtain and
return the appropriate database connection.
Use ConnectionOptions.None only when shard mapping changes are not expected while an application is
online. In that case, the cached values can be assumed to always be correct, and the extra round-trip validation
call to the target database can be safely skipped. That reduces database traffic. The connectionOptions may
also be set via a value in a configuration file to indicate whether sharding changes are expected or not during a
period of time.
This example uses the value of an integer key CustomerID, using a ShardMap object named
customerShardMap.
// Connect to the shard for that customer ID. No need to call a SqlConnection
// constructor followed by the Open method.
using (SqlConnection conn = customerShardMap.OpenConnectionForKey(customerId,
Configuration.GetCredentialsConnectionString(), ConnectionOptions.Validate))
{
// Execute a simple command.
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = @"UPDATE Sales.Customer
SET PersonID = @newPersonID
WHERE CustomerID = @customerID";
cmd.Parameters.AddWithValue("@customerID", customerId);
cmd.Parameters.AddWithValue("@newPersonID", newPersonId);
cmd.ExecuteNonQuery();
}
The OpenConnectionForKey method returns a new already-open connection to the correct database.
Connections utilized in this way still take full advantage of ADO.Net connection pooling. As long as transactions
and requests can be satisfied by one shard at a time, this should be the only modification necessary in an
application already using ADO.Net.
The OpenConnectionForKeyAsync method is also available if your application makes use asynchronous
programming with ADO.Net. Its behavior is the data dependent routing equivalent of ADO.Net's
Connection.OpenAsync method.
Integrating with transient fault handling
A best practice in developing data access applications in the cloud is to ensure that transient faults are caught by
the app, and that the operations are retried several times before throwing an error. Transient fault handling for
cloud applications is discussed at Transient Fault Handling.
Transient fault handling can coexist naturally with the Data Dependent Routing pattern. The key requirement is to
retry the entire data access request including the using block that obtained the data-dependent routing
connection. The example above could be rewritten as follows (note highlighted change).
Example - data dependent routing with transient fault handling
Configuration.SqlRetryPolicy.ExecuteAction(() =>
{
// Connect to the shard for a customer ID.
using (SqlConnection conn = customerShardMap.OpenConnectionForKey(customerId,
Configuration.GetCredentialsConnectionString(), ConnectionOptions.Validate))
{
// Execute a simple command
SqlCommand cmd = conn.CreateCommand();
cmd.Parameters.AddWithValue("@customerID", customerId);
cmd.Parameters.AddWithValue("@newPersonID", newPersonId);
cmd.ExecuteNonQuery();
Console.WriteLine("Update completed");
}
});
Packages necessary to implement transient fault handling are downloaded automatically when you build the
elastic database sample application. Packages are also available separately at Enterprise Library - Transient Fault
Handling Application Block. Use version 6.0 or later.
Transactional consistency
Transactional properties are guaranteed for all operations local to a shard. For example, transactions submitted
through data-dependent routing execute within the scope of the target shard for the connection. At this time,
there are no capabilities provided for enlisting multiple connections into a transaction, and therefore there are no
transactional guarantees for operations performed across shards.
Next steps
To detach a shard, or to reattach a shard, see Using the RecoveryManager class to fix shard map problems
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For
questions, please reach out to us on the SQL Database forum and for feature requests, please add them to the
SQL Database feedback forum.
Credentials used to access the Elastic Database client
library
1/17/2017 • 3 min to read • Edit Online
The Elastic Database client library uses three different kinds of credentials to access the shard map manager.
Depending on the need, use the credential with the lowest level of access possible.
Management credentials: for creating or manipulating a shard map manager. (See the glossary.)
Access credentials: to access an existing shard map manager to obtain information about shards.
Connection credentials: to connect to shards.
See also Managing databases and logins in Azure SQL Database.
The variable smmAdminConnectionString is a connection string that contains the management credentials. The
user ID and password provides read/write access to both shard map database and individual shards. The
management connection string also includes the server name and database name to identify the global shard map
database. Here is a typical connection string for that purpose:
"Server=<yourserver>.database.windows.net;Database=<yourdatabase>;User ID=<yourmgmtusername>;Password=
<yourmgmtpassword>;Trusted_Connection=False;Encrypt=True;Connection Timeout=30;”
Do not use values in the form of "username@server"—instead just use the "username" value. This is because
credentials must work against both the shard map manager database and individual shards, which may be on
different servers.
Access credentials
When creating a shard map manager in an application that does not administer shard maps, use credentials that
have read-only permissions on the global shard map. The information retrieved from the global shard map under
these credentials are used for data-dependent routing and to populate the shard map cache on the client. The
credentials are provided through the same call pattern to GetSqlShardMapManager as shown above:
// Obtain shard map manager.
ShardMapManager shardMapManager = ShardMapManagerFactory.GetSqlShardMapManager(
smmReadOnlyConnectionString,
ShardMapManagerLoadPolicy.Lazy
);
Note the use of the smmReadOnlyConnectionString to reflect the use of different credentials for this access on
behalf of non-admin users: these credentials should not provide write permissions on the global shard map.
Connection credentials
Additional credentials are needed when using the OpenConnectionForKey method to access a shard associated
with a sharding key. These credentials need to provide permissions for read-only access to the local shard map
tables residing on the shard. This is needed to perform connection validation for data-dependent routing on the
shard. This code snippet allows data access in the context of data dependent routing:
In this example, smmUserConnectionString holds the connection string for the user credentials. For Azure SQL
DB, here is a typical connection string for user credentials:
As with the admin credentials, do not values in the form of "username@server". Instead, just use "username". Also
note that the connection string does not contain a server name and database name. That is because the
OpenConnectionForKey call will automatically direct the connection to the correct shard based on the key.
Hence, the database name and server name are not provided.
See also
Managing databases and logins in Azure SQL Database
Securing your SQL Database
Getting started with Elastic Database jobs
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For questions,
please reach out to us on the SQL Database forum and for feature requests, please add them to the SQL Database
feedback forum.
Multi-shard querying
1/23/2017 • 2 min to read • Edit Online
Overview
With the Elastic Database tools, you can create sharded database solutions. Multi-shard querying is used for
tasks such as data collection/reporting that require running a query that stretches across several shards. (Contrast
this to data-dependent routing, which performs all work on a single shard.)
1. Get a RangeShardMap or ListShardMap using the TryGetRangeShardMap, the TryGetListShardMap, or
the GetShardMap method. See Constructing a ShardMapManager and Get a RangeShardMap or
ListShardMap.
2. Create a MultiShardConnection object.
3. Create a MultiShardCommand.
4. Set the CommandText property to a T-SQL command.
5. Execute the command by calling the ExecuteReader method.
6. View the results using the MultiShardDataReader class.
Example
The following code illustrates the usage of multi-shard querying using a given ShardMap named myShardMap.
A key difference is the construction of multi-shard connections. Where SqlConnection operates on a single
database, the MultiShardConnection takes a collection of shards as its input. Populate the collection of shards
from a shard map. The query is then executed on the collection of shards using UNION ALL semantics to
assemble a single overall result. Optionally, the name of the shard where the row originates from can be added to
the output using the ExecutionOptions property on command.
Note the call to myShardMap.GetShards(). This method retrieves all shards from the shard map and provides an
easy way to run a query across all relevant databases. The collection of shards for a multi-shard query can be
refined further by performing a LINQ query over the collection returned from the call to
myShardMap.GetShards(). In combination with the partial results policy, the current capability in multi-shard
querying has been designed to work well for tens up to hundreds of shards.
A limitation with multi-shard querying is currently the lack of validation for shards and shardlets that are queried.
While data-dependent routing verifies that a given shard is part of the shard map at the time of querying, multi-
shard queries do not perform this check. This can lead to multi-shard queries running on databases that have been
removed from the shard map.
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For questions,
please reach out to us on the SQL Database forum and for feature requests, please add them to the SQL Database
feedback forum.
See also
System.Data.SqlClient classes and methods.
Manage shards using the Elastic Database client library. Includes a namespace called
Microsoft.Azure.SqlDatabase.ElasticScale.Query that provides the ability to query multiple shards using a single
query and result. It provides a querying abstraction over a collection of shards. It also provides alternative
execution policies, in particular partial results, to deal with failures when querying over many shards.
Elastic Database tools glossary
1/17/2017 • 2 min to read • Edit Online
The following terms are defined for the Elastic Database tools, a feature of Azure SQL Database. The tools are used
to manage shard maps, and include the client library, the split-merge tool, elastic pools, and queries.
These terms are used in Adding a shard using Elastic Database tools and Using the RecoveryManager class to fix
shard map problems.
Range shard map: A shard map in which the shard distribution strategy is based on multiple ranges of
contiguous values.
Reference tables: Tables that are not sharded but are replicated across shards. For example, zip codes can be
stored in a reference table.
Shard: An Azure SQL database that stores data from a sharded data set.
Shard elasticity: The ability to perform both horizontal scaling and vertical scaling.
Sharded tables: Tables that are sharded, i.e., whose data is distributed across shards based on their sharding key
values.
Sharding key: A column value that determines how data is distributed across shards. The value type can be one
of the following: int, bigint, varbinary, or uniqueidentifier.
Shard set: The collection of shards that are attributed to the same shard map in the shard map manager.
Shardlet: All of the data associated with a single value of a sharding key on a shard. A shardlet is the smallest unit
of data movement possible when redistributing sharded tables.
Shard map: The set of mappings between sharding keys and their respective shards.
Shard map manager: A management object and data store that contains the shard map(s), shard locations, and
mappings for one or more shard sets.
Verbs
Horizontal scaling: The act of scaling out (or in) a collection of shards by adding or removing shards to a shard
map, as shown below.
Merge: The act of moving shardlets from two shards to one shard and updating the shard map accordingly.
Shardlet move: The act of moving a single shardlet to a different shard.
Shard: The act of horizontally partitioning identically structured data across multiple databases based on a
sharding key.
Split: The act of moving several shardlets from one shard to another (typically new) shard. A sharding key is
provided by the user as the split point.
Vertical Scaling: The act of scaling up (or down) the performance level of an individual shard. For example,
changing a shard from Standard to Premium (which results in more computing resources).
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For questions,
please reach out to us on the SQL Database forum and for feature requests, please add them to the SQL Database
feedback forum.
Moving data between scaled-out cloud databases
1/17/2017 • 18 min to read • Edit Online
If you are a Software as a Service developer, and suddenly your app undergoes tremendous demand, you need
to accommodate the growth. So you add more databases (shards). How do you redistribute the data to the new
databases without disrupting the data integrity? Use the split-merge tool to move data from constrained
databases to the new databases.
The split-merge tool runs as an Azure web service. An administrator or developer uses the tool to move
shardlets (data from a shard) between different databases (shards). The tool uses shard map management to
maintain the service metadata database, and ensure consistent mappings.
Download
Microsoft.Azure.SqlDatabase.ElasticScale.Service.SplitMerge
Documentation
1. Elastic database Split-Merge tool tutorial
2. Split-Merge security configuration
3. Split-merge security considerations
4. Shard map management
5. Migrate existing databases to scale-out
6. Elastic database tools
7. Elastic Database tools glossary
// Reference tables
schemaInfo.Add(new ReferenceTableInfo("dbo", "region"));
schemaInfo.Add(new ReferenceTableInfo("dbo", "nation"));
// Sharded tables
schemaInfo.Add(new ShardedTableInfo("dbo", "customer", "C_CUSTKEY"));
schemaInfo.Add(new ShardedTableInfo("dbo", "orders", "O_CUSTKEY"));
// Publish
smm.GetSchemaInfoCollection().Add(Configuration.ShardMapName, schemaInfo);
The tables ‘region’ and ‘nation’ are defined as reference tables and will be copied with split/merge/move
operations. ‘customer’ and ‘orders’ in turn are defined as sharded tables. C_CUSTKEY and O_CUSTKEY serve as
the sharding key.
Referential Integrity
The split-merge service analyzes dependencies between tables and uses foreign key-primary key relationships
to stage the operations for moving reference tables and shardlets. In general, reference tables are copied first in
dependency order, then shardlets are copied in order of their dependencies within each batch. This is necessary
so that FK-PK constraints on the target shard are honored as the new data arrives.
Shard Map Consistency and Eventual Completion
In the presence of failures, the split-merge service resumes operations after any outage and aims to complete
any in progress requests. However, there may be unrecoverable situations, e.g., when the target shard is lost or
compromised beyond repair. Under those circumstances, some shardlets that were supposed to be moved may
continue to reside on the source shard. The service ensures that shardlet mappings are only updated after the
necessary data has been successfully copied to the target. Shardlets are only deleted on the source once all their
data has been copied to the target and the corresponding mappings have been updated successfully. The
deletion operation happens in the background while the range is already online on the target shard. The split-
merge service always ensures correctness of the mappings stored in the shard map.
Billing
The split-merge service runs as a cloud service in your Microsoft Azure subscription. Therefore charges for
cloud services apply to your instance of the service. Unless you frequently perform split/merge/move
operations, we recommend you delete your split-merge cloud service. That saves costs for running or deployed
cloud service instances. You can re-deploy and start your readily runnable configuration whenever you need to
perform split or merge operations.
Monitoring
Status tables
The split-merge Service provides the RequestStatus table in the metadata store database for monitoring of
completed and ongoing requests. The table lists a row for each split-merge request that has been submitted to
this instance of the split-merge service. It gives the following information for each request:
Timestamp: The time and date when the request was started.
OperationId: A GUID that uniquely identifies the request. This request can also be used to cancel the
operation while it is still ongoing.
Status: The current state of the request. For ongoing requests, it also lists the current phase in which the
request is.
CancelRequest: A flag that indicates whether the request has been cancelled.
Progress: A percentage estimate of completion for the operation. A value of 50 indicates that the operation
is approximately 50% complete.
Details: An XML value that provides a more detailed progress report. The progress report is periodically
updated as sets of rows are copied from source to target. In case of failures or exceptions, this column also
includes more detailed information about the failure.
Azure Diagnostics
The split-merge service uses Azure Diagnostics based on Azure SDK 2.5 for monitoring and diagnostics. You
control the diagnostics configuration as explained here: Enabling Diagnostics in Azure Cloud Services and
Virtual Machines. The download package includes two diagnostics configurations - one for the web role and one
for the worker role. These diagnostics configurations for the service follow the guidance from Cloud Service
Fundamentals in Microsoft Azure. It includes the definitions to log Performance Counters, IIS logs, Windows
Event Logs, and split-merge application event logs.
Deploy Diagnostics
To enable monitoring and diagnostics using the diagnostic configuration for the web and worker roles provided
by the NuGet package, run the following commands using Azure PowerShell:
$storage_name = "<YourAzureStorageAccount>"
$key = "<YourAzureStorageAccountKey"
$config_path = "<YourFilePath>\SplitMergeWebContent.diagnostics.xml"
$service_name = "<YourCloudServiceName>"
$config_path = "<YourFilePath>\SplitMergeWorkerContent.diagnostics.xml"
$service_name = "<YourCloudServiceName>"
You can find more information on how to configure and deploy diagnostics settings here: Enabling Diagnostics
in Azure Cloud Services and Virtual Machines.
Retrieve diagnostics
You can easily access your diagnostics from the Visual Studio Server Explorer in the Azure part of the Server
Explorer tree. Open a Visual Studio instance, and in the menu bar click View, and Server Explorer. Click the Azure
icon to connect to your Azure subscription. Then navigate to Azure -> Storage -> -> Tables -> WADLogsTable.
For more information, see Browsing Storage Resources with Server Explorer.
The WADLogsTable highlighted in the figure above contains the detailed events from the split-merge service’s
application log. Note that the default configuration of the downloaded package is geared towards a production
deployment. Therefore the interval at which logs and counters are pulled from the service instances is large (5
minutes). For test and development, lower the interval by adjusting the diagnostics settings of the web or the
worker role to your needs. Right-click on the role in the Visual Studio Server Explorer (see above) and then
adjust the Transfer Period in the dialog for the Diagnostics configuration settings:
Performance
In general, better performance is to be expected from the higher, more performant service tiers in Azure SQL
Database. Higher IO, CPU and memory allocations for the higher service tiers benefit the bulk copy and delete
operations that the split-merge service uses. For that reason, increase the service tier just for those databases
for a defined, limited period of time.
The service also performs validation queries as part of its normal operations. These validation queries check for
unexpected presence of data in the target range and ensure that any split/merge/move operation starts from a
consistent state. These queries all work over sharding key ranges defined by the scope of the operation and the
batch size provided as part of the request definition. These queries perform best when an index is present that
has the sharding key as the leading column.
In addition, a uniqueness property with the sharding key as the leading column will allow the service to use an
optimized approach that limits resource consumption in terms of log space and memory. This uniqueness
property is required to move large data sizes (typically above 1GB).
How to upgrade
1. Follow the steps in Deploy a split-merge service.
2. Change your cloud service configuration file for your split-merge deployment to reflect the new
configuration parameters. A new required parameter is the information about the certificate used for
encryption. An easy way to do this is to compare the new configuration template file from the download
against your existing configuration. Make sure you add the settings for
“DataEncryptionPrimaryCertificateThumbprint” and “DataEncryptionPrimary” for both the web and the
worker role.
3. Before deploying the update to Azure, ensure that all currently running split-merge operations have finished.
You can easily do this by querying the RequestStatus and PendingWorkflows tables in the split-merge
metadata database for ongoing requests.
4. Update your existing cloud service deployment for split-merge in your Azure subscription with the new
package and your updated service configuration file.
You do not need to provision a new metadata database for split-merge to upgrade. The new version will
automatically upgrade your existing metadata database to the new version.
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For
questions, please reach out to us on the SQL Database forum and for feature requests, please add them to the
SQL Database feedback forum.
Elastic database tools FAQ
1/17/2017 • 2 min to read • Edit Online
If I have a single-tenant per shard and no sharding key, how do I populate the sharding key for the schema info?
The schema info object is only used to split merge scenarios. If an application is inherently single-tenant, then it
does not require the Split Merge tool and thus there is no need to populate the schema info object.
I’ve provisioned a database and I already have a Shard Map Manager, how do I register this new database as a shard?
Please see Adding a shard to an application using the elastic database client library.
How much do elastic database tools cost?
Using the elastic database client library does not incur any costs. Costs accrue only for the Azure SQL databases
that you use for shards and the Shard Map Manager, as well as the web/worker roles you provision for the Split
Merge tool.
Why are my credentials not working when I add a shard from a different server?
Do not use credentials in the form of “User ID=username@servername”, instead simply use “User ID = username”.
Also, be sure that the “username” login has permissions on the shard.
Do I need to create a Shard Map Manager and populate shards every time I start my applications?
No—the creation of the Shard Map Manager (for example,
ShardMapManagerFactory.CreateSqlShardMapManager) is a one-time operation. Your application should use
the call ShardMapManagerFactory.TryGetSqlShardMapManager() at application start-up time. There should
only one such call per application domain.
I have questions about using elastic database tools, how do I get them answered?
Please reach out to us on the Azure SQL Database forum.
When I get a database connection using a sharding key, I can still query data for other sharding keys on the same shard. Is this by
design?
The Elastic Scale APIs give you a connection to the correct database for your sharding key, but do not provide
sharding key filtering. Add WHERE clauses to your query to restrict the scope to the provided sharding key, if
necessary.
Can I use a different Azure Database edition for each shard in my shard set?
Yes, a shard is an individual database, and thus one shard could be a Premium edition while another be a Standard
edition. Further, the edition of a shard can scale up or down multiple times during the lifetime of the shard.
Does the Split Merge tool provision (or delete) a database during a split or merge operation?
No. For split operations, the target database must exist with the appropriate schema and be registered with the
Shard Map Manager. For merge operations, you must delete the shard from the shard map manager and then
delete the database.
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For questions,
please reach out to us on the SQL Database forum and for feature requests, please add them to the SQL Database
feedback forum.
Azure SQL Database elastic query overview
(preview)
2/21/2017 • 9 min to read • Edit Online
The elastic query feature (in preview) enables you to run a Transact-SQL query that spans multiple databases in
Azure SQL Database. It allows you to perform cross-database queries to access remote tables, and to connect
Microsoft and third party tools (Excel, PowerBI, Tableau, etc.) to query across data tiers with multiple databases.
Using this feature, you can scale out queries to large data tiers in SQL Database and visualize the results in
business intelligence (BI) reports.
NOTE
Elastic query works best for occasional reporting scenarios where most of the processing can be performed on the data
tier. For heavy reporting workloads or data warehousing scenarios with more complex queries, also consider using Azure
SQL Data Warehouse.
IMPORTANT
You must possess ALTER ANY EXTERNAL DATA SOURCE permission. This permission is included with the ALTER
DATABASE permission. ALTER ANY EXTERNAL DATA SOURCE permissions are needed to refer to the underlying data
source.
Reference data: The topology is used for reference data management. In the figure below, two tables (T1 and
T2) with reference data are kept on a dedicated database. Using an elastic query, you can now access tables T1
and T2 remotely from other databases, as shown in the figure. Use topology 1 if reference tables are small or
remote queries into reference table have selective predicates.
Figure 2 Vertical partitioning - Using elastic query to query reference data
Cross-database querying: Elastic queries enable use cases that require querying across several SQL databases.
Figure 3 shows four different databases: CRM, Inventory, HR and Products. Queries performed in one of the
databases also need access to one or all the other databases. Using an elastic query, you can configure your
database for this case by running a few simple DDL statements on each of the four databases. After this one-
time configuration, access to a remote table is as simple as referring to a local table from your T-SQL queries or
from your BI tools. This approach is recommended if the remote queries do not return large results.
Figure 3 Vertical partitioning - Using elastic query to query across various databases
The following steps configure elastic database queries for vertical partitioning scenarios that require access to a
table located on remote SQL databases with the same schema:
CREATE MASTER KEY mymasterkey
CREATE DATABASE SCOPED CREDENTIAL mycredential
CREATE/DROP EXTERNAL DATA SOURCE mydatasource of type RDBMS
CREATE/DROP EXTERNAL TABLE mytable
After running the DDL statements, you can access the remote table “mytable” as though it were a local table.
Azure SQL Database automatically opens a connection to the remote database, processes your request on the
remote database, and returns the results.
T-SQL querying
Once you have defined your external data sources and your external tables, you can use regular SQL Server
connection strings to connect to the databases where you defined your external tables. You can then run T-SQL
statements over your external tables on that connection with the limitations outlined below. You can find more
information and examples of T-SQL queries in the documentation topics for horizontal partitioning and vertical
partitioning.
IMPORTANT
Authentication using Azure Active Directory with elastic queries is not currently supported.
Cost
Elastic query is included into the cost of Azure SQL Database databases. Note that topologies where your remote
databases are in a different data center than the elastic query endpoint are supported, but data egress from
remote databases are charged regular Azure rates.
Preview limitations
Running your first elastic query can take up to a few minutes on the Standard performance tier. This time is
necessary to load the elastic query functionality; loading performance improves with higher performance
tiers.
Scripting of external data sources or external tables from SSMS or SSDT is not yet supported.
Import/Export for SQL DB does not yet support external data sources and external tables. If you need to use
Import/Export, drop these objects before exporting and then re-create them after importing.
Elastic query currently only supports read-only access to external tables. You can, however, use full T-SQL
functionality on the database where the external table is defined. This can be useful to, e.g., persist temporary
results using, e.g., SELECT INTO , or to define stored procedures on the elastic query database which refer to
external tables.
Except for nvarchar(max), LOB types are not supported in external table definitions. As a workaround, you can
create a view on the remote database that casts the LOB type into nvarchar(max), define your external table
over the view instead of the base table and then cast it back into the original LOB type in your queries.
Column statistics over external tables are currently not supported. Tables statistics are supported, but need to
be created manually.
Feedback
Please share feedback on your experience with elastic queries with us on Disqus below, the MSDN forums, or on
Stackoverflow. We are interested in all kinds of feedback about the service (defects, rough edges, feature gaps).
Next steps
For a vertical partitioning tutorial, see Getting started with cross-database query (vertical partitioning).
For syntax and sample queries for vertically partitioned data, see Querying vertically partitioned data)
For a horizontal partitioning (sharding) tutorial, see Getting started with elastic query for horizontal
partitioning (sharding).
For syntax and sample queries for horizontally partitioned data, see Querying horizontally partitioned data)
See sp_execute _remote for a stored procedure that executes a Transact-SQL statement on a single remote
Azure SQL Database or set of databases serving as shards in a horizontal partitioning scheme.
Reporting across scaled-out cloud databases
(preview)
2/21/2017 • 7 min to read • Edit Online
Sharded databases distribute rows across a scaled out data tier. The schema is identical on all participating
databases, also known as horizontal partitioning. Using an elastic query, you can create reports that span all
databases in a sharded database.
For a quick start, see Reporting across scaled-out cloud databases.
For non-sharded databases, see Query across cloud databases with different schemas.
Prerequisites
Create a shard map using the elastic database client library. see Shard map management. Or use the sample
app in Get started with elastic database tools.
Alternatively, see Migrate existing databases to scaled-out databases.
The user must possess ALTER ANY EXTERNAL DATA SOURCE permission. This permission is included with the
ALTER DATABASE permission.
ALTER ANY EXTERNAL DATA SOURCE permissions are needed to refer to the underlying data source.
Overview
These statements create the metadata representation of your sharded data tier in the elastic query database.
1. CREATE MASTER KEY
2. CREATE DATABASE SCOPED CREDENTIAL
3. CREATE EXTERNAL DATA SOURCE
4. CREATE EXTERNAL TABLE
NOTE
Make sure that the "<username>" does not include any "@servername" suffix.
<External_Data_Source> ::=
CREATE EXTERNAL DATA SOURCE <data_source_name> WITH
(TYPE = SHARD_MAP_MANAGER,
LOCATION = '<fully_qualified_server_name>',
DATABASE_NAME = ‘<shardmap_database_name>',
CREDENTIAL = <credential_name>,
SHARD_MAP_NAME = ‘<shardmapname>’
) [;]
Example
The external data source references your shard map. An elastic query then uses the external data source and the
underlying shard map to enumerate the databases that participate in the data tier. The same credentials are used
to read the shard map and to access the data on the shards during the processing of an elastic query.
<sharded_external_table_options> ::=
DATA_SOURCE = <External_Data_Source>,
[ SCHEMA_NAME = N'nonescaped_schema_name',]
[ OBJECT_NAME = N'nonescaped_object_name',]
DISTRIBUTION = SHARDED(<sharding_column_name>) | REPLICATED |ROUND_ROBIN
Example
WITH
(
DATA_SOURCE = MyExtSrc,
SCHEMA_NAME = 'orders',
OBJECT_NAME = 'order_details',
DISTRIBUTION=SHARDED(ol_w_id)
);
Remarks
The DATA_SOURCE clause defines the external data source (a shard map) that is used for the external table.
The SCHEMA_NAME and OBJECT_NAME clauses map the external table definition to a table in a different schema.
If omitted, the schema of the remote object is assumed to be “dbo” and its name is assumed to be identical to the
external table name being defined. This is useful if the name of your remote table is already taken in the database
where you want to create the external table. For example, you want to define an external table to get an aggregate
view of catalog views or DMVs on your scaled out data tier. Since catalog views and DMVs already exist locally,
you cannot use their names for the external table definition. Instead, use a different name and use the catalog
view’s or the DMV’s name in the SCHEMA_NAME and/or OBJECT_NAME clauses. (See the example below.)
The DISTRIBUTION clause specifies the data distribution used for this table. The query processor utilizes the
information provided in the DISTRIBUTION clause to build the most efficient query plans.
1. SHARDED means data is horizontally partitioned across the databases. The partitioning key for the data
distribution is the parameter.
2. REPLICATED means that identical copies of the table are present on each database. It is your responsibility to
ensure that the replicas are identical across the databases.
3. ROUND_ROBIN means that the table is horizontally partitioned using an application-dependent distribution
method.
Data tier reference: The external table DDL refers to an external data source. The external data source specifies a
shard map which provides the external table with the information necessary to locate all the databases in your
data tier.
Security considerations
Users with access to the external table automatically gain access to the underlying remote tables under the
credential given in the external data source definition. Avoid undesired elevation of privileges through the
credential of the external data source. Use GRANT or REVOKE for an external table just as though it were a regular
table.
Once you have defined your external data source and your external tables, you can now use full T-SQL over your
external tables.
select
w_id as warehouse,
o_c_id as customer,
count(*) as cnt_orderline,
max(ol_quantity) as max_quantity,
avg(ol_amount) as avg_amount,
min(ol_delivery_d) as min_deliv_date
from warehouse
join orders
on w_id = o_w_id
join order_line
on o_id = ol_o_id and o_w_id = ol_w_id
where w_id > 100 and w_id < 200
group by w_id, o_c_id
EXEC sp_execute_remote
N'MyExtSrc',
N'select count(w_id) as foo from warehouse'
Best practices
Ensure that the elastic query endpoint database has been given access to the shardmap database and all
shards through the SQL DB firewalls.
Validate or enforce the data distribution defined by the external table. If your actual data distribution is
different from the distribution specified in your table definition, your queries may yield unexpected results.
Elastic query currently does not perform shard elimination when predicates over the sharding key would allow
it to safely exclude certain shards from processing.
Elastic query works best for queries where most of the computation can be done on the shards. You typically
get the best query performance with selective filter predicates that can be evaluated on the shards or joins
over the partitioning keys that can be performed in a partition-aligned way on all shards. Other query patterns
may need to load large amounts of data from the shards to the head node and may perform poorly
Next steps
For an overview of elastic query, see Elastic query overview.
For a vertical partitioning tutorial, see Getting started with cross-database query (vertical partitioning).
For syntax and sample queries for vertically partitioned data, see Querying vertically partitioned data)
For a horizontal partitioning (sharding) tutorial, see Getting started with elastic query for horizontal
partitioning (sharding).
See sp_execute _remote for a stored procedure that executes a Transact-SQL statement on a single remote
Azure SQL Database or set of databases serving as shards in a horizontal partitioning scheme.
Query across cloud databases with different schemas
(preview)
2/21/2017 • 6 min to read • Edit Online
Vertically-partitioned databases use different sets of tables on different databases. That means that the schema is
different on different databases. For instance, all tables for inventory are on one database while all accounting-
related tables are on a second database.
Prerequisites
The user must possess ALTER ANY EXTERNAL DATA SOURCE permission. This permission is included with the
ALTER DATABASE permission.
ALTER ANY EXTERNAL DATA SOURCE permissions are needed to refer to the underlying data source.
Overview
NOTE
Unlike with horizontal partitioning, these DDL statements do not depend on defining a data tier with a shard map through
the elastic database client library.
NOTE
Ensure that the <username> does not include any "@servername" suffix.
<External_Data_Source> ::=
CREATE EXTERNAL DATA SOURCE <data_source_name> WITH
(TYPE = RDBMS,
LOCATION = ’<fully_qualified_server_name>’,
DATABASE_NAME = ‘<remote_database_name>’,
CREDENTIAL = <credential_name>
) [;]
IMPORTANT
The TYPE parameter must be set to RDBMS.
Example
The following example illustrates the use of the CREATE statement for external data sources.
External Tables
Syntax:
CREATE EXTERNAL TABLE [ database_name . [ schema_name ] . | schema_name . ] table_name
( { <column_definition> } [ ,...n ])
{ WITH ( <rdbms_external_table_options> ) }
)[;]
<rdbms_external_table_options> ::=
DATA_SOURCE = <External_Data_Source>,
[ SCHEMA_NAME = N'nonescaped_schema_name',]
[ OBJECT_NAME = N'nonescaped_object_name',]
Example
The following example shows how to retrieve the list of external tables from the current database:
Remarks
Elastic query extends the existing external table syntax to define external tables that use external data sources of
type RDBMS. An external table definition for vertical partitioning covers the following aspects:
Schema: The external table DDL defines a schema that your queries can use. The schema provided in your
external table definition needs to match the schema of the tables in the remote database where the actual data
is stored.
Remote database reference: The external table DDL refers to an external data source. The external data
source specifies the logical server name and database name of the remote database where the actual table
data is stored.
Using an external data source as outlined in the previous section, the syntax to create external tables is as follows:
The DATA_SOURCE clause defines the external data source (i.e. the remote database in case of vertical
partitioning) that is used for the external table.
The SCHEMA_NAME and OBJECT_NAME clauses provide the ability to map the external table definition to a table
in a different schema on the remote database, or to a table with a different name, respectively. This is useful if you
want to define an external table to a catalog view or DMV on your remote database - or any other situation where
the remote table name is already taken locally.
The following DDL statement drops an existing external table definition from the local catalog. It does not impact
the remote database.
Permissions for CREATE/DROP EXTERNAL TABLE: ALTER ANY EXTERNAL DATA SOURCE permissions are
needed for external table DDL which is also needed to refer to the underlying data source.
Security considerations
Users with access to the external table automatically gain access to the underlying remote tables under the
credential given in the external data source definition. You should carefully manage access to the external table in
order to avoid undesired elevation of privileges through the credential of the external data source. Regular SQL
permissions can be used to GRANT or REVOKE access to an external table just as though it were a regular table.
SELECT
c_id as customer,
c_lastname as customer_name,
count(*) as cnt_orderline,
max(ol_quantity) as max_quantity,
avg(ol_amount) as avg_amount,
min(ol_delivery_d) as min_deliv_date
FROM customer
JOIN orders
ON c_id = o_c_id
JOIN order_line
ON o_id = ol_o_id and o_c_id = ol_c_id
WHERE c_id = 100
EXEC sp_execute_remote
N'MyExtSrc',
N'select count(w_id) as foo from warehouse'
Best practices
Ensure that the elastic query endpoint database has been given access to the remote database by enabling
access for Azure Services in its SQL DB firewall configuration. Also ensure that the credential provided in the
external data source definition can successfully log into the remote database and has the permissions to access
the remote table.
Elastic query works best for queries where most of the computation can be done on the remote databases. You
typically get the best query performance with selective filter predicates that can be evaluated on the remote
databases or joins that can be performed completely on the remote database. Other query patterns may need
to load large amounts of data from the remote database and may perform poorly.
Next steps
For an overview of elastic query, see Elastic query overview.
For a vertical partitioning tutorial, see Getting started with cross-database query (vertical partitioning).
For a horizontal partitioning (sharding) tutorial, see Getting started with elastic query for horizontal
partitioning (sharding).
For syntax and sample queries for horizontally partitioned data, see Querying horizontally partitioned data)
See sp_execute _remote for a stored procedure that executes a Transact-SQL statement on a single remote
Azure SQL Database or set of databases serving as shards in a horizontal partitioning scheme.
Distributed transactions across cloud databases
4/10/2017 • 7 min to read • Edit Online
Elastic database transactions for Azure SQL Database (SQL DB) allow you to run transactions that span several
databases in SQL DB. Elastic database transactions for SQL DB are available for .NET applications using ADO .NET
and integrate with the familiar programming experience using the System.Transaction classes. To get the library,
see .NET Framework 4.6.1 (Web Installer).
On premises, such a scenario usually required running Microsoft Distributed Transaction Coordinator (MSDTC).
Since MSDTC is not available for Platform-as-a-Service application in Azure, the ability to coordinate distributed
transactions has now been directly integrated into SQL DB. Applications can connect to any SQL Database to
launch distributed transactions, and one of the databases will transparently coordinate the distributed transaction,
as shown in the following figure.
Common scenarios
Elastic database transactions for SQL DB enable applications to make atomic changes to data stored in several
different SQL Databases. The preview focuses on client-side development experiences in C# and .NET. A server-
side experience using T-SQL is planned for a later time.
Elastic database transactions targets the following scenarios:
Multi-database applications in Azure: With this scenario, data is vertically partitioned across several databases
in SQL DB such that different kinds of data reside on different databases. Some operations require changes to
data which is kept in two or more databases. The application uses elastic database transactions to coordinate
the changes across databases and ensure atomicity.
Sharded database applications in Azure: With this scenario, the data tier uses the Elastic Database client library
or self-sharding to horizontally partition the data across many databases in SQL DB. One prominent use case is
the need to perform atomic changes for a sharded multi-tenant application when changes span tenants. Think
for instance of a transfer from one tenant to another, both residing on different databases. A second case is
fine-grained sharding to accommodate capacity needs for a large tenant which in turn typically implies that
some atomic operations needs to stretch across several databases used for the same tenant. A third case is
atomic updates to reference data that are replicated across databases. Atomic, transacted, operations along
these lines can now be coordinated across several databases using the preview. Elastic database transactions
use two-phase commit to ensure transaction atomicity across databases. It is a good fit for transactions that
involve less than 100 databases at a time within a single transaction. These limits are not enforced, but one
should expect performance and success rates for elastic database transactions to suffer when exceeding these
limits.
Development experience
Multi-database applications
The following sample code uses the familiar programming experience with .NET System.Transactions. The
TransactionScope class establishes an ambient transaction in .NET. (An “ambient transaction” is one that lives in
the current thread.) All connections opened within the TransactionScope participate in the transaction. If different
databases participate, the transaction is automatically elevated to a distributed transaction. The outcome of the
transaction is controlled by setting the scope to complete to indicate a commit.
scope.Complete();
}
Sharded database applications
Elastic database transactions for SQL DB also support coordinating distributed transactions where you use the
OpenConnectionForKey method of the elastic database client library to open connections for a scaled out data tier.
Consider cases where you need to guarantee transactional consistency for changes across several different
sharding key values. Connections to the shards hosting the different sharding key values are brokered using
OpenConnectionForKey. In the general case, the connections can be to different shards such that ensuring
transactional guarantees requires a distributed transaction. The following code sample illustrates this approach. It
assumes that a variable called shardmap is used to represent a shard map from the elastic database client library:
scope.Complete();
}
Next steps
Not yet using elastic database capabilities for your Azure applications? Check out our Documentation Map. For
questions, please reach out to us on the SQL Database forum and for feature requests, please add them to the SQL
Database feedback forum.
Managing scaled-out cloud databases
1/17/2017 • 7 min to read • Edit Online
To manage scaled-out sharded databases, the Elastic Database jobs feature (preview) enables you to reliably
execute a Transact-SQL (T-SQL) script across a group of databases, including:
a custom-defined collection of databases (explained below)
all databases in an elastic pool
a shard set (created using Elastic Database client library).
Documentation
Install the Elastic Database job components.
Get started with Elastic Database jobs.
Create and manage jobs using PowerShell.
Create and manage scaled out Azure SQL Databases
Elastic Database jobs is currently a customer-hosted Azure Cloud Service that enables the execution of ad-hoc
and scheduled administrative tasks, which are called jobs. With jobs, you can easily and reliably manage large
groups of Azure SQL Databases by running Transact-SQL scripts to perform administrative operations.
NOTE
In the Azure portal, only a reduced set of functions limited to SQL Azure elastic pools is available. Use the PowerShell APIs
to access the full set of current functionality.
Applications
Perform administrative tasks, such as deploying a new schema.
Update reference data-product information common across all databases. Or schedules automatic updates
every weekday, after hours.
Rebuild indexes to improve query performance. The rebuilding can be configured to execute across a
collection of databases on a recurring basis, such as during off-peak hours.
Collect query results from a set of databases into a central table on an on-going basis. Performance queries
can be continually executed and configured to trigger additional tasks to be executed.
Execute longer running data processing queries across a large set of databases, for example the collection of
customer telemetry. Results are collected into a single destination table for further analysis.
Idempotent scripts
The scripts must be idempotent. In simple terms, "idempotent" means that if the script succeeds, and it is run
again, the same result occurs. A script may fail due to transient network issues. In that case, the job will
automatically retry running the script a preset number of times before desisting. An idempotent script has the
same result even if has been successfully run twice.
A simple tactic is to test for the existence of an object before creating it.
IF NOT EXIST (some_object)
-- Create the object
-- If it exists, drop the object before recreating it.
Similarly, a script must be able to execute successfully by logically testing for and countering any conditions it
finds.
Next steps
Install the components, then create and add a log in to each database in the group of databases. To further
understand job creation and management, see creating and managing elastic database jobs. See also Getting
started with Elastic Database jobs.
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For
questions, please reach out to us on the SQL Database forum and for feature requests, please add them to the
SQL Database feedback forum.
Securing your SQL Database
4/14/2017 • 5 min to read • Edit Online
This article walks through the basics of securing the data tier of an application using Azure SQL Database. In
particular, this article will get you started with resources for protecting data, controlling access, and proactive
monitoring.
For a complete overview of security features available on all flavors of SQL, see the Security Center for SQL
Server Database Engine and Azure SQL Database. Additional information is also available in the Security and
Azure SQL Database technical white paper (PDF).
Protect data
SQL Database secures you data by providing encryption for data in motion using Transport Layer Security, for
data at rest using Transparent Data Encryption, and for data in use using Always Encrypted.
IMPORTANT
All connections to Azure SQL Database require encryption (SSL/TLS) at all times while data is "in transit" to and from the
database. In your application's connection string, you must specify parameters to encrypt the connection and not to trust
the server certificate (this is done for you if you copy your connection string out of the Azure Classic Portal), otherwise the
connection will not verify the identity of the server and will be susceptible to "man-in-the-middle" attacks. For the
ADO.NET driver, for instance, these connection string parameters are Encrypt=True and TrustServerCertificate=False.
Control access
SQL Database secures your data by limiting access to your database using firewall rules, authentication
mechanisms requiring users to prove their identity, and authorization to data through role-based memberships
and permissions, as well as through row-level security and dynamic data masking. For a discussion of the use of
access control features in SQL Database, see Control access.
IMPORTANT
Managing databases and logical servers within Azure is controlled by your portal user account's role assignments. For more
information on this topic, see Role-based access control in Azure Portal.
Proactive monitoring
SQL Database secures your data by providing auditing and threat detection capabilities.
Auditing
SQL Database Auditing tracks database activities and helps you to maintain regulatory compliance, by recording
database events to an audit log in your Azure Storage account. Auditing enables you to understand ongoing
database activities, as well as analyze and investigate historical activity to identify potential threats or suspected
abuse and security violations. For additional information, see Get started with SQL Database Auditing.
Threat detection
Threat Detection complements auditing, by providing an additional layer of security intelligence built into the
Azure SQL Database service. It works around the clock to learn, profile and detect anomalous database activities.
You will be alerted about suspicious activities, potential vulnerabilities, SQL injection attacks and anomalous
database access patterns. You can respond to alerts by following the provided informative and actionable
instructions. For more information, see Get started with SQL Database Threat Detection.
Data Masking
SQL Database Dynamic Data Masking limits sensitive data exposure by masking it to non-privileged users.
Dynamic Data Masking automatically discovers potentially sensitive data in Azure SQL Database and provides
actionable recommendations to mask these fields, with minimal impact on the application layer. It works by
obfuscating the sensitive data in the result set of a query over designated database fields, while the data in the
database is not changed. For more information, see Get started with SQL Database Dynamic Data Masking
Compliance
In addition to the above features and functionality that can help your application meet various security
compliance requirements, Azure SQL Database also participates in regular audits and has been certified against a
number of compliance standards. For more information, see the Microsoft Azure Trust Center, where you can find
the most current list of SQL Database compliance certifications.
Next steps
For a discussion of the use of access control features in SQL Database, see Control access.
For a discussion of database auditing, see SQL Database auditing.
For a discussion of threat detection, see SQL Database threat detection.
Azure SQL Database access control
4/14/2017 • 4 min to read • Edit Online
To provide security, SQL Database controls access with firewall rules limiting connectivity by IP address,
authentication mechanisms requiring users to prove their identity, and authorization mechanisms limiting users
to specific actions and data.
IMPORTANT
For an overview of the SQL Database security features, see SQL security overview. For a tutorial using SQL Server
authentication, see SQL authentication and authorization. For a tutorial using Azure Active Directory authentication, see
Azure AD authentication and authorization.
Authentication
SQL Database supports two types of authentication:
SQL Authentication, which uses a username and password. When you created the logical server for your
database, you specified a "server admin" login with a username and password. Using these credentials, you can
authenticate to any database on that server as the database owner, or "dbo."
Azure Active Directory Authentication, which uses identities managed by Azure Active Directory and is
supported for managed and integrated domains. Use Active Directory authentication (integrated security)
whenever possible. If you want to use Azure Active Directory Authentication, you must create another server
admin called the "Azure AD admin," which is allowed to administer Azure AD users and groups. This admin can
also perform all operations that a regular server admin can. See Connecting to SQL Database By Using Azure
Active Directory Authentication for a walkthrough of how to create an Azure AD admin to enable Azure Active
Directory Authentication.
The Database Engine closes connections that remain idle for more than 30 minutes. The connection must login
again before it can be used. Continuously active connections to SQL Database require reauthorization (performed
by the database engine) at least every 10 hours. The database engine attempts reauthorization using the originally
submitted password and no user input is required. For performance reasons, when a password is reset in SQL
Database, the connection is not be reauthenticated, even if the connection is reset due to connection pooling. This
is different from the behavior of on-premises SQL Server. If the password has been changed since the connection
was initially authorized, the connection must be terminated and a new connection made using the new password.
A user with the KILL DATABASE CONNECTION permission can explicitly terminate a connection to SQL Database by
using the KILL command.
User accounts can be created in the master database and can be granted permissions in all databases on the
server, or they can be created in the database itself (called contained users). For information on creating and
managing logins, see Manage logins. To enhance portability and scalabilty, use contained database users to
enhance scalability. For more information on contained users, see Contained Database Users - Making Your
Database Portable, CREATE USER (Transact-SQL), and Contained Databases.
As a best practice your application should use a dedicated account to authenticate -- this way you can limit the
permissions granted to the application and reduce the risks of malicious activity in case your application code is
vulnerable to a SQL injection attack. The recommended approach is to create a contained database user, which
allows your app to authenticate directly to the database.
Authorization
Authorization refers to what a user can do within an Azure SQL Database, and this is controlled by your user
account's database role memberships and object-level permissions. As a best practice, you should grant users the
least privileges necessary. The server admin account you are connecting with is a member of db_owner, which has
authority to do anything within the database. Save this account for deploying schema upgrades and other
management operations. Use the "ApplicationUser" account with more limited permissions to connect from your
application to the database with the least privileges needed by your application. For more information, see
Manage logins.
Typically, only administrators need access to the master database. Routine access to each user database should be
through non-administrator contained database users created in each database. When you use contained database
users, you do not need to create logins in the master database. For more information, see Contained Database
Users - Making Your Database Portable.
You should familiarize yourself with the following features that can be used to limit or elevate permissions:
Impersonation and module-signing can be used to securely elevate permissions temporarily.
Row-Level Security can be used limit which rows a user can access.
Data Masking can be used to limit exposure of sensitive data.
Stored procedures can be used to limit the actions that can be taken on the database.
Next steps
For an overview of the SQL Database security features, see SQL security overview.
To learn more about firewall rules, see Firewall rules.
To learn about users and logins, see Manage logins.
For a discussion of proactive monitoring, see Database Auditing and SQL Database Threat Detection.
For a tutorial using SQL Server authentication, see SQL authentication and authorization.
For a tutorial using Azure Active Directory authentication, see Azure AD authentication and authorization.
Azure SQL Database server-level and database-
level firewall rules
4/14/2017 • 11 min to read • Edit Online
Microsoft Azure SQL Database provides a relational database service for Azure and other Internet-based
applications. To help protect your data, firewalls prevent all access to your database server until you specify
which computers have permission. The firewall grants access to databases based on the originating IP address
of each request.
Overview
Initially, all Transact-SQL access to your Azure SQL server is blocked by the firewall. To begin using your Azure
SQL server, you must specify one or more server-level firewall rules that enable access to your Azure SQL
server. Use the firewall rules to specify which IP address ranges from the Internet are allowed, and whether
Azure applications can attempt to connect to your Azure SQL server.
To selectively grant access to just one of the databases in your Azure SQL server, you must create a database-
level rule for the required database. Specify an IP address range for the database firewall rule that is beyond
the IP address range specified in the server-level firewall rule, and ensure that the IP address of the client falls
in the range specified in the database-level rule.
Connection attempts from the Internet and Azure must first pass through the firewall before they can reach
your Azure SQL server or SQL Database, as shown in the following diagram:
Server-level firewall rules: These rules enable clients to access your entire Azure SQL server, that is, all the
databases within the same logical server. These rules are stored in the master database. Server-level
firewall rules can be configured by using the portal or by using Transact-SQL statements. To create server-
level firewall rules using the Azure portal or PowerShell, you must be the subscription owner or a
subscription contributor. To create a server-level firewall rule using Transact-SQL, you must connect to the
SQL Database instance as the server-level principal login or the Azure Active Directory administrator (which
means that a server-level firewall rule must first be created by a user with Azure-level permissions).
Database-level firewall rules: These rules enable clients to access certain (secure) databases within the
same logical server. You can create these rules for each database (including the master database0) and they
are stored in the individual databases. Database-level firewall rules can only be configured by using
Transact-SQL statements and only after you have configured the first server-level firewall. If you specify an
IP address range in the database-level firewall rule that is outside the range specified in the server-level
firewall rule, only those clients that have IP addresses in the database-level range can access the database.
You can have a maximum of 128 database-level firewall rules for a database. Database-level firewall rules
for master and user databases can only be created and managed through Transact-SQL. For more
information on configuring database-level firewall rules, see the example later in this article and see
sp_set_database_firewall_rule (Azure SQL Databases).
Recommendation: Microsoft recommends using database-level firewall rules whenever possible to enhance
security and to make your database more portable. Use server-level firewall rules for administrators and when
you have many databases that have the same access requirements and you don't want to spend time
configuring each database individually.
NOTE
For information about portable databases in the context of business continuity, see Authentication requirements for
disaster recovery.
NOTE
To access Azure SQL Database from your local computer, ensure the firewall on your network and local computer allows
outgoing communication on TCP port 1433.
IMPORTANT
This option configures the firewall to allow all connections from Azure including connections from the subscriptions of
other customers. When selecting this option, make sure your login and user permissions limit access to only authorized
users.
Creating and managing firewall rules
The first server-level firewall setting can be created using the Azure portal or programmatically using Azure
PowerShell, Azure CLI, or the REST API. Subsequent server-level firewall rules can be created and managed
using these methods, and through Transact-SQL.
IMPORTANT
Database-level firewall rules can only be created and managed using Transact-SQL.
To improve performance, server-level firewall rules are temporarily cached at the database level. To refresh the
cache, see DBCC FLUSHAUTHCACHE.
Azure portal
To set a server-level firewall rule in the Azure portal, you can either go to the Overview page for your Azure
SQL database or the Overview page for your Azure Database logical server.
TIP
For a tutorial, see Create a DB using the Azure portal.
2. Click Add client IP on the toolbar to add the IP address of the computer you are currently using and
then click Save. A server-level firewall rule is created for your current IP address.
From server overview page
The overview page for your server opens, showing you the fully qualified server name (such as
mynewserver20170403.database.windows.net) and provides options for further configuration.
1. To set a server-level rule from server overview page, click Firewall in the left-hand menu under Settings
as showed in the following image:
2. Click Add client IP on the toolbar to add the IP address of the computer you are currently using and
then click Save. A server-level firewall rule is created for your current IP address.
Transact-SQL
CATALOG VIEW OR STORED PROCEDURE LEVEL DESCRIPTION
The following examples review the existing rules, enable a range of IP addresses on the server Contoso, and
deletes a firewall rule:
To delete a server-level firewall rule, execute the sp_delete_firewall_rule stored procedure. The following
example deletes the rule named ContosoFirewallRule:
EXECUTE sp_delete_firewall_rule @name = N'ContosoFirewallRule'
Azure PowerShell
CMDLET LEVEL DESCRIPTION
TIP
For PowerShell examples in the context of a quick start, see Create DB - PowerShell and Create a single database and
configure a firewall rule using PowerShell
Azure CLI
CMDLET LEVEL DESCRIPTION
az sql server firewall rule show Shows the details of a firewall rule.
The following example sets a server-level firewall rule using the Azure CLI:
REST API
API LEVEL DESCRIPTION
Q. Is the person or team configuring or auditing the firewall rules, centrally managing firewall rules for many
(perhaps 100s) of databases?
This selection depends upon your needs and environment. Server-level firewall rules might be easier to
configure, but scripting can configure rules at the database-level. And even if you use server-level firewall rules,
you might need to audit the database-firewall rules, to see if users with CONTROL permission on the database
have created database-level firewall rules.
Q. Can I use a mix of both server-level and database-level firewall rules?
Yes. Some users, such as administrators might need server-level firewall rules. Other users, such as users of a
database application, might need database-level firewall rules.
Next steps
For a quick start on creating a database and a server-level firewall rule, see Create an Azure SQL database.
For help in connecting to an Azure SQL database from open source or third-party applications, see Client
quick-start code samples to SQL Database.
For information on additional ports that you may need to open, see the SQL Database: Outside vs inside
section of Ports beyond 1433 for ADO.NET 4.5 and SQL Database
For an overview of Azure SQL Database security, see Securing your database
Use Azure Active Directory Authentication for
authentication with SQL Database or SQL Data
Warehouse
4/14/2017 • 7 min to read • Edit Online
Azure Active Directory authentication is a mechanism of connecting to Microsoft Azure SQL Database and SQL
Data Warehouse by using identities in Azure Active Directory (Azure AD). With Azure AD authentication, you can
centrally manage the identities of database users and other Microsoft services in one central location. Central ID
management provides a single place to manage database users and simplifies permission management. Benefits
include the following:
It provides an alternative to SQL Server authentication.
Helps stop the proliferation of user identities across database servers.
Allows password rotation in a single place
Customers can manage database permissions using external (AAD) groups.
It can eliminate storing passwords by enabling integrated Windows authentication and other forms of
authentication supported by Azure Active Directory.
Azure AD authentication uses contained database users to authenticate identities at the database level.
Azure AD supports token-based authentication for applications connecting to SQL Database.
Azure AD authentication supports ADFS (domain federation) or native user/password authentication for a
local Azure Active Directory without domain synchronization.
Azure AD supports connections from SQL Server Management Studio that use Active Directory Universal
Authentication, which includes Multi-Factor Authentication (MFA). MFA includes strong authentication with a
range of easy verification options — phone call, text message, smart cards with pin, or mobile app
notification. For more information, see SSMS support for Azure AD MFA with SQL Database and SQL Data
Warehouse.
The configuration steps include the following procedures to configure and use Azure Active Directory
authentication.
1. Create and populate Azure AD.
2. Optional: Associate or change the active directory that is currently associated with your Azure Subscription.
3. Create an Azure Active Directory administrator for Azure SQL server or Azure SQL Data Warehouse.
4. Configure your client computers.
5. Create contained database users in your database mapped to Azure AD identities.
6. Connect to your database by using Azure AD identities.
NOTE
To learn how to create and populate Azure AD, and then configure Azure AD with Azure SQL Database and SQL Data
Warehouse, see Configure Azure AD with Azure SQL Database.
Trust architecture
The following high-level diagram summarizes the solution architecture of using Azure AD authentication with
Azure SQL Database. The same concepts apply to SQL Data Warehouse. To support Azure AD native user
password, only the Cloud portion and Azure AD/Azure SQL Database is considered. To support Federated
authentication (or user/password for Windows credentials), the communication with ADFS block is required. The
arrows indicate communication pathways.
The following diagram indicates the federation, trust, and hosting relationships that allow a client to connect to a
database by submitting a token. The token is authenticated by an Azure AD, and is trusted by the database.
Customer 1 can represent an Azure Active Directory with native users or an Azure AD with federated users.
Customer 2 represents a possible solution including imported users; in this example coming from a federated
Azure Active Directory with ADFS being synchronized with Azure Active Directory. It's important to understand
that access to a database using Azure AD authentication requires that the hosting subscription is associated to
the Azure AD. The same subscription must be used to create the SQL Server hosting the Azure SQL Database or
SQL Data Warehouse.
Administrator structure
When using Azure AD authentication, there are two Administrator accounts for the SQL Database server; the
original SQL Server administrator and the Azure AD administrator. The same concepts apply to SQL Data
Warehouse. Only the administrator based on an Azure AD account can create the first Azure AD contained
database user in a user database. The Azure AD administrator login can be an Azure AD user or an Azure AD
group. When the administrator is a group account, it can be used by any group member, enabling multiple Azure
AD administrators for the SQL Server instance. Using group account as an administrator enhances manageability
by allowing you to centrally add and remove group members in Azure AD without changing the users or
permissions in SQL Database. Only one Azure AD administrator (a user or group) can be configured at any time.
Permissions
To create new users, you must have the ALTER ANY USER permission in the database. The ALTER ANY USER
permission can be granted to any database user. The ALTER ANY USER permission is also held by the server
administrator accounts, and database users with the CONTROL ON DATABASE or ALTER ON DATABASE permission
for that database, and by members of the db_owner database role.
To create a contained database user in Azure SQL Database or SQL Data Warehouse, you must connect to the
database using an Azure AD identity. To create the first contained database user, you must connect to the
database by using an Azure AD administrator (who is the owner of the database). This is demonstrated in steps 4
and 5 below. Any Azure AD authentication is only possible if the Azure AD admin was created for Azure SQL
Database or SQL Data Warehouse server. If the Azure Active Directory admin was removed from the server,
existing Azure Active Directory users created previously inside SQL Server can no longer connect to the database
using their Azure Active Directory credentials.
Next steps
To learn how to create and populate Azure AD, and then configure Azure AD with Azure SQL Database, see
Configure Azure AD with Azure SQL Database.
For an overview of access and control in SQL Database, see SQL Database access and control.
For an overview of logins, users, and database roles in SQL Database, see Logins, users, and database roles.
For more information about database principals, see Principals.
For more information about database roles, see Database roles.
For more information about firewall rules in SQL Database, see SQL Database firewall rules.
For a tutorial using SQL Server authentication, see SQL authentication and authorization.
For a tutorial using Azure Active Directory authentication, see Azure AD authentication and authorization.
Controlling and granting database access
4/14/2017 • 11 min to read • Edit Online
When firewall rules have been configured, people can connect to a SQL Database as one of the administrator
accounts, as the database owner, or as a database user in the database.
NOTE
This topic applies to Azure SQL server, and to both SQL Database and SQL Data Warehouse databases that are created
on the Azure SQL server. For simplicity, SQL Database is used when referring to both SQL Database and SQL Data
Warehouse.
TIP
For a tutorial using SQL Server authentication, see Tutorial: SQL Server authentication. For a tutorial using Azure Active
Directory authentication, see Tutorial: AAD authentication.
Server admin
When you create an Azure SQL server, you must designate a Server admin login. SQL server creates that
account as a login in the master database. This account connects using SQL Server authentication (user
name and password). Only one of these accounts can exist.
Azure Active Directory admin
One Azure Active Directory account, either an individual or security group account, can also be configured
as an administrator. It is optional to configure an Azure AD administrator, but an Azure AD administrator
must be configured if you want to use Azure AD accounts to connect to SQL Database. For more
information about configuring Azure Active Directory access, see Connecting to SQL Database or SQL Data
Warehouse By Using Azure Active Directory Authentication and SSMS support for Azure AD MFA with SQL
Database and SQL Data Warehouse.
The Server admin and Azure AD admin accounts has the following characteristics:
These are the only accounts that can automatically connect to any SQL Database on the server. (To connect
to a user database, other accounts must either be the owner of the database, or have a user account in the
user database.)
These accounts enter user databases as the dbo user and they have all the permissions in the user
databases. (The owner of a user database also enters the database as the dbo user.)
These accounts do not enter the master database as the dbo user and they have limited permissions in
master.
These accounts are not members of the standard SQL Server sysadmin fixed server role, which is not
available in SQL database.
These accounts can create, alter, and drop databases, logins, users in master, and server-level firewall rules.
These accounts can add and remove members to the dbmanager and loginmanager roles.
These accounts can view the sys.sql_logins system table.
Configuring the firewall
When the server-level firewall is configured for an individual IP address or range, the SQL server admin and
the Azure Active Directory admin can connect to the master database and all the user databases. The initial
server-level firewall can be configured through the Azure portal, using PowerShell or using the REST API. Once
a connection is made, additional server-level firewall rules can also be configured by using Transact-SQL.
Administrator access path
When the server-level firewall is properly configured, the SQL server admin and the Azure Active Directory
admin can connect using client tools such as SQL Server Management Studio or SQL Server Data Tools. Only
the latest tools provide all the features and capabilities. The following diagram shows a typical configuration
for the two administrator accounts.
When using an open port in the server-level firewall, administrators can connect to any SQL Database.
Connecting to a database by using SQL Server Management Studio
For a walk-through of creating a server, a database, server-level firewall rules, and using SQL Server
Management Studio to query a database, see Get started with Azure SQL Database servers, databases, and
firewall rules by using the Azure portal and SQL Server Management Studio.
IMPORTANT
It is recommended that you always use the latest version of Management Studio to remain synchronized with updates
to Microsoft Azure and SQL Database. Update SQL Server Management Studio.
NOTE
Use a strong password when creating a login or contained database user. For more information, see Strong
Passwords.
To improve performance, logins (server-level principals) are temporarily cached at the database level.
To refresh the authentication cache, see DBCC FLUSHAUTHCACHE.
3. In the master database, create a user by using the CREATE USER statement. The user can be an Azure
Active Directory authentication contained database user (if you have configured your environment for
Azure AD authentication), or a SQL Server authentication contained database user, or a SQL Server
authentication user based on a SQL Server authentication login (created in the previous step.) Sample
statements:
4. Add the new user, to the dbmanager database role by using the ALTER ROLE statement. Sample
statements:
5. If necessary, configure a firewall rule to allow the new user to connect. (The new user might be covered
by an existing firewall rule.)
Now the user can connect to the master database and can create new databases. The account creating the
database becomes the owner of the database.
Login managers
The other administrative role is the login manager role. Members of this role can create new logins in the
master database. If you wish, you can complete the same steps (create a login and user, and add a user to the
loginmanager role) to enable a user to create new logins in the master. Usually logins are not necessary as
Microsoft recommends using contained database users, which authenticate at the database-level instead of
using users based on logins. For more information, see Contained Database Users - Making Your Database
Portable.
Non-administrator users
Generally, non-administrator accounts do not need access to the master database. Create contained database
users at the database level using the CREATE USER (Transact-SQL) statement. The user can be an Azure Active
Directory authentication contained database user (if you have configured your environment for Azure AD
authentication), or a SQL Server authentication contained database user, or a SQL Server authentication user
based on a SQL Server authentication login (created in the previous step.) For more information, see
Contained Database Users - Making Your Database Portable.
To create users, connect to the database, and execute statements similar to the following examples:
Initially, only one of the administrators or the owner of the database can create users. To authorize additional
users to create new users, grant that selected user the ALTER ANY USER permission, by using a statement such
as:
To give additional users full control of the database, make them a member of the db_owner fixed database
role using the ALTER ROLE statement.
NOTE
The most common reason to create database users based on logins, is when you have SQL Server authentication users
that need access to multiple databases. Users based on logins are tied to the login, and only one password that is
maintained for that login. Contained database users in individual databases are each individual entities and each
maintains its own password. This can confuse contained database users if they do not maintain their passwords as
identical.
Permissions
There are over 100 permissions that can be individually granted or denied in SQL Database. Many of these
permissions are nested. For example, the UPDATE permission on a schema includes the UPDATE permission
on each table within that schema. As in most permission systems, the denial of a permission overrides a grant.
Because of the nested nature and the number of permissions, it can take careful study to design an
appropriate permission system to properly protect your database. Start with the list of permissions at
Permissions (Database Engine) and review the poster size graphic of the permissions.
Considerations and restrictions
When managing logins and users in SQL Database, consider the following:
You must be connected to the master database when executing the CREATE/ALTER/DROP DATABASE
statements.
The database user corresponding to the Server admin login cannot be altered or dropped.
US-English is the default language of the Server admin login.
Only the administrators (Server admin login or Azure AD administrator) and the members of the
dbmanager database role in the master database have permission to execute the CREATE DATABASE and
DROP DATABASE statements.
You must be connected to the master database when executing the CREATE/ALTER/DROP LOGIN statements.
However using logins is discouraged. Use contained database users instead.
To connect to a user database, you must provide the name of the database in the connection string.
Only the server-level principal login and the members of the loginmanager database role in the master
database have permission to execute the CREATE LOGIN , ALTER LOGIN , and DROP LOGIN statements.
When executing the CREATE/ALTER/DROP LOGIN and CREATE/ALTER/DROP DATABASE statements in an
ADO.NET application, using parameterized commands is not allowed. For more information, see
Commands and Parameters.
When executing the CREATE/ALTER/DROP DATABASE and CREATE/ALTER/DROP LOGIN statements, each of
these statements must be the only statement in a Transact-SQL batch. Otherwise, an error occurs. For
example, the following Transact-SQL checks whether the database exists. If it exists, a DROP DATABASE
statement is called to remove the database. Because the DROP DATABASE statement is not the only
statement in the batch, executing the following Transact-SQL statement results in an error.
When executing the CREATE USER statement with the FOR/FROM LOGIN option, it must be the only
statement in a Transact-SQL batch.
When executing the ALTER USER statement with the WITH LOGIN option, it must be the only statement in a
Transact-SQL batch.
To CREATE/ALTER/DROP a user requires the ALTER ANY USER permission on the database.
When the owner of a database role tries to add or remove another database user to or from that database
role, the following error may occur: User or role 'Name' does not exist in this database. This error
occurs because the user is not visible to the owner. To resolve this issue, grant the role owner the
VIEW DEFINITION permission on the user.
Next steps
To learn more about firewall rules, see Azure SQL Database Firewall.
For an overview of all the SQL Database security features, see SQL security overview.
For a tutorial, see Get started with SQL security
For information about views and stored procedures, see Creating views and stored procedures
For information about granting access to a database object, see Granting Access to a Database Object
For a tutorial using SQL Server authentication, see Tutorial: SQL Server authentication.
For a tutorial using Azure Active Directory authentication, see Tutorial: AAD authentication.
Universal Authentication with SQL Database and SQL
Data Warehouse (SSMS support for MFA)
4/14/2017 • 2 min to read • Edit Online
Azure SQL Database and Azure SQL Data Warehouse support connections from SQL Server Management Studio
(SSMS) using Active Directory Universal Authentication.
Active Directory Universal Authentication supports the two non-interactive authentication methods (Active
Directory Password Authentication and Active Directory Integrated Authentication). Non-interactive Active
Directory Password and Active Directory Integrated Authentication methods can be used in many different
applications (ADO.NET, JDBC, ODBC, etc.). These two methods never result in pop-up dialog boxes.
Active Directory Universal Authentication is an interactive method that also supports Azure Multi-Factor
Authentication (MFA). Azure MFA helps safeguard access to data and applications while meeting user
demand for a simple sign-in process. It delivers strong authentication with a range of easy verification
options—phone call, text message, smart cards with pin, or mobile app notification—allowing users to
choose the method they prefer. Interactive MFA with Azure AD can result in a pop-up dialog box for
validation.
For a description of Multi-Factor Authentication, see Multi-Factor Authentication. For configuration steps, see
Configure Azure SQL Database multi-factor authentication for SQL Server Management Studio.
Azure AD domain name or tenant ID parameter
Beginning with SSMS version 17, users that are imported into the current Active Directory from other Azure Active
Directories, can provide the Azure AD domain name, or tenant ID when they connect. This allows Active Directory
Universal Authentication to identify the correct authenticating authority. This option is also required to support
Microsoft accounts (MSA) such as outlook.com, hotmail.com or live.com. All these users who want to be
authenticated using Universal Authentication must enter their Azure AD domain name or tenant ID. This parameter
represents the current Azure AD domain name/tenant ID the Azure Server is linked with. For example, if Azure
Server is associated with Azure AD domain contosotest.onmicrosoft.com where user joe@contosodev.onmicrosoft.com is
hosted as an imported user from Azure AD domain contosodev.onmicrosoft.com , the domain name required to
authenticate this user is contosotest.onmicrosoft.com . When the user is a native user of the Azure AD linked to Azure
Server, and is not an MSA account, no domain name or tenant ID is required. To enter the parameter (beginning
with SSMS version 17), in the Connect to Database dialog box, complete the dialog box, selecting Active
Directory Universal Authentication, click Options, click the Connection Properties tab, check the AD
domain name or tenant ID box, and provide authenticating authority, such as the domain name
(contosotest.onmicrosoft.com) or the guid of the tenant ID.
Next steps
For configuration steps, see Configure Azure SQL Database multi-factor authentication for SQL Server
Management Studio.
Grant others access to your database: SQL Database Authentication and Authorization: Granting Access
Make sure others can connect through the firewall: Configure an Azure SQL Database server-level firewall rule
using the Azure portal
Get started with SQL database auditing
4/14/2017 • 11 min to read • Edit Online
Azure SQL Database Auditing tracks database events and writes them to an audit log in your Azure Storage
account.
Auditing can help you maintain regulatory compliance, understand database activity, and gain insight into
discrepancies and anomalies that could indicate business concerns or suspected security violations.
Auditing enables and facilitates adherence to compliance standards but doesn't guarantee compliance. For more
information about Azure programs that support standards compliance, see the Azure Trust Center.
Azure SQL Database Auditing overview
Set up auditing for your database
Analyze audit logs and reports
IMPORTANT
The introduction of the new Blob Auditing brings a major change to the way server auditing policy is being inherited by the
database. See Blob/Table differences in server auditing policy inheritance section for additional details.
You can configure auditing for different types of event categories, as explained in the Set up auditing for your
database section.
An auditing policy can be defined for a specific database or as a default server policy. A default server auditing
policy applies to all existing and newly created databases on a server.
2. Navigate to the settings blade of the SQL Database / SQL Server you want to audit. In the Settings blade,
select Auditing & Threat detection.
3. In the database auditing configuration blade, you can check the Inherit settings from server checkbox to
designate that this database will be audited according to its server's settings. If this option is checked, you
will see a View server auditing settings link that allows you to view or modify the server auditing
settings from this context.
4. If you prefer to enable Blob Auditing on the database-level (in addition or instead of server-level auditing),
uncheck the Inherit Auditing settings from server option, turn ON Auditing, and choose the Blob
Auditing Type.
If server Blob auditing is enabled, the database configured audit will exist side by side with the server
Blob audit.
5. Select Storage Details to open the Audit Logs Storage Blade. Select the Azure storage account where logs
will be saved, and the retention period, after which the old logs will be deleted, then click OK at the bottom.
Tip: Use the same storage account for all audited databases to get the most out of the auditing reports
templates.
6. If you want to customize the audited events, you can do this via PowerShell or REST API - see the Automation
(PowerShell / REST API) section for more details.
7. Once you've configured your auditing settings, you can turn on the new Threat Detection (preview) feature,
and configure the emails to receive security alerts. Threat Detection allows you to receive proactive alerts on
anomalous database activities that may indicate potential security threats. See Getting Started with Threat
Detection for more details.
8. Click Save.
(deprecated)
Tabl e Audi ti ng
Before setting up Table Auditing, check if you are using a "Downlevel Client". Also, if you have strict firewall
settings, please note that the IP endpoint of your database will change when enabling Table Auditing.
4. If you prefer not to inherit Auditing settings from server, uncheck the Inherit Auditing settings from
server option, turn ON Auditing, and choose Table Auditing Type.
5. Select Storage Details to open the Audit Logs Storage Blade. Select the Azure storage account where logs will
be saved, and the retention period, after which the old logs will be deleted. Tip: Use the same storage account
for all audited databases to get the most out of the auditing reports templates (see screenshot in Blob Auditing
section).
6. Click on Audited Events to customize which events to audit. In the Logging by event blade, click
Success and Failure to log all events, or choose individual event categories.
Customizing audited events can also be done via PowerShell or REST API - see the Automation
(PowerShell / REST API) section for more details.
7. Once you've configured your auditing settings, you can turn on the new Threat Detection (preview) feature,
and configure the emails to receive security alerts. Threat Detection allows you to receive proactive alerts on
anomalous database activities that may indicate potential security threats. See Getting Started with Threat
Detection for more details.
8. Click Save.
Blob/table differences in server auditing policy inheritance
1. If Server Blob auditing is enabled, it always applies to the database (i.e. the database will be audited),
Bl ob audi ti ng
regardless of:
The database auditing settings.
Whether or not the "Inherit settings from server" checkbox is checked in the database blade.
2. Enabling Blob auditing on the database, in addition to enabling it on the server, will not override or change
any of the settings of the server Blob auditing - both audits will exist side by side. In other words, the
database will be audited twice in parallel (once by the Server policy and once by the Database policy).
NOTE
You should avoid enabling both server Blob auditing and database Blob auditing together, unless:
You need to use a different storage account or retention period for a specific database.
You want to audit different event types or categories for a specific database than are being audited for the rest
of the databases on this server (e.g. if table inserts need to be audited only for a specific database).
Otherwise, it is recommended to only enable server-level Blob Auditing and leave the database-level
auditing disabled for all databases.
(deprecated)
Tabl e audi ti ng
If server-level Table auditing is enabled, it only applies to the database if the "Inherit settings from server"
checkbox is checked in the database blade (this is checked by default for all existing and newly created databases).
If the checkbox is checked, any changes made to the auditing settings in database override the server
settings for this database.
If the checkbox is unchecked and the database-level auditing is disabled, the database will not be audited.
For further details about the Blob audit logs storage folder hierarchy, blob naming convention, and log format,
see the Blob Audit Log Format Reference (doc file download).
There are several methods to view Blob Auditing logs:
1. Through the Azure portal - open the relevant database. At the top of the database's Auditing & Threat
detection blade, click on View audit logs.
An Audit records blade will open, where you'll be able to view the logs.
You can choose to view specific dates by clicking on Filter at the top area of the Audit records blade
You can toggle between audit records that were created by server policy or database policy audit
2. Download log files from your Azure Storage Blob container via the portal or by using a tool such as Azure
Storage Explorer.
Once you have downloaded the log file locally, you can double-click the file to open, view and analyze the
logs in SSMS.
Additional methods:
You can download multiple files simultaneously via Azure Storage Explorer - right-click on a
specific subfolder (e.g. a subfolder that includes all log files for a specific date) and choose "Save as"
to save in a local folder.
After downloading several files (or an entire day, as described above), you can merge them locally
as follows:
Open SSMS -> File -> Open -> Merge Extended Events -> Choose all files to merge
Programmatically:
Extended Events Reader C# library (more info here)
Querying Extended Events Files Using PowerShell (more info here)
3. We have created a sample application that runs in Azure and utilizes OMS public APIs to push SQL audit
logs into OMS for consumption via the OMS dashboard (more info here).
(deprecated)
Tabl e audi ti ng
Table Auditing logs are saved as a collection of Azure Storage Tables with a SQLDBAuditLogs prefix.
For further details about the Table audit log format, see the Table Audit Log Format Reference (doc file download).
There are several methods to view Table Auditing logs:
1. Through the Azure portal - open the relevant database. At the top of the database's Auditing & Threat
detection blade, click on View audit logs.
An Audit records blade will open, where you'll be able to view the logs.
You can choose to view specific dates by clicking on Filter at the top area of the Audit records blade
You can download and view the audit logs in Excel format by clicking on Open in Excel at the top
area of the Audit records blade
2. Alternatively, a preconfigured report template is available as a downloadable Excel spreadsheet to help you
quickly analyze log data. To use the template on your audit logs, you need Excel 2013 or later and Power
Query, which you can download here.
You can also import your audit logs into the Excel template directly from your Azure storage account using
Power Query. You can then explore your audit records and create dashboards and reports on top of the log
data.
In production, you are likely to refresh your storage keys periodically. When refreshing your keys, you need to re-
Storage key regenerati on
2. Go to the storage configuration blade and regenerate the Primary Access Key.
3. Go back to the auditing configuration blade, switch the Storage Access Key from Secondary to Primary, and
then click OK at the bottom. Then click SAVE at the top of the auditing configuration blade.
4. Go back to the storage configuration blade and regenerate the Secondary Access Key (in preparation for the
next keys refresh cycle).
Automation (PowerShell / REST API)
You can also configure Auditing in Azure SQL Database using the following automation tools:
1. PowerShell cmdlets
Get-AzureRMSqlDatabaseAuditingPolicy
Get-AzureRMSqlServerAuditingPolicy
Remove-AzureRMSqlDatabaseAuditing
Remove-AzureRMSqlServerAuditing
Set-AzureRMSqlDatabaseAuditingPolicy
Set-AzureRMSqlServerAuditingPolicy
Use-AzureRMSqlServerAuditingPolicy
For an script example, see Configure auditing and threat detectoin using PowerShell.
2. REST API - Blob Auditing
Create or Update Database Blob Auditing Policy
Create or Update Server Blob Auditing Policy
Get Database Blob Auditing Policy
Get Server Blob Auditing Policy
Get Server Blob Auditing Operation Result
3. REST API - Table Auditing (deprecated)
Create or Update Database Auditing Policy
Create or Update Server Auditing Policy
Get Database Auditing Policy
Get Server Auditing Policy
SQL Database - Downlevel clients support and IP
endpoint changes for Auditing
4/14/2017 • 1 min to read • Edit Online
Database Auditing works automatically with SQL clients that support TDS redirection. Note that redirection does
not apply when using the Blob Auditing method.
Threat Detection detects anomalous database activities indicating potential security threats to the database. Threat
Detection is currently in preview.
Overview
Threat Detection provides a new layer of security, which enables customers to detect and respond to potential
threats as they occur by providing security alerts on anomalous activities. Users can explore the suspicious events
using SQL Database Auditing to determine if they result from an attempt to access, breach or exploit data in the
database. Threat Detection makes it simple to address potential threats to the database without the need to be a
security expert or manage advanced security monitoring systems.
For example, Threat Detection detects certain anomalous database activities indicating potential SQL injection
attempts. SQL injection is one of the common Web application security issues on the Internet, used to attack data-
driven applications. Attackers take advantage of application vulnerabilities to inject malicious SQL statements into
application entry fields, for breaching or modifying data in the database.
4. In the Auditing Records blade, click Open in Excel to open a pre-configured excel template to import and
run deeper analysis of the audit log around the time of the suspicious event.
Note: In Excel 2010 or later, Power Query and the Fast Combine setting is required.
5. To configure the Fast Combine setting - In the POWER QUERY ribbon tab, select Options to display the
Options dialog. Select the Privacy section and choose the second option - 'Ignore the Privacy Levels and
potentially improve performance':
6. To load SQL audit logs, ensure that the parameters in the settings tab are set correctly and then select the
'Data' ribbon and click the 'Refresh All' button.
7. The results appear in the SQL Audit Logs sheet which enables you to run deeper analysis of the anomalous
activities that were detected, and mitigate the impact of the security event in your application.
Next steps
For an overview of SQL Database auditing, see Database auditing.
For a PowerShell script example, see Configure auditing and threat detection using PowerShell.
SQL Database dynamic data masking
4/14/2017 • 3 min to read • Edit Online
SQL Database dynamic data masking limits sensitive data exposure by masking it to non-privileged users.
Dynamic data masking helps prevent unauthorized access to sensitive data by enabling customers to designate
how much of the sensitive data to reveal with minimal impact on the application layer. It’s a policy-based security
feature that hides the sensitive data in the result set of a query over designated database fields, while the data in
the database is not changed.
For example, a service representative at a call center may identify callers by several digits of their credit card
number, but those data items should not be fully exposed to the service representative. A masking rule can be
defined that masks all but the last four digits of any credit card number in the result set of any query. As another
example, an appropriate data mask can be defined to protect personally identifiable information (PII) data, so that
a developer can query production environments for troubleshooting purposes without violating compliance
regulations.
Credit card Masking method, which exposes the last four digits of
the designated fields and adds a constant string as a prefix
in the form of a credit card.
XXXX-XXXX-XXXX-1234
aXX@XXXX.com
Custom text Masking method, which exposes the first and last
characters and adds a custom padding string in the middle.
If the original string is shorter than the exposed prefix and
suffix, only the padding string is used.
prefix[padding]suffix
Set up dynamic data masking for your database using REST API
See Operations for Azure SQL Databases.
Overview of business continuity with Azure SQL
Database
4/13/2017 • 11 min to read • Edit Online
This overview describes the capabilities that Azure SQL Database provides for business continuity and disaster
recovery. It provides options, recommendations, and tutorials for recovering from disruptive events that could
cause data loss or cause your database and application to become unavailable. The discussion includes what to
do when a user or application error affects data integrity, an Azure region has an outage, or your application
requires maintenance.
Point in Time Restore from Any restore point within 7 Any restore point within 35 Any restore point within 35
backup days days days
Geo-Restore from geo- ERT < 12h, RPO < 1h ERT < 12h, RPO < 1h ERT < 12h, RPO < 1h
replicated backups
Restore from Azure Backup ERT < 12h, RPO < 1 wk ERT < 12h, RPO < 1 wk ERT < 12h, RPO < 1 wk
Vault
Active Geo-Replication ERT < 30s, RPO < 5s ERT < 30s, RPO < 5s ERT < 30s, RPO < 5s
IMPORTANT
To recover using automated backups, you must be a member of the SQL Server Contributor role or the subscription
owner - see RBAC: Built-in roles. You can recover using the Azure portal, PowerShell, or the REST API. You cannot use
Transact-SQL.
Use automated backups as your business continuity and recovery mechanism if your application:
Is not considered mission critical.
Doesn't have a binding SLA therefore the downtime of 24 hours or longer will not result in financial liability.
Has a low rate of data change (low transactions per hour) and losing up to an hour of change is an
acceptable data loss.
Is cost sensitive.
If you need faster recovery, use Active Geo-Replication (discussed next). If you need to be able to recover data
from a period older than 35 days, consider archiving your database regularly to a BACPAC file (a compressed
file containing your database schema and associated data) stored either in Azure blob storage or in another
location of your choice. For more information on how to create a transactionally consistent database archive,
see create a database copy and export the database copy.
Use Active Geo -Replication and auto -failover groups to reduce recovery time and limit data loss associated
with a recovery
In addition to using database backups for database recovery in the event of a business disruption, you can use
Active Geo-Replication to configure a database to have up to four readable secondary databases in the regions
of your choice. These secondary databases are kept synchronized with the primary database using an
asynchronous replication mechanism. This feature is used to protect against business disruption in the event of
a data center outage or during an application upgrade. Active Geo-Replication can also be used to provide
better query performance for read-only queries to geographically dispersed users.
To enable automated and transparent failover you should organize your geo-replicated databases into groups
using the auto-failover group feature of SQL Database.
If the primary database goes offline unexpectedly or you need to take it offline for maintenance activities, you
can quickly promote a secondary to become the primary (also called a failover) and configure applications to
connect to the newly promoted primary. If your application is connecting to the databases using the failover
group listener, you don’t need to change the SQL connection string configuration after failover. With a planned
failover, there is no data loss. With an unplanned failover, there may be some small amount of data loss for very
recent transactions due to the nature of asynchronous replication. Using auto-failover groups, you can
customize the failover policy to minimize the potential data loss. After a failover, you can later failback - either
according to a plan or when the data center comes back online. In all cases, users experience a small amount of
downtime and need to reconnect.
IMPORTANT
To use Active Geo-Replication and auto-failover groups, you must either be the subscription owner or have
administrative permissions in SQL Server. You can configure and failover using the Azure portal, PowerShell, or the REST
API using permissions on the subscription or using Transact-SQL using permissions within SQL Server.
NOTE
When the data center comes back online the old primaries automatically re-connect to the new primary and become
secondary databases. If you need to relocate the primary back to the original region you can initiate a planned failover
manually (failback).
NOTE
If the data center comes back online before you switch your application over to the recovered database, you can simply
cancel the recovery.
Next steps
For a discussion of application design considerations for stand-alone databases and for elastic pools, see Design
an application for cloud disaster recovery and Elastic Pool disaster recovery strategies.
Learn about SQL Database backups
4/14/2017 • 5 min to read • Edit Online
SQL Database automatically creates a database backups and uses Azure read-access geo-redundant storage
(RA-GRS) to provide geo-redundancy. These backups are created automatically and at no additional charge. You
don't need to do anything to make them happen. Database backups are an essential part of any business
continuity and disaster recovery strategy because they protect your data from accidental corruption or deletion.
If you want to keep backups in your own storage container you can configure a long-term backup retention
policy. For more information, see Long-term retention.
NOTE
In Azure storage, the term replication refers to copying files from one location to another. SQL's database replication
refers to keeping to multiple secondary databases synchronized with a primary database.
IMPORTANT
If you delete the Azure SQL server that hosts SQL Databases, all databases that belong to the server are also deleted and
cannot be recovered. You cannot restore a deleted server.
TIP
For a How-to guide, see Configure and restore from Azure SQL Database long-term backup retention
Next steps
Database backups are an essential part of any business continuity and disaster recovery strategy because
they protect your data from accidental corruption or deletion. To learn about the other Azure SQL Database
business continuity solutions, see Business continuity overview.
To restore to a point in time using the Azure portal, see restore database to a point in time using the Azure
portal.
To restore to a point in time using PowerShell, see restore database to a point in time using PowerShell.
To configure, manage, and restore from long-term retention of automated backups in an Azure Recovery
Services vault using the Azure portal, see Manage long-term backup retention using the Azure portal.
To configure, manage, and restore from long-term retention of automated backups in an Azure Recovery
Services vault using PowerShell, see Manage long-term backup retention using PowerShell.
Storing Azure SQL Database Backups for up to 10
years
4/19/2017 • 6 min to read • Edit Online
Many applications have regulatory, compliance, or other business purposes that require you to retain the
automatic full database backups beyond the 7-35 days provided by SQL Database's automatic backups. The
Long-Term Backup Retention feature enables you to store your Azure SQL Database backups in an Azure
Recovery Services vault for up to 10 years. You can store up to 1000 databases per vault. You can select any
backup in the vault to restore it as a new database.
IMPORTANT
Long-Term Backup Retention is currently in preview and available in the following regions: Australia East, Australia
Southeast, Brazil South, Central US, East Asia, East US, East US 2, India Central, India South, Japan East, Japan West, North
Central US, North Europe, South Central US, Southeast Asia, West Europe, and West US.
NOTE
You can enable up to 200 databases per vault during a 24-hour period. Therefore, we recommend that you use a
separate vault for each server to minimize the impact of this limit.
TIP
For a how-to guide, see Configure and restore from Azure SQL Database long-term backup retention
To configure, manage, and restore from long-term backup retention of automated backups in an Azure
Recovery Services vault using PowerShell, see Configure and restore from Azure SQL Database long-term
backup retention.
NOTE
The backups already in the vault are not be impacted. They are automatically deleted by the Recovery Service when their
retention period expires.
Next steps
Database backups are an essential part of any business continuity and disaster recovery strategy because they
protect your data from accidental corruption or deletion. To learn about the other Azure SQL Database business
continuity solutions, see Business continuity overview.
Recover an Azure SQL database using automated
database backups
4/14/2017 • 6 min to read • Edit Online
SQL Database provides these options for database recovery using automated database backups and backups in
long-term retention. You can restore from a database backup to:
A new database on the same logical server recovered to a specified point in time within the retention period.
A database on the same logical server recovered to the deletion time for a deleted database.
A new database on any logical server in any region recovered to the point of the most recent daily backups in
geo-replicated blob storage (RA-GRS).
You can also use automated database backups to create a database copy on any logical server in any region.
Recovery time
The recovery time to restore a database using automated database backups is impacted by several factors:
The size of the database
The performance level of the database
The number of transaction logs involved
The amount of activity that needs to be replayed to recover to the restore point
The network bandwidth if the restore is to a different region
The number of concurrent restore requests being processed in the target region.
For a very large, and/or active database, the restore may take several hours. If there is prolonged outage
in a region, it is possible that there are large numbers of Geo-Restore requests being processed by other
regions. When there are many requests, the recovery time may increase for databases in that region.
Most database restores complete within 12 hours.
There is no built-in functionality to do bulk restore. The Azure SQL Database: Full Server Recovery script
is an example of one way of accomplishing this task.
IMPORTANT
To recover using automated backups, you must be a member of the SQL Server Contributor role in the subscription or be
the subscription owner. You can recover using the Azure portal, PowerShell, or the REST API. You cannot use Transact-
SQL.
Point-In-Time Restore
You can restore an existing database to an earlier point in time as a new database on the same logical server
using the Azure portal, PowerShell, or the REST API.
IMPORTANT
You cannot overwrite the existing database during restore.
The database can be restored to any service tier or performance level, and as a single database or into an elastic
pool. Ensure you have sufficient resources on the logical server or in the elastic pool to which you are restoring
the database. Once complete, the restored database is a normal, fully accessible, online database. The restored
database is charged at normal rates based on its service tier and performance level. You do not incur charges
until the database restore is complete.
You generally restore a database to an earlier point for recovery purposes. When doing so, you can treat the
restored database as a replacement for the original database or use it to retrieve data from and then update the
original database.
Database replacement: If the restored database is intended as a replacement for the original database, you
should verify the performance level and/or service tier are appropriate and scale the database if necessary.
You can rename the original database and then give the restored database the original name using the
ALTER DATABASE command in T-SQL.
Data recovery: If you plan to retrieve data from the restored database to recover from a user or application
error, you need to write and execute the necessary data recovery scripts to extract data from the restored
database to the original database. Although the restore operation may take a long time to complete, the
restoring database is visible in the database list throughout the restore process. If you delete the database
during the restore, the restore operation is canceled and you are not charged for the database that did not
complete the restore.
Azure portal
To recover to a point in time using the Azure portal, open the page for your database and click Restore on the
toolbar.
IMPORTANT
If you delete an Azure SQL Database server instance, all its databases are also deleted and cannot be recovered. There is
currently no support for restoring a deleted server.
Azure portal
To recover a deleted database during its retention period using the Azure portal, open the page for your server
and in the Operations area, click Deleted databases.
Geo-Restore
You can restore a SQL database on any server in any Azure region from the most recent geo-replicated full and
differential backups. Geo-Restore uses a geo-redundant backup as its source and can be used to recover a
database even if the database or datacenter is inaccessible due to an outage.
Geo-Restore is the default recovery option when your database is unavailable because of an incident in the
region where the database is hosted. If a large-scale incident in a region results in unavailability of your
database application, you can restore a database from the geo-replicated backups to a server in any other
region. There is a delay between when a differential backup is taken and when it is geo-replicated to an Azure
blob in a different region. This delay can be up to an hour, so, if a disaster occurs, there can be up to one hour
data loss. The following illustration shows restore of the database from the last available backup in another
region.
For detailed information about using Geo-Restore to recover from an outage, see Recover from an outage
IMPORTANT
Recovery from backups is the most basic of the disaster recovery solutions available in SQL Database with the longest
RPO and Estimate Recovery Time (ERT). For Basic databases with maximum size of 2 GB Geo-Restore, provides a
reasonable DR solution with an ERT of 12 hours. For larger Standard or Premium databases, if shorter recovery times are
desired, or to reduce the likelihood of data loss you should consider using Active Geo-Replication. Active Geo-Replication
offers a much lower RPO and ERT as it only requires you initiate a failover to a continuously replicated secondary. For
details, see Active Geo-Replication.
Azure portal
To geo-restore a database during its retention period using the Azure portal, open the SQL Databases page and
then click Add. In the Select source text box, select Backup. Specify the backup from which to perform the
recovery in the region and on the server of your choice.
REST API
API DESCRIPTION
Get Create or Update Database Status Returns the status during a restore operation
Summary
Automatic backups protect your databases from user and application errors, accidental database deletion, and
prolonged outages. This built-in capability is available for all service tiers and performance levels.
Next steps
For a business continuity overview and scenarios, see Business continuity overview
To learn about Azure SQL Database automated backups, see SQL Database automated backups
To learn about long-term backup retention, see Long-term backup retention
To configure, manage, and restore from long-term retention of automated backups in an Azure Recovery
Services vault using the Azure portal, see Configure and use long-term backup retention.
To learn about faster recovery options, see Active-Geo-Replication
Overview: SQL Database Active Geo-Replication
4/14/2017 • 11 min to read • Edit Online
Active Geo-Replication enables you to configure up to four readable secondary databases in the same or
different data center locations (regions). Secondary databases are available for querying and for failover in the
case of a data center outage or the inability to connect to the primary database. Active geo-replication must be
between databases within the same subscription.
NOTE
Active Geo-Replication (readable secondaries) is now available for all databases in all service tiers. In April 2017, the
non-readable secondary type will be retired and existing non-readable databases will automatically be upgraded to
readable secondaries.
You can configure Active Geo-Replication using the Azure portal, PowerShell, Transact-SQL, or the REST API -
Create or Update Database.
If for any reason your primary database fails, or simply needs to be taken offline, you can failover to any of
your secondary databases. When failover is activated to one of the secondary databases, all other secondaries
are automatically linked to the new primary.
You can failover to a secondary using the Azure portal, PowerShell, Transact-SQL, the REST API - Planned
Failover, or REST API - Unplanned Failover.
After failover, ensure the authentication requirements for your server and database are configured on the new
primary. For details, see SQL Database security after disaster recovery.
The Active Geo-Replication feature implements a mechanism to provide database redundancy within the same
Microsoft Azure region or in different regions (geo-redundancy). Active Geo-Replication asynchronously
replicates committed transactions from a database to up to four copies of the database on different servers,
using read committed snapshot isolation (RCSI) for isolation. When Active Geo-Replication is configured, a
secondary database is created on the specified server. The original database becomes the primary database.
The primary database asynchronously replicates committed transactions to each of the secondary databases.
Only full transactions are replicated. While at any given point, the secondary database might be slightly behind
the primary database, the secondary data is guaranteed to never have partial transactions. The specific RPO
data can be found at Overview of Business Continuity.
One of the primary benefits of Active Geo-Replication is that it provides a database-level disaster recovery
solution with low recovery time. When you place the secondary database on a server in a different region, you
add maximum resilience to your application. Cross-region redundancy enables applications to recover from a
permanent loss of an entire datacenter or parts of a datacenter caused by natural disasters, catastrophic
human errors, or malicious acts. The following figure shows an example of Active Geo-Replication configured
with a primary in the North Central US region and secondary in the South Central US region.
Another key benefit is that the secondary databases are readable and can be used to offload read-only
workloads such as reporting jobs. If you only intend to use the secondary database for load-balancing, you can
create it in the same region as the primary. Creating a secondary in the same region, does not increase the
application's resilience to catastrophic failures.
Other scenarios where Active Geo-Replication can be used include:
Database migration: You can use Active Geo-Replication to migrate a database from one server to
another online with minimum downtime.
Application upgrades: You can create an extra secondary as a fail back copy during application upgrades.
To achieve real business continuity, adding database redundancy between datacenters is only part of the
solution. Recovering an application (service) end-to-end after a catastrophic failure requires recovery of all
components that constitute the service and any dependent services. Examples of these components include
the client software (for example, a browser with a custom JavaScript), web front ends, storage, and DNS. It is
critical that all components are resilient to the same failures and become available within the recovery time
objective (RTO) of your application. Therefore, you need to identify all dependent services and understand the
guarantees and capabilities they provide. Then, you must take adequate steps to ensure that your service
functions during the failover of the services on which it depends. For more information about designing
solutions for disaster recovery, see Designing Cloud Solutions for Disaster Recovery Using Active Geo-
Replication.
NOTE
The log replay is delayed on the secondary database if there are schema updates that it is receiving from the Primary
that require a schema lock on the secondary database.
Active geo-replication of elastic pool databases: Active Geo-Replication can be configured for any
database in any elastic pool. The secondary database can be in another elastic pool. For regular databases,
the secondary can be an elastic pool and vice versa as long as the service tiers are the same.
Configurable performance level of the secondary database: A secondary database can be created
with lower performance level than the primary. Both primary and secondary databases are required to
have the same service tier. This option is not recommended for applications with high database write
activity because the increased replication lag increases the risk of substantial data loss after a failover. In
addition, after failover the application’s performance is impacted until the new primary is upgraded to a
higher performance level. The log IO percentage chart on Azure portal provides a good way to estimate the
minimal performance level of the secondary that is required to sustain the replication load. For example, if
your Primary database is P6 (1000 DTU) and its log IO percent is 50% the secondary needs to be at least P4
(500 DTU). You can also retrieve the log IO data using sys.resource_stats or sys.dm_db_resource_stats
database views. For more information on the SQL Database performance levels, see SQL Database options
and performance.
User-controlled failover and failback: A secondary database can explicitly be switched to the primary
role at any time by the application or the user. During a real outage the “unplanned” option should be used,
which immediately promotes a secondary to be the primary. When the failed primary recovers and is
available again, the system automatically marks the recovered primary as a secondary and bring it up-to-
date with the new primary. Due to the asynchronous nature of replication, a small amount of data can be
lost during unplanned failovers if a primary fails before it replicates the most recent changes to the
secondary. When a primary with multiple secondaries fails over, the system automatically reconfigures the
replication relationships and links the remaining secondaries to the newly promoted primary without
requiring any user intervention. After the outage that caused the failover is mitigated, it may be desirable to
return the application to the primary region. To do that, the failover command should be invoked with the
“planned” option.
Keeping credentials and firewall rules in sync: We recommend using database firewall rules for geo-
replicated databases so these rules can be replicated with the database to ensure all secondary databases
have the same firewall rules as the primary. This approach eliminates the need for customers to manually
configure and maintain firewall rules on servers hosting both the primary and secondary databases.
Similarly, using contained database users for data access ensures both primary and secondary databases
always have the same user credentials so during a failover, there is no disruptions due to mismatches with
logins and passwords. With the addition of Azure Active Directory, customers can manage user access to
both primary and secondary databases and eliminating the need for managing credentials in databases
altogether.
NOTE
The delay caused by a sp_wait_for_database_copy_sync procedure call can be significant. The delay depends on the
size of the transaction log length at the moment and this call does not return until the entire log is replicated. Avoid
calling this procedure unless absolutely necessary.
NOTE
Many new features of Active Geo-Replication are only supported using Azure Resource Manager based Azure SQL REST
API and Azure SQL Database PowerShell cmdlets. The (classic) REST API and Azure SQL Database (classic) cmdlets are
supported for backward compatibility so using the Azure Resource Manager-based APIs are recommended.
Transact-SQL
COMMAND DESCRIPTION
ALTER DATABASE (Azure SQL Database) Use ADD SECONDARY ON SERVER argument to create a
secondary database for an existing database and starts data
replication
ALTER DATABASE (Azure SQL Database) Use REMOVE SECONDARY ON SERVER to terminate a data
replication between a SQL Database and the specified
secondary database.
sys.geo_replication_links (Azure SQL Database) Returns information about all existing replication links for
each database on the Azure SQL Database logical server.
sys.dm_geo_replication_link_status (Azure SQL Database) Gets the last replication time, last replication lag, and other
information about the replication link for a given SQL
database.
sys.dm_operation_status (Azure SQL Database) Shows the status for all database operations including the
status of the replication links.
sp_wait_for_database_copy_sync (Azure SQL Database) causes the application to wait until all committed
transactions are replicated and acknowledged by the active
secondary database.
PowerShell
CMDLET DESCRIPTION
REST API
API DESCRIPTION
Get Create or Update Database Status Returns the status during a create operation.
Set Secondary Database as Primary (Planned Failover) Promote a secondary database in a Geo-Replication
partnership to become the new primary database.
Set Secondary Database as Primary (Unplanned Failover) To force a failover to the secondary database and set the
secondary as the primary.
Get Replication Links Gets all replication links for a given SQL database in a geo-
replication partnership. It retrieves the information visible in
the sys.geo_replication_links catalog view.
Get Replication Link Gets a specific replication link for a given SQL database in a
geo-replication partnership. It retrieves the information
visible in the sys.geo_replication_links catalog view.
Next steps
For a business continuity overview and scenarios, see Business continuity overview
To learn about Azure SQL Database automated backups, see SQL Database automated backups.
To learn about using automated backups for recovery, see Restore a database from the service-initiated
backups.
To learn about using automated backups for archiving, see database copy.
To learn about authentication requirements for a new primary server and database, see SQL Database
security after disaster recovery.
Configure and manage Azure SQL Database security
for geo-restore or failover
2/16/2017 • 4 min to read • Edit Online
NOTE
Active Geo-Replication is now available for all databases in all service tiers.
Setting up logins on the target server involves three steps outlined below:
1. Determine logins with access to the primary database:
The first step of the process is to determine which logins must be duplicated on the target server. This is
accomplished with a pair of SELECT statements, one in the logical master database on the source server and one
in the primary database itself.
Only the server admin or a member of the LoginManager server role can determine the logins on the source
server with the following SELECT statement.
Only a member of the db_owner database role, the dbo user, or server admin, can determine all of the database
user principals in the primary database.
NOTE
The INFORMATION_SCHEMA and sys users have NULL SIDs, and the guest SID is 0x00. The dbo SID may start with
0x01060000000001648000000000048454, if the database creator was the server admin instead of a member of
DbManager.
Next steps
For more information on managing database access and logins, see SQL Database security: Manage database
access and login security.
For more information on contained database users, see Contained Database Users - Making Your Database
Portable.
For information about using and configuring Active Geo-Replication, see Active Geo-Replication
For informatin about using Geo-Restore, see Geo-Restore
Application design for cloud disaster recovery using
Active Geo-Replication in SQL Database
1/23/2017 • 10 min to read • Edit Online
NOTE
Active Geo-Replication is now available for all databases in all tiers.
Learn how to use Active Geo-Replication in SQL Database to design database applications resilient to regional
failures and catastrophic outages. For business continuity planning, consider the application deployment topology,
the service level agreement you are targeting, traffic latency, and costs. In this article, we look at the common
application patterns, and discuss the benefits and trade-offs of each option. For information about Active Geo-
Replication with Elastic Pools, see Elastic Pool disaster recovery strategies.
NOTE
Azure traffic manager is used throughout this article for illustration purposes only. You can use any load-balancing solution
that supports failover routing method.
In addition to the main application instances, you should consider deploying a small worker role application that
monitors your primary database by issuing periodic T-SQL read-only (RO) commands. You can use it to
automatically trigger failover, to generate an alert on your application's admin console, or to do both. To ensure
that monitoring is not impacted by region-wide outages, you should deploy the monitoring application instances
to each region and have each instance connected to the primary database in the primary region and the
secondary database in the local region.
NOTE
Both monitoring applications should be active and probe both primary and secondary databases. The latter can be used to
detect a failure in the secondary region and alert when the application is not protected.
The following diagram shows this configuration before an outage.
After an outage in the primary region, the monitoring application detects that the primary database is not
accessible and registers an alert. Depending on your application SLA, you can decide how many consecutive
monitoring probes should fail before it declares a database outage. To achieve coordinated failover of the
application end-point and the database, you should have the monitoring application perform the following steps:
1. Update the status of the primary end-point in order to trigger end-point failover.
2. Call the secondary database to initiate database failover.
After failover, the application will process the user requests in the secondary region but will remain co-located
with the database because the primary database will now be in the secondary region. This scenario is illustrated
by the next diagram. In all diagrams, solid lines indicate active connections, dotted lines indicate suspended
connections and stop signs indicate action triggers.
If an outage happens in the secondary region, the replication link between the primary and the secondary
database is suspended and the monitoring application registers an alert that the primary database is exposed. The
application's performance is not impacted, but the application operates exposed and therefore at higher risk in
case both regions fail in succession.
NOTE
We only recommend deployment configurations with a single DR region. This is because most of the Azure geographies
have two regions. These configurations will not protect your application from a catastrophic failure of both regions. In an
unlikely event of such a failure, you can recover your databases in a third region using geo-restore operation.
Once the outage is mitigated, the secondary database is automatically synchronized with the primary. During
synchronization, performance of the primary could be slightly impacted depending on the amount of data that
needs to be synchronized. The following diagram illustrates an outage in the secondary region.
The key advantages of this design pattern are:
The SQL connection string is set during the application deployment in each region and doesn’t change after
failover.
The application's performance is not impacted by failover as the application and the database are always co-
located.
The main tradeoff is that the redundant application instance in the secondary region is only used for disaster
recovery.
NOTE
While this pattern uses more than one secondary database, only one of the secondaries would be used for failover for the
reasons noted earlier. Because this pattern requires read-only access to the secondary, it requires Active Geo-Replication.
Traffic manager should be configured for performance routing to direct the user connections to the application
instance closest to the user's geographic location. The following diagram illustrates this configuration before an
outage.
If a database outage is detected in the primary region, you initiate failover of the primary database to one of the
secondary regions, changing the location of the primary database. The traffic manager automatically excludes the
offline end-point from the routing table, but continues routing the end-user traffic to the remaining online
instances. Because the primary database is now in a different region, all online instances must change their read-
write SQL connection string to connect to the new primary. It is important that you make this change prior to
initiating the database failover. The read-only SQL connection strings should remain unchanged as they always
point to the database in the same region. The failover steps are:
1. Change read-write SQL connection strings to point to the new primary.
2. Call the designated secondary database in order to initiate database failover.
The following diagram illustrates the new configuration after the failover.
In case of an outage in one of the secondary regions, the traffic manager automatically removes the offline end-
point in that region from the routing table. The replication channel to the secondary database in that region is
suspended. Because the remaining regions get additional user traffic in this scenario, the application's
performance is impacted during the outage. Once the outage is mitigated, the secondary database in the impacted
region is immediately synchronized with the primary. During synchronization performance of the primary could
be slightly impacted depending on the amount of data that needs to be synchronized. The following diagram
illustrates an outage in one of the secondary regions.
The key advantage of this design pattern is that you can scale the application workload across multiple
secondaries to achieve the optimal end-user performance. The tradeoffs of this option are:
Read-write connections between the application instances and database have varying latency and cost
Application performance is impacted during the outage
Application instances are required to dynamically change the SQL connection string after database failover.
NOTE
A similar approach can be used to offload specialized workloads such as reporting jobs, business intelligence tools, or
backups. Typically these workloads consume significant database resources therefore it is recommended that you designate
one of the secondary databases for them with the performance level matched to the anticipated workload.
NOTE
Because this pattern requires read-only access to the secondary it requires Active Geo-Replication.
In case of an outage in the secondary region, the traffic manager marks the application end-point in the primary
region as degraded and the replication channel is suspended. However, this outage does not impact the
application's performance during the outage. Once the outage is mitigated, the secondary database is
immediately synchronized with the primary. During synchronization performance of the primary could be slightly
impacted depending on the amount of data that needs to be synchronized.
This design pattern has several advantages:
It avoids data loss during the temporary outages.
It does not require you to deploy a monitoring application as the recovery is triggered by traffic manager.
Downtime depends only on how quickly traffic manager detects the connectivity failure, which is configurable.
The tradeoffs are:
Application must be able to operate in read-only mode.
It is required to dynamically switch to it when it is connected to a read-only database.
Resumption of read-write operations requires recovery of the primary region, which means full data access
may be disabled for hours or even days.
NOTE
In case of a permanent service outage in the region, you must manually activate database failover and accept the data loss.
The application will be functional in the secondary region with read-write access to the database.
Active-passive deployment for disaster Read-write access < 5 sec Failure detection time + failover API call
recovery with co-located database + application verification test
access
Active-active deployment for Read-write access < 5 sec Failure detection time + failover API call
application load balancing + SQL connection string change +
application verification test
Active-passive deployment for data Read-only access < 5 sec Read-write Read-only access = connectivity failure
preservation access = zero detection time + application verification
test
Read-write access = time to mitigate
the outage
Next steps
To learn about Azure SQL Database automated backups, see SQL Database automated backups
For a business continuity overview and scenarios, see Business continuity overview
To learn about using automated backups for recovery, see restore a database from the service-initiated
backups
To learn about faster recovery options, see Active-Geo-Replication
To learn about using automated backups for archiving, see database copy
For information about Active Geo-Replication with Elastic Pools, see Elastic Pool disaster recovery strategies.
Disaster recovery strategies for applications using
SQL Database elastic pools
4/13/2017 • 14 min to read • Edit Online
Over the years we have learned that cloud services are not foolproof and catastrophic incidents can and will
happen. SQL Database provides a number of capabilities to provide for the business continuity of your application
when these incidents occur. Elastic pools and single databases support the same kind of disaster recovery
capabilities. This article describes several DR strategies for elastic pools that leverage these SQL Database business
continuity features.
For the purposes of this article we will use the canonical SaaS ISV application pattern:
A modern cloud based web application provisions one SQL database for each end user. The ISV has a large
number of customers and therefore uses many databases, known as tenant databases. Because the tenant
databases typically have unpredictable activity patterns, the ISV uses an elastic pool to make the database cost
very predictable over extended periods of time. The elastic pool also simplifies the performance management
when the user activity spikes. In addition to the tenant databases the application also uses several databases to
manage user profiles, security, collect usage patterns etc. Availability of the individual tenants does not impact the
application’s availability as whole. However, the availability and performance of management databases is
critical for the application’s function and if the management databases are offline the entire application is offline.
In the rest of the paper we will discuss the DR strategies covering a range of scenarios from the cost sensitive
startup applications to the ones with stringent availability requirements.
If the outage was temporary, it is possible that the primary region will be recovered by Azure before all the
restores are complete in the DR region. In this case, you should orchestrate moving the application back to the
primary region. The process will take the steps illustrated on the next diagram.
Cancel all outstanding geo-restore requests.
Failover the management database(s) to the primary region (5). Note: After the region’s recovery the old
primaries have automatically become secondaries. Now they will switch roles again.
Change the application's connection string to point back to the primary region. Now all new accounts and
tenant databases will be created in the primary region. Some existing customers will see their data temporarily
unavailable.
Set all databases in the DR pool to read-only to ensure they cannot be modified in the DR region (6).
For each database in the DR pool that has changed since the recovery, rename or delete the corresponding
databases in the primary pool (7).
Copy the updated databases from the DR pool to the primary pool (8).
Delete the DR pool (9)
At this point your application will be online in the primary region with all tenant databases available in the primary
pool.
The key benefit of this strategy is low ongoing cost for data tier redundancy. Backups are taken automatically by
the SQL Database service with no application rewrite and at no additional cost. The cost is incurred only when the
elastic databases are restored. The trade-off is that the complete recovery of all tenant databases will take
significant time. It will depend on the total number of restores you will initiate in the DR region and overall size of
the tenant databases. Even if you prioritize some tenants' restores over others, you will be competing with all the
other restores that are initiated in the same region as the service will arbitrate and throttle to minimize the overall
impact on the existing customers' databases. In addition, the recovery of the tenant databases cannot start until
the new elastic pool in the DR region is created.
As in the first scenario, the management database(s) will be quite active so you use a single geo-replicated
database for it (1). This will ensure the predictable performance for new customer subscriptions, profile updates
and other management operations. The region in which the primaries of the management database(s) reside will
be the primary region and the region in which the secondaries of the management database(s) reside will be the
DR region.
The paying customers’ tenant databases will have active databases in the “paid” pool provisioned in the primary
region. You should provision a secondary pool with the same name in the DR region. Each tenant would be geo-
replicated to the secondary pool (2). This will enable a quick recovery of all tenant databases using failover.
If an outage occurs in the primary region, the recovery steps to bring your application online are illustrated in the
next diagram:
The key benefit of this strategy is that it provides the highest SLA for the paying customers. It also guarantees
that the new trials are unblocked as soon as the trial DR pool is created. The trade-off is that this setup will
increase the total cost of the tenant databases by the cost of the secondary DR pool for paid customers. In
addition, if the secondary pool has a different size, the paying customers will experience lower performance after
failover until the pool upgrade in the DR region is completed.
As in the previous scenarios, the management database(s) will be quite active so you should configure them as
single geo-replicated database(s) (1). This will ensure the predictable performance of the new customer
subscriptions, profile updates and other management operations. Region A would be the primary region for the
management database(s) and the region B will be used for recovery of the management database(s).
The paying customers’ tenant databases will be also geo-replicated but with primaries and secondaries split
between region A and region B (2). This way the tenant primary databases impacted by the outage can failover to
the other region and become available. The other half of the tenant databases will not be impacted at all.
The next diagram illustrates the recovery steps to take if an outage occurs in region A.
NOTE
The failover operation is asynchronous. To minimize the recovery time it is important that you execute the tenant databases'
failover command in batches of at least 20 databases.
At this point your application is back online in region B. All paying customers have access to their data while the
trial customers will experience delay when accessing their data.
When region A is recovered you need to decide if you want to use region B for trial customers or failback to using
the trial customers pool in region A. One criteria could be the % of trial tenant databases modified since the
recovery. Regardless of that decision you will need to re-balance the paid tenants between two pools. the next
diagram illustrates the process when the trial tenant databases fail back to region A.
Cancel all outstanding geo-restore requests to trial DR pool.
Failover the management database (8). After the region’s recovery, the old primary had automatically became
the secondary. Now it becomes the primary again.
Select which paid tenant databases will fail back to pool 1 and initiate failover to their secondaries (9). After the
region’s recovery all databases in pool 1 automatically became secondaries. Now 50% of them will become
primaries again.
Reduce the size of pool 2 to the original eDTU (10).
Set all restored trial databases in the region B to read-only (11).
For each database in the trial DR pool that has changed since the recovery rename or delete the corresponding
database in the trial primary pool (12).
Copy the updated databases from the DR pool to the primary pool (13).
Delete the DR pool (14)
The key benefits of this strategy are:
It supports the most aggressive SLA for the paying customers because it ensures that an outage cannot impact
more than 50% of the tenant databases.
It guarantees that the new trials are unblocked as soon as the trail DR pool is created during the recovery.
It allows more efficient use of the pool capacity as 50% of secondary databases in pool 1 and pool 2 are
guaranteed to be less active then the primary databases.
The main trade-offs are:
The CRUD operations against the management database(s) will have lower latency for the end users connected
to region A than for the end users connected to region B as they will be executed against the primary of the
management database(s).
It requires more complex design of the management database. For example, each tenant record would have to
have a location tag that needs to be changed during failover and failback.
The paying customers may experience lower performance than usual until the pool upgrade in region B is
completed.
Summary
This article focuses on the disaster recovery strategies for the database tier used by a SaaS ISV multi-tenant
application. The strategy you choose should be based on the needs of the application, such as the business model,
the SLA you want to offer to your customers, budget constraint etc.. Each described strategy outlines the benefits
and trade-off so you could make an informed decision. Also, your specific application will likely include other
Azure components. So you should review their business continuity guidance and orchestrate the recovery of the
database tier with them. To learn more about managing recovery of database applications in Azure, refer to
Designing cloud solutions for disaster recovery .
Next steps
To learn about Azure SQL Database automated backups, see SQL Database automated backups
For a business continuity overview and scenarios, see Business continuity overview
To learn about using automated backups for recovery, see restore a database from the service-initiated
backups
To learn about faster recovery options, see Active-Geo-Replication
To learn about using automated backups for archiving, see database copy
Managing rolling upgrades of cloud applications
using SQL Database Active Geo-Replication
1/23/2017 • 8 min to read • Edit Online
NOTE
Active Geo-Replication is now available for all databases in all tiers.
Learn how to use Geo-Replication in SQL Database to enable rolling upgrades of your cloud application. Because
upgrade is a disruptive operation, it should be part of your business continuity planning and design. In this article
we look at two different methods of orchestrating the upgrade process, and discuss the benefits and trade-offs of
each option. For the purposes of this article we will use a simple application that consists of a web site connected
to a single database as its data tier. Our goal is to upgrade version 1 of the application to version 2 without any
significant impact on the end user experience.
When evaluating the upgrade options you should consider the following factors:
Impact on application availability during upgrades. How long the application function may be limited or
degraded.
Ability to roll back in case of an upgrade failure.
Vulnerability of the application if an unrelated catastrophic failure occurs during the upgrade.
Total dollar cost. This includes additional redundancy and incremental costs of the temporary components used
by the upgrade process.
NOTE
Note the preparation steps will not impact the application in the production slot and it can function in full access mode.
Once the preparation steps are completed the application is ready for the actual upgrade. The following diagram
illustrates the steps involved in the upgrade process.
1. Set the primary database in the production slot to read-only mode (3). This will guarantee that the production
instance of the application (V1) will remain read-only during the upgrade thus preventing the data divergence
between the V1 and V2 database instances.
2. Disconnect the secondary database using the planned termination mode (4). It will create a fully synchronized
independent copy of the primary database. This database will be upgraded.
3. Turn the primary database to read-write mode and run the upgrade script in the stage slot (5).
If the upgrade completed successfully you are now ready to switch the end users to the staged copy the
application. It will now become the production slot of the application. This involves a few more steps as illustrated
on the following diagram.
1. Switch the online endpoint in the WATM profile to contoso-2.azurewebsites.net, which points to the V2 version
of the web site (6). It now becomes the production slot with the V2 application and the end user traffic is
directed to it.
2. If you no longer need the V1 application components so you can safely remove them (7).
If the upgrade process is unsuccessful, for example due to an error in the upgrade script, the stage slot should be
considered compromised. To rollback the application to the pre-upgrade state you simply revert the application in
the production slot to full access. The steps involved are shown on the next diagram.
1. Set the database copy to read-write mode (8). This will restore the full V1 functionally in the production slot.
2. Perform the root cause analysis and remove the compromised components in the stage slot (9).
At this point the application is fully functional and the upgrade steps can be repeated.
NOTE
The rollback does not require changes in WATM profile as it already points to contoso-1.azurewebsites.net as the active
endpoint.
The key advantage of this option is that you can upgrade a application in a single region using a set of simple
steps. The dollar cost of the upgrade is relatively low. The main tradeoff is that if a catastrophic failure occurs
during the upgrade the recovery to the pre-upgrade state will involve re-deployment of the application in a
different region and restoring the database from backup using geo-restore. This process will result in significant
downtime.
NOTE
Note the preparation steps will not impact the application in the production slot and it can function in full access mode.
Once the preparation steps are completed, the stage slot is ready for the upgrade. The following diagram illustrates
the upgrade steps.
1. Set the primary database in the production slot to read-only mode (6). This will guarantee that the production
instance of the application (V1) will remain read-only during the upgrade thus preventing the data divergence
between the V1 and V2 database instances.
2. Disconnect the secondary database in the same region using the planned termination mode (7). It will create a
fully synchronized independent copy of the primary database, which will automatically become a primary after
the termination. This database will be upgraded.
3. Turn the primary database in the stage slot to read-write mode and run the upgrade script (8).
If the upgrade completed successfully you are now ready to switch the end users to the V2 version of the
application. The following diagram illustrates the steps involved.
1. Switch the active endpoint in the WATM profile to contoso-2.azurewebsites.net, which now points to the V2
version of the web site (9). It now becomes a production slot with the V2 application and end user traffic is
directed to it.
2. If you no longer need the V1 application so you can safely remove it (10 and 11).
If the upgrade process is unsuccessful, for example due to an error in the upgrade script, the stage slot should be
considered compromised. To rollback the application to the pre-upgrade state you simply revert to using the
application in the production slot with full access. The steps involved are shown on the next diagram.
1. Set the primary database copy in the production slot to read-write mode (12). This will restore the full V1
functionally in the production slot.
2. Perform the root cause analysis and remove the compromised components in the stage slot (13 and 14).
At this point the application is fully functional and the upgrade steps can be repeated.
NOTE
The rollback does not require changes in WATM profile as it already points to contoso-1.azurewebsites.net as the active
endpoint.
The key advantage of this option is that you can upgrade both the application and its geo-redundant copy in
parallel without compromising your business continuity during the upgrade. The main tradeoff is that it requires
double redundancy of each application component and therefore incurs higher dollar cost. It also involves a more
complicated workflow.
Summary
The two upgrade methods described in the article differ in complexity and the dollar cost but they both focus on
minimizing the time when the end user is limited to read-only operations. That time is directly defined by the
duration of the upgrade script. It does not depend on the database size, the service tier you chose, the web site
configuration and other factors that you cannot easily control. This is because all the preparation steps are
decoupled from the upgrade steps and can be done without impacting the production application. The efficiency of
the upgrade script is the key factor that determines the end-user experience during upgrades. So the best way you
can improve it is by focusing your efforts on making the upgrade script as efficient as possible.
Next steps
For a business continuity overview and scenarios, see Business continuity overview
To learn about Azure SQL Database automated backups, see SQL Database automated backups
To learn about using automated backups for recovery, see restore a database from automated backups
To learn about faster recovery options, see Active-Geo-Replication
To learn about using automated backups for archiving, see database copy
Additionale Resources
The following pages will help you learn about the specific operations required to implement the upgrade workflow:
Add secondary database
Failover database to secondary
Disconnect Geo-Replication secondary
Geo-restore database
Drop database
Copy database
Set database to read-only or read-write mode
SQL Database Application Development Overview
4/14/2017 • 2 min to read • Edit Online
This article walks through the basic considerations that a developer should be aware of when writing code to
connect to Azure SQL Database.
TIP
For a tutorial showing you how to create a server, create a server-based firewall, view server properties, connect using SQL
Server Management Studio, query the master database, create a sample database and a blank database, query database
properties, connect using SQL Server Management Studio, and query the sample database, see Get Started Tutorial.
Tools
You can leverage open source tools like cheetah, sql-cli, VS Code. Additionally, Azure SQL Database works with
Microsoft tools like Visual Studio and SQL Server Management Studio. You can also use the Azure Management
Portal, PowerShell, and REST APIs help you gain additional productivity.
Resource limitations
Azure SQL Database manages the resources available to a database using two different mechanisms: Resources
Governance and Enforcement of Limits.
More Information: Azure SQL Database resource limits
Security
Azure SQL Database provides resources for limiting access, protecting data, and monitoring activities on a SQL
Database.
More Information: Securing your SQL Database
Authentication
Azure SQL Database supports both SQL Server authentication users and logins, as well as Azure Active
Directory authentication users and logins.
You need to specify a particular database, instead of defaulting to the master database.
You cannot use the Transact-SQL USE myDatabaseName; statement on SQL Database to switch to another
database.
More information: SQL Database security: Manage database access and login security
Resiliency
When a transient error occurs while connecting to SQL Database, your code should retry the call. We recommend
that retry logic use backoff logic, so that it does not overwhelm the SQL Database with multiple clients retrying
simultaneously.
Code samples: For code samples that illustrate retry logic, see samples for the language of your choice at:
Connection libraries for SQL Database and SQL Server
More information: Error messages for SQL Database client programs
Managing Connections
In your client connection logic, override the default timeout to be 30 seconds. The default of 15 seconds is too
short for connections that depend on the internet.
If you are using a connection pool, be sure to close the connection the instant your program is not actively
using it, and is not preparing to reuse it.
Network Considerations
On the computer that hosts your client program, ensure the firewall allows outgoing TCP communication on
port 1433. More information: Configure an Azure SQL Database firewall
If your client program connects to SQL Database while your client runs on an Azure virtual machine (VM), you
must open certain port ranges on the VM. More information: Ports beyond 1433 for ADO.NET 4.5 and SQL
Database
Client connections to Azure SQL Database sometimes bypass the proxy and interact directly with the database.
Ports other than 1433 become important. More information: Ports beyond 1433 for ADO.NET 4.5 and SQL
Database
Next steps
Explore all the capabilities of SQL Database
Connection libraries for SQL Database and SQL
Server
4/14/2017 • 1 min to read • Edit Online
This topic lists each library or driver that client programs can use when connecting to Azure SQL Database or to
Microsoft SQL Server.
Ruby Windows, Linux, Mac Ruby Driver for SQL Server Install
Related links
SQL Server Drivers, for connecting from a client
Connect to SQL Database by using .NET (C#)
Connect to SQL Database by using PHP
Connect to SQL Database by using Node.js
Connect to SQL Database by using Java
Connect to SQL Database by using Python
Connect to SQL Database by using Ruby
Design patterns for multitenant SaaS applications
and Azure SQL Database
4/12/2017 • 13 min to read • Edit Online
In this article, you can learn about the requirements and common data architecture patterns of multitenant
software as a service (SaaS) database applications that run in a cloud environment. It also explains the factors
you need to consider and the trade-offs of different design patterns. Elastic pools and elastic tools in Azure SQL
Database can help you meet your specific requirements without compromising other objectives.
Developers sometimes make choices that work against their long-term best interests when they design tenancy
models for the data tiers of multitenant applications. Initially, at least, a developer might perceive ease of
development and lower cloud service provider costs as more important than tenant isolation or the scalability of
an application. This choice can lead to customer satisfaction concerns and a costly course-correction later.
A multitenant application is an application hosted in a cloud environment and that provides the same set of
services to hundreds or thousands of tenants who do not share or see each other’s data. An example is an SaaS
application that provides services to tenants in a cloud-hosted environment.
Multitenant applications
In multitenant applications, data and workload can be easily partitioned. You can partition data and workload, for
example, along tenant boundaries, because most requests occur within the confines of a tenant. That property is
inherent in the data and the workload, and it favors the application patterns discussed in this article.
Developers use this type of application across the whole spectrum of cloud-based applications, including:
Partner database applications that are being transitioned to the cloud as SaaS applications
SaaS applications built for the cloud from the ground up
Direct, customer-facing applications
Employee-facing enterprise applications
SaaS applications that are designed for the cloud and those with roots as partner database applications typically
are multitenant applications. These SaaS applications deliver a specialized software application as a service to
their tenants. Tenants can access the application service and have full ownership of associated data stored as part
of the application. But to take advantage of the benefits of SaaS, tenants must surrender some control over their
own data. They trust the SaaS service provider to keep their data safe and isolated from other tenants’ data.
Examples of this kind of multitenant SaaS application are MYOB, SnelStart, and Salesforce.com. Each of these
applications can be partitioned along tenant boundaries and support the application design patterns we discuss
in this article.
Applications that provide a direct service to customers or to employees within an organization (often referred to
as users, rather than tenants) are another category on the multitenant application spectrum. Customers
subscribe to the service and do not own the data that the service provider collects and stores. Service providers
have less stringent requirements to keep their customers’ data isolated from each other beyond government-
mandated privacy regulations. Examples of this kind of customer-facing multitenant application are media
content providers like Netflix, Spotify, and Xbox LIVE. Other examples of easily partitionable applications are
customer-facing, Internet-scale applications, or Internet of Things (IoT) applications in which each customer or
device can serve as a partition. Partition boundaries can separate users and devices.
Not all applications partition easily along a single property such as tenant, customer, user, or device. A complex
enterprise resource planning (ERP) application, for example, has products, orders, and customers. It usually has a
complex schema with thousands of highly interconnected tables.
No single partition strategy can apply to all tables and work across an application's workload. This article focuses
on multitenant applications that have easily partitionable data and workloads.
NOTE
An application developer might choose to place different tenants in different database schemas, and then use the schema
name to disambiguate the different tenants. We do not recommend this approach because it usually requires the use of
dynamic SQL, and it can’t be effective in plan caching. In the remainder of this article, we focus on the shared table
approach for this category of multitenant application.
Tenant isolation and resource sharing Elastic pools: Allocate a pool of SQL Database resources and
share the resources across various databases. Also, individual
databases can draw as much resources from the pool as
needed to accommodate capacity demand spikes due to
changes in tenant workloads. The elastic pool itself can be
scaled up or down as needed. Elastic pools also provide ease
of manageability and monitoring and troubleshooting at the
pool level.
Shared models
As described earlier, for most SaaS providers, a shared model approach might pose problems with tenant
isolation issues and complexities with application development and maintenance. However, for multitenant
applications that provide a service directly to consumers, tenant isolation requirements may not be as high a
priority as minimizing cost. They might be able to pack tenants in one or more databases at a high density to
reduce costs. Shared-database models using a single database or multiple sharded databases might result in
additional efficiencies in resource sharing and overall cost. Azure SQL Database provides some features that help
customers build isolation for improved security and management at scale in the data tier.
Database schema
Elastic jobs
Elastic transactions
Summary
Tenant isolation requirements are important for most SaaS multitenant applications. The best option to provide
isolation leans heavily toward the database-per-tenant approach. The other two approaches require investments
in complex application layers that require skilled development staff to provide isolation, which significantly
increases cost and risk. If isolation requirements are not accounted for early in the service development,
retrofitting them can be even more costly in the first two models. The main drawbacks associated with the
database-per-tenant model are related to increased cloud resource costs due to reduced sharing, and
maintaining and managing many databases. SaaS application developers often struggle when they make these
trade-offs.
Although trade-offs might be major barriers with most cloud database service providers, Azure SQL Database
eliminates the barriers with its elastic pool and elastic database capabilities. SaaS developers can combine the
isolation characteristics of a database-per-tenant model and optimize resource sharing and the manageability
improvements of many databases by using elastic pools and associated tools.
Multitenant application providers who have no tenant isolation requirements and who can pack tenants in a
database at a high density might find that shared data models result in additional efficiency in resource sharing
and reduce overall cost. Azure SQL Database elastic database tools, sharding libraries, and security features help
SaaS providers build and manage multitenant applications.
Next steps
Get started with elastic database tools with a sample app that demonstrates the client library.
Create an elastic pool custom dashboard for SaaS with a sample app that uses elastic pools for a cost-effective,
scalable database solution.
Use the Azure SQL Database tools to migrate existing databases to scale out.
To create an elastic pool using the Azure portal, see create an elastic pool.
Learn how to monitor and manage an elastic pool.
Additional resources
What is an Azure elastic pool?
Scaling out with Azure SQL Database
Multitenant applications with elastic database tools and row-level security
Authentication in multitenant apps by using Azure Active Directory and OpenID Connect
Tailspin Surveys application
Elastic database tools and row-level security (RLS) offer a powerful set of capabilities for flexibly and efficiently
scaling the data tier of a multi-tenant application with Azure SQL Database. See Design Patterns for Multi-tenant
SaaS Applications with Azure SQL Database for more information.
This article illustrates how to use these technologies together to build an application with a highly scalable data
tier that supports multi-tenant shards, using ADO.NET SqlClient and/or Entity Framework.
Elastic database tools enables developers to scale out the data tier of an application via industry-standard
sharding practices using a set of .NET libraries and Azure service templates. Managing shards with using the
Elastic Database Client Library helps automate and streamline many of the infrastructural tasks typically
associated with sharding.
Row-level security enables developers to store data for multiple tenants in the same database using security
policies to filter out rows that do not belong to the tenant executing a query. Centralizing access logic with RLS
inside the database, rather than in the application, simplifies maintenance and reduces the risk of error as an
application’s codebase grows.
Using these features together, an application can benefit from cost savings and efficiency gains by storing data for
multiple tenants in the same shard database. At the same time, an application still has the flexibility to offer
isolated, single-tenant shards for “premium” tenants who require stricter performance guarantees since multi-
tenant shards do not guarantee equal resource distribution among tenants.
In short, the elastic database client library’s data dependent routing APIs automatically connect tenants to the
correct shard database containing their sharding key (generally a “TenantId”). Once connected, an RLS security
policy within the database ensures that tenants can only access rows that contain their TenantId. It is assumed that
all tables contain a TenantId column to indicate which rows belong to each tenant.
// Ask shard map to broker a validated connection for the given key
SqlConnection conn = null;
try
{
conn = shardMap.OpenConnectionForKey(shardingKey, connectionStr, ConnectionOptions.Validate);
return conn;
}
catch (Exception)
{
if (conn != null)
{
conn.Dispose();
}
throw;
}
}
// ...
Now the SESSION_CONTEXT is automatically set with the specified TenantId whenever ElasticScaleContext is
invoked:
// Program.cs
SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
{
using (var db = new ElasticScaleContext<int>(sharding.ShardMap, tenantId, connStrBldr.ConnectionString))
{
var query = from b in db.Blogs
orderby b.Name
select b;
ADO.NET SqlClient
For applications using ADO.NET SqlClient, the recommended approach is to create a wrapper function around
ShardMap.OpenConnectionForKey() that automatically sets 'TenantId' in the SESSION_CONTEXT to the correct
TenantId before returning a connection. To ensure that SESSION_CONTEXT is always set, you should only open
connections using this wrapper function.
// Program.cs
// ...
// Wrapper function for ShardMap.OpenConnectionForKey() that automatically sets SESSION_CONTEXT with the correct
// tenantId before returning a connection. As a best practice, you should only open connections using this
// method to ensure that SESSION_CONTEXT is always set before executing a query.
public static SqlConnection OpenConnectionForTenant(ShardMap shardMap, int tenantId, string connectionStr)
{
SqlConnection conn = null;
try
{
// Ask shard map to broker a validated connection for the given key
conn = shardMap.OpenConnectionForKey(tenantId, connectionStr, ConnectionOptions.Validate);
return conn;
}
catch (Exception)
{
if (conn != null)
{
conn.Dispose();
}
throw;
}
}
// ...
TIP
For more complex projects that need to add the predicate on hundreds of tables, you can use a helper stored procedure
that automatically generates a security policy adding a predicate on all tables in a schema. See Apply Row-Level Security to
all tables - helper script (blog).
Now if you run the sample application again, tenants will able to see only rows that belong to them. In addition,
the application cannot insert rows that belong to tenants other than the one currently connected to the shard
database, and it cannot update visible rows to have a different TenantId. If the application attempts to do either, a
DbUpdateException will be raised.
If you add a new table later on, simply ALTER the security policy and add filter and block predicates on the new
table:
Now the application does not need to specify a TenantId when inserting rows:
SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
{
using (var db = new ElasticScaleContext<int>(sharding.ShardMap, tenantId, connStrBldr.ConnectionString))
{
var blog = new Blog { Name = name }; // default constraint sets TenantId automatically
db.Blogs.Add(blog);
db.SaveChanges();
}
});
NOTE
If you use default constraints for an Entity Framework project, it is recommended that you do NOT include the TenantId
column in your EF data model. This is because Entity Framework queries automatically supply default values which will
override the default constraints created in T-SQL that use SESSION_CONTEXT. To use default constraints in the sample
project, for instance, you should remove TenantId from DataClasses.cs (and run Add-Migration in the Package Manager
Console) and use T-SQL to ensure that the field only exists in the database tables. This way, EF will not automatically supply
incorrect default values when inserting data.
Maintenance
Adding new shards: You must execute the T-SQL script to enable RLS on any new shards, otherwise queries
on these shards will not be filtered.
Adding new tables: You must add a filter and block predicate to the security policy on all shards whenever a
new table is created, otherwise queries on the new table will not be filtered. This can be automated using a DDL
trigger, as described in Apply Row-Level Security automatically to newly created tables (blog).
Summary
Elastic database tools and row-level security can be used together to scale out an application’s data tier with
support for both multi-tenant and single-tenant shards. Multi-tenant shards can be used to store data more
efficiently (particularly in cases where a large number of tenants have only a few rows of data), while single-tenant
shards can be used to support premium tenants with stricter performance and isolation requirements. For more
information, see Row-Level Security reference.
Additional resources
What is an Azure elastic pool?
Scaling out with Azure SQL Database
Design Patterns for Multi-tenant SaaS Applications with Azure SQL Database
Authentication in multitenant apps, using Azure AD and OpenID Connect
Tailspin Surveys application
This topic describes the Azure SQL Database connection behavior for clients that use ADO.NET 4.5 or a later
version.
Outside vs inside
For connections to Azure SQL Database, we must first ask whether your client program runs outside or inside the
Azure cloud boundary. The subsections discuss two common scenarios.
Outside: Client runs on your desktop computer
Port 1433 is the only port that must be open on your desktop computer that hosts your SQL Database client
application.
Inside: Client runs on Azure
When your client runs inside the Azure cloud boundary, it uses what we can call a direct route to interact with the
SQL Database server. After a connection is established, further interactions between the client and database
involve no middleware proxy.
The sequence is as follows:
1. ADO.NET 4.5 (or later) initiates a brief interaction with the Azure cloud, and receives a dynamically
identified port number.
The dynamically identified port number is in the range of 11000-11999 or 14000-14999.
2. ADO.NET then connects to the SQL Database server directly, with no middleware in between.
3. Queries are sent directly to the database, and results are returned directly to the client.
Ensure that the port ranges of 11000-11999 and 14000-14999 on your Azure client machine are left available for
ADO.NET 4.5 client interactions with SQL Database.
In particular, ports in the range must be free of any other outbound blockers.
On your Azure VM, the Windows Firewall with Advanced Security controls the port settings.
You can use the firewall's user interface to add a rule for which you specify the TCP protocol along with
a port range with the syntax like 11000-11999.
Version clarifications
This section clarifies the monikers that refer to product versions. It also lists some pairings of versions between
products.
ADO.NET
ADO.NET 4.0 supports the TDS 7.3 protocol, but not 7.4.
ADO.NET 4.5 and later supports the TDS 7.4 protocol.
Related links
ADO.NET 4.6 was released on July 20, 2015. A blog announcement from the .NET team is available here.
ADO.NET 4.5 was released on August 15, 2012. A blog announcement from the .NET team is available here.
A blog post about ADO.NET 4.5.1 is available here.
TDS protocol version list
SQL Database Development Overview
Azure SQL Database firewall
How to: Configure firewall settings on SQL Database
Get the required values for authenticating an
application to access SQL Database from code
1/17/2017 • 1 min to read • Edit Online
To create and manage SQL Database from code you must register your app in the Azure Active Directory (AAD)
domain in the subscription where your Azure resources have been created.
# Sign in to Azure.
Add-AzureRmAccount
# If you have multiple subscriptions, uncomment and set to the subscription you want to work with.
#$subscriptionId = "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
#Set-AzureRmContext -SubscriptionId $subscriptionId
$appName = "{app-name}"
$uri = "http://{app-name}"
$secret = "{app-password}"
# If you still get a PrincipalNotFound error, then rerun the following until successful.
$roleassignment = New-AzureRmRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName
$azureAdApplication.ApplicationId.Guid
See also
Create a SQL database with C#
Connecting to SQL Database By Using Azure Active Directory Authentication
SQL error codes for SQL Database client
applications: Database connection error and other
issues
2/16/2017 • 18 min to read • Edit Online
This article lists SQL error codes for SQL Database client applications, including database connection errors,
transient errors (also called transient faults), resource governance errors, database copy issues, elastic pool, and
other errors. Most categories are particular to Azure SQL Database, and do not apply to Microsoft SQL Server.
Related topics:
More detailed information is available here: Azure SQL Database resource limits
ERRORCORRECTIV
ERRORNUMBER ERRORSEVERITY ERRORFORMAT ERRORINSERTS ERRORCAUSE EACTION
1132 EX_RESOURCE The elastic pool Elastic pool space Attempting to Please consider
has reached its limit in MBs. write data to a increasing the
storage limit. The database when DTUs of the
storage usage for the storage limit elastic pool if
the elastic pool of the elastic pool possible in order
cannot exceed has been to increase its
(%d) MBs. reached. storage limit,
reduce the
storage used by
individual
databases within
the elastic pool,
or remove
databases from
the elastic pool.
ERRORCORRECTIV
ERRORNUMBER ERRORSEVERITY ERRORFORMAT ERRORINSERTS ERRORCAUSE EACTION
10929 EX_USER The %s minimum DTU min per The total number Please consider
guarantee is %d, database; DTU of concurrent increasing the
maximum limit is max per database workers DTUs of the
%d and the (requests) across elastic pool if
current usage for all databases in possible in order
the database is the elastic pool to increase its
%d. However, the attempted to worker limit, or
server is currently exceed the pool remove
too busy to limit. databases from
support requests the elastic pool.
greater than %d
for this database.
See
http://go.microso
ft.com/fwlink/?
LinkId=267637
for assistance.
Otherwise, please
try again later.
40857 EX_USER Elastic pool not name of server; Specified elastic Please provide a
found for server: elastic pool name pool does not valid elastic pool
'%ls', elastic pool exist in the name.
name: '%ls'. specified server.
40858 EX_USER Elastic pool '%ls' elastic pool Specified elastic Provide new
already exists in name, server pool already elastic pool
server: '%ls' name exists in the name.
specified logical
server.
40859 EX_USER Elastic pool does elastic pool Specified service Provide the
not support service tier tier is not correct edition or
service tier '%ls'. supported for leave service tier
elastic pool blank to use the
provisioning. default service
tier.
40860 EX_USER Elastic pool '%ls' elastic pool Elastic pool and Please specify
and service name; service service objective correct
objective '%ls' level objective can be specified combination of
combination is name together only if elastic pool and
invalid. service objective service objective.
is specified as
'ElasticPool'.
ERRORCORRECTIV
ERRORNUMBER ERRORSEVERITY ERRORFORMAT ERRORINSERTS ERRORCAUSE EACTION
40861 EX_USER The database database edition, The database Please do not
edition '%.ls' elastic pool edition is specify a
cannot be service tier different than the database edition
different than elastic pool which is different
the elastic pool service tier. than the elastic
service tier which pool service tier.
is '%.ls'. Note that the
database edition
does not need to
be specified.
40862 EX_USER Elastic pool name None Elastic pool Please specify the
must be specified service objective elastic pool name
if the elastic pool does not if using the
service objective uniquely identify elastic pool
is specified. an elastic pool. service objective.
40864 EX_USER The DTUs for the DTUs for elastic Attempting to Please retry
elastic pool must pool; elastic pool set the DTUs for setting the DTUs
be at least (%d) service tier. the elastic pool for the elastic
DTUs for service below the pool to at least
tier '%.*ls'. minimum limit. the minimum
limit.
40865 EX_USER The DTUs for the DTUs for elastic Attempting to Please retry
elastic pool pool; elastic pool set the DTUs for setting the DTUs
cannot exceed service tier. the elastic pool for the elastic
(%d) DTUs for above the pool to no
service tier '%.*ls'. maximum limit. greater than the
maximum limit.
40867 EX_USER The DTU max per DTU max per Attempting to Please consider
database must database; elastic set the DTU max using the elastic
be at least (%d) pool service tier per database pool service tier
for service tier below the that supports the
'%.*ls'. supported limit. desired setting.
40868 EX_USER The DTU max per DTU max per Attempting to Please consider
database cannot database; elastic set the DTU max using the elastic
exceed (%d) for pool service tier. per database pool service tier
service tier '%.*ls'. beyond the that supports the
supported limit. desired setting.
40870 EX_USER The DTU min per DTU min per Attempting to Please consider
database cannot database; elastic set the DTU min using the elastic
exceed (%d) for pool service tier. per database pool service tier
service tier '%.*ls'. beyond the that supports the
supported limit. desired setting.
ERRORCORRECTIV
ERRORNUMBER ERRORSEVERITY ERRORFORMAT ERRORINSERTS ERRORCAUSE EACTION
40877 EX_USER An elastic pool None The elastic pool Please remove
cannot be contains one or databases from
deleted unless it more databases the elastic pool in
does not contain and therefore order to delete it.
any databases. cannot be
deleted.
40881 EX_USER The elastic pool Name of elastic Attempting to Please consider
'%.*ls' has pool; database create or add increasing the
reached its count limit of database to DTUs of the
database count elastic pool;e elastic pool when elastic pool if
limit. The DTUs for the database possible in order
database count resource pool. count limit of the to increase its
limit for the elastic pool has database limit, or
elastic pool been reached. remove
cannot exceed databases from
(%d) for an elastic the elastic pool.
pool with (%d)
DTUs.
40891 EX_USER The DTU min per DTU min per Attempting to Please ensure the
database (%d) database; DTU set the DTU min DTU min per
cannot exceed max per per database databases does
the DTU max per database. higher than the not exceed the
database (%d). DTU max per DTU max per
database. database.
ERRORCORRECTIV
ERRORNUMBER ERRORSEVERITY ERRORFORMAT ERRORINSERTS ERRORCAUSE EACTION
TBD EX_USER The storage size elastic pool The max size for Please set the
for an individual service tier the database max size of the
database in a exceeds the max database within
elastic pool size allowed by the limits of the
cannot exceed the elastic pool max size allowed
the max size service tier. by the elastic
allowed by '%.*ls' pool service tier.
service tier elastic
pool.
Related topics:
Create an elastic pool (C#)
Manage an elastic pool (C#).
Create an elastic pool (PowerShell)
Monitor and manage an elastic pool (PowerShell).
General errors
The following errors do not fall into any previous categories.
Related links
Azure SQL Database Features
Azure SQL Database resource limits
Using elastic database client library with Dapper
1/17/2017 • 8 min to read • Edit Online
This document is for developers that rely on Dapper to build applications, but also want to embrace elastic
database tooling to create applications that implement sharding to scale-out their data tier. This document
illustrates the changes in Dapper-based applications that are necessary to integrate with elastic database tools. Our
focus is on composing the elastic database shard management and data dependent routing with Dapper.
Sample Code: Elastic database tools for Azure SQL Database - Dapper integration.
Integrating Dapper and DapperExtensions with the elastic database client library for Azure SQL Database is easy.
Your applications can use data dependent routing by changing the creation and opening of new SqlConnection
objects to use the OpenConnectionForKey call from the client library. This limits changes in your application to only
where new connections are created and opened.
Dapper overview
Dapper is an object-relational mapper. It maps .NET objects from your application to a relational database (and
vice versa). The first part of the sample code illustrates how you can integrate the elastic database client library with
Dapper-based applications. The second part of the sample code illustrates how to integrate when using both
Dapper and DapperExtensions.
The mapper functionality in Dapper provides extension methods on database connections that simplify submitting
T-SQL statements for execution or querying the database. For instance, Dapper makes it easy to map between your
.NET objects and the parameters of SQL statements for Execute calls, or to consume the results of your SQL
queries into .NET objects using Query calls from Dapper.
When using DapperExtensions, you no longer need to provide the SQL statements. Extensions methods such as
GetList or Insert over the database connection create the SQL statements behind the scenes.
Another benefit of Dapper and also DapperExtensions is that the application controls the creation of the database
connection. This helps interact with the elastic database client library which brokers database connections based on
the mapping of shardlets to databases.
To get the Dapper assemblies, see Dapper dot net. For the Dapper extensions, see DapperExtensions.
Technical Guidance
Data dependent routing with Dapper
With Dapper, the application is typically responsible for creating and opening the connections to the underlying
database. Given a type T by the application, Dapper returns query results as .NET collections of type T. Dapper
performs the mapping from the T-SQL result rows to the objects of type T. Similarly, Dapper maps .NET objects
into SQL values or parameters for data manipulation language (DML) statements. Dapper offers this functionality
via extension methods on the regular SqlConnection object from the ADO .NET SQL Client libraries. The SQL
connection returned by the Elastic Scale APIs for DDR are also regular SqlConnection objects. This allows us to
directly use Dapper extensions over the type returned by the client library’s DDR API, as it is also a simple SQL
Client connection.
These observations make it straightforward to use connections brokered by the elastic database client library for
Dapper.
This code example (from the accompanying sample) illustrates the approach where the sharding key is provided by
the application to the library to broker the connection to the right shard.
The call to the OpenConnectionForKey API replaces the default creation and opening of a SQL Client connection.
The OpenConnectionForKey call takes the arguments that are required for data dependent routing:
The shard map to access the data dependent routing interfaces
The sharding key to identify the shardlet
The credentials (user name and password) to connect to the shard
The shard map object creates a connection to the shard that holds the shardlet for the given sharding key. The
elastic database client APIs also tag the connection to implement its consistency guarantees. Since the call to
OpenConnectionForKey returns a regular SQL Client connection object, the subsequent call to the Execute
extension method from Dapper follows the standard Dapper practice.
Queries work very much the same way - you first open the connection using OpenConnectionForKey from the
client API. Then you use the regular Dapper extension methods to map the results of your SQL query into .NET
objects:
Note that the using block with the DDR connection scopes all database operations within the block to the one
shard where tenantId1 is kept. The query only returns blogs stored on the current shard, but not the ones stored on
any other shards.
SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
{
using (SqlConnection sqlconn =
shardingLayer.ShardMap.OpenConnectionForKey(tenantId2, connStrBldr.ConnectionString, ConnectionOptions.Validate))
{
var blog = new Blog { Name = name2 };
sqlconn.Insert(blog);
}
});
Limitations
The approaches outlined in this document entail a couple of limitations:
The sample code for this document does not demonstrate how to manage schema across shards.
Given a request, we assume that all its database processing is contained within a single shard as identified by
the sharding key provided by the request. However, this assumption does not always hold, for example, when it
is not possible to make a sharding key available. To address this, the elastic database client library includes the
MultiShardQuery class. The class implements a connection abstraction for querying over several shards. Using
MultiShardQuery in combination with Dapper is beyond the scope of this document.
Conclusion
Applications using Dapper and DapperExtensions can easily benefit from elastic database tools for Azure SQL
Database. Through the steps outlined in this document, those applications can use the tool's capability for data
dependent routing by changing the creation and opening of new SqlConnection objects to use the
OpenConnectionForKey call of the elastic database client library. This limits the application changes required to
those places where new connections are created and opened.
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For questions,
please reach out to us on the SQL Database forum and for feature requests, please add them to the SQL Database
feedback forum.
Getting started with JSON features in Azure SQL
Database
1/17/2017 • 6 min to read • Edit Online
Azure SQL Database lets you parse and query data represented in JavaScript Object Notation (JSON) format, and
export your relational data as JSON text.
JSON is a popular data format used for exchanging data in modern web and mobile applications. JSON is also used
for storing semi-structured data in log files or in NoSQL databases like Azure DocumentDB. Many REST web
services return results formatted as JSON text or accept data formatted as JSON. Most Azure services such as
Azure Search, Azure Storage, and Azure DocumentDB have REST endpoints that return or consume JSON.
Azure SQL Database lets you work with JSON data easily and integrate your database with modern services.
Overview
Azure SQL Database provides the following functions for working with JSON data:
If you have JSON text, you can extract data from JSON or verify that JSON is properly formatted by using the built-
in functions JSON_VALUE, JSON_QUERY, and ISJSON. The JSON_MODIFY function lets you update value inside
JSON text. For more advanced querying and analysis, OPENJSON function can transform an array of JSON objects
into a set of rows. Any SQL query can be executed on the returned result set. Finally, there is a FOR JSON clause
that lets you format data stored in your relational tables as JSON text.
The FOR JSON PATH clause formats the results of the query as JSON text. Column names are used as keys, while
the cell values are generated as JSON values:
[
{"CustomerName":"Eric Torres","PhoneNumber":"(307) 555-0100","FaxNumber":"(307) 555-0101"},
{"CustomerName":"Cosmina Vlad","PhoneNumber":"(505) 555-0100","FaxNumber":"(505) 555-0101"},
{"CustomerName":"Bala Dixit","PhoneNumber":"(209) 555-0100","FaxNumber":"(209) 555-0101"}
]
The result set is formatted as a JSON array where each row is formatted as a separate JSON object.
PATH indicates that you can customize the output format of your JSON result by using dot notation in column
aliases. The following query changes the name of the "CustomerName" key in the output JSON format, and puts
phone and fax numbers in the "Contact" sub-object:
{
"Name":"Nada Jovanovic",
"Contact":{
"Phone":"(215) 555-0100",
"Fax":"(215) 555-0101"
}
}
In this example we returned a single JSON object instead of an array by specifying the
WITHOUT_ARRAY_WRAPPER option. You can use this option if you know that you are returning a single object as a
result of query.
The main value of the FOR JSON clause is that it lets you return complex hierarchical data from your database
formatted as nested JSON objects or arrays. The following example shows how to include Orders that belong to
the Customer as a nested array of Orders:
Instead of sending separate queries to get Customer data and then to fetch a list of related Orders, you can get all
the necessary data with a single query, as shown in the following sample output:
{
"Name":"Nada Jovanovic",
"Phone":"(215) 555-0100",
"Fax":"(215) 555-0101",
"Orders":[
{"OrderID":382,"OrderDate":"2013-01-07","ExpectedDeliveryDate":"2013-01-08"},
{"OrderID":395,"OrderDate":"2013-01-07","ExpectedDeliveryDate":"2013-01-08"},
{"OrderID":1657,"OrderDate":"2013-01-31","ExpectedDeliveryDate":"2013-02-01"}
]
}
The JSON data used in this example is represented by using the NVARCHAR(MAX) type. JSON can be inserted into
this table or provided as an argument of the stored procedure using standard Transact-SQL syntax as shown in the
following example:
Any client-side language or library that works with string data in Azure SQL Database will also work with JSON
data. JSON can be stored in any table that supports the NVARCHAR type, such as a Memory-optimized table or a
System-versioned table. JSON does not introduce any constraint either in the client-side code or in the database
layer.
update Products
set Data = JSON_MODIFY(Data, '$.Price', 60)
where Id = 1
The JSON_VALUE function extracts a value from JSON text stored in the Data column. This function uses a
JavaScript-like path to reference a value in JSON text to extract. The extracted value can be used in any part of SQL
query.
The JSON_QUERY function is similar to JSON_VALUE. Unlike JSON_VALUE, this function extracts complex sub-
object such as arrays or objects that are placed in JSON text.
The JSON_MODIFY function lets you specify the path of the value in the JSON text that should be updated, as well
as a new value that will overwrite the old one. This way you can easily update JSON text without reparsing the
entire structure.
Since JSON is stored in a standard text, there are no guarantees that the values stored in text columns are properly
formatted. You can verify that text stored in JSON column is properly formatted by using standard Azure SQL
Database check constraints and the ISJSON function:
If the input text is properly formatted JSON, the ISJSON function returns the value 1. On every insert or update of
JSON column, this constraint will verify that new text value is not malformed JSON.
In the example above, we can specify where to locate the JSON array that should be opened (in the $.Orders path),
what columns should be returned as result, and where to find the JSON values that will be returned as cells.
We can transform a JSON array in the @orders variable into a set of rows, analyze this result set, or insert rows
into a standard table:
END
The collection of orders formatted as a JSON array and provided as a parameter to the stored procedure can be
parsed and inserted into the Orders table.
Next steps
To learn how to integrate JSON into your application, check out these resources:
TechNet Blog
MSDN documentation
Channel 9 video
To learn about various scenarios for integrating JSON into your application, see the demos in this Channel 9 video
or find a scenario that matches your use case in JSON Blog posts.
Optimize performance by using In-Memory
technologies in SQL Database
4/14/2017 • 16 min to read • Edit Online
By using In-Memory technologies in Azure SQL Database, you can achieve performance improvements with
various workloads: transactional (online transactional processing (OLTP)), analytics (online analytical processing
(OLAP)), and mixed (hybrid transaction/analytical processing (HTAP)). Because of the more efficient query and
transaction processing, In-Memory technologies also help you to reduce cost. You typically don't need to upgrade
the pricing tier of the database to achieve performance gains. In some cases, you might even be able reduce the
pricing tier, while still seeing performance improvements with In-Memory technologies.
Here are two examples of how In-Memory OLTP helped to significantly improve performance:
By using In-Memory OLTP, Quorum Business Solutions was able to double their workload while improving
DTUs (i.e., resource consumption) by 70%.
The following video demonstrates significant improvement in resource consumption with a sample workload:
In-Memory OLTP in Azure SQL Database.
In-Memory technologies are available in all databases in the Premium tier, including databases in Premium elastic
pools.
The following video explains potential performance gains with In-Memory technologies in Azure SQL Database.
Remember that the performance gain that you see always depends on many factors, including the nature of the
workload and data, access pattern of the database, and so on.
Error 40536
If you get error 40536 when you run the T-SQL script, run the following T-SQL script to verify whether the
database supports In-Memory:
A result of 0 means that In-Memory isn't supported, and 1 means that it is supported. To diagnose the problem,
ensure that the database is at the Premium service tier.
About the created memory-optimized items
Tables: The sample contains the following memory-optimized tables:
SalesLT.Product_inmem
SalesLT.SalesOrderHeader_inmem
SalesLT.SalesOrderDetail_inmem
Demo.DemoSalesOrderHeaderSeed
Demo.DemoSalesOrderDetailSeed
You can inspect memory-optimized tables through the Object Explorer in SSMS. Right-click Tables > Filter >
Filter Settings > Is Memory Optimized. The value equals 1.
Or you can query the catalog views, such as:
Natively compiled stored procedure: You can inspect SalesLT.usp_InsertSalesOrder_inmem through a catalog
view query:
To make the _ondisk version of the preceding T-SQL script for ostress.exe, you would simply replace both
occurrences of the _inmem substring with _ondisk. These replacements affect the names of tables and stored
procedures.
Install RML utilities and ostress
Ideally, you would plan to run ostress.exe on an Azure virtual machine (VM). You would create an Azure VM in the
same Azure geographic region where your AdventureWorksLT database resides. But you can run ostress.exe on
your laptop instead.
On the VM, or on whatever host you choose, install the Replay Markup Language (RML) utilities. The utilities
include ostress.exe.
For more information, see:
The ostress.exe discussion in Sample Database for In-Memory OLTP.
Sample Database for In-Memory OLTP.
The blog for installing ostress.exe.
Run the _inmem stress workload first
You can use an RML Cmd Prompt window to run our ostress.exe command line. The command-line parameters
direct ostress to:
Run 100 connections concurrently (-n100).
Have each connection run the T-SQL script 50 times (-r50).
ostress.exe -n100 -r50 -S<servername>.database.windows.net -U<login> -P<password> -d<database> -q -Q"DECLARE @i int = 0, @od
SalesLT.SalesOrderDetailType_inmem, @SalesOrderID int, @DueDate datetime2 = sysdatetime(), @CustomerID int = rand() * 8000,
@BillToAddressID int = rand() * 10000, @ShipToAddressID int = rand()* 10000; INSERT INTO @od SELECT OrderQty, ProductID FROM
Demo.DemoSalesOrderDetailSeed WHERE OrderID= cast((rand()*60) as int); WHILE (@i < 20) begin; EXECUTE
SalesLT.usp_InsertSalesOrder_inmem @SalesOrderID OUTPUT, @DueDate, @CustomerID, @BillToAddressID, @ShipToAddressID, @od; set
@i += 1; end"
2. Copy the text of the preceding ostress.exe command line to your clipboard.
3. Replace the <placeholders> for the parameters -S -U -P -d with the correct real values.
4. Run your edited command line in an RML Cmd window.
Result is a duration
When ostress.exe finishes, it writes the run duration as its final line of output in the RML Cmd window. For
example, a shorter test run lasted about 1.5 minutes:
11/12/15 00:35:00.873 [0x000030A8] OSTRESS exiting normally, elapsed time: 00:01:31.867
EXECUTE Demo.usp_DemoReset;
2. Edit the ostress.exe command line to replace all _inmem with _ondisk.
3. Rerun ostress.exe for the second time, and capture the duration result.
4. Again, reset the database (for responsibly deleting what can be a large amount of test data).
Expected comparison results
Our In-Memory tests have shown that performance improved by nine times for this simplistic workload, with
ostress running on an Azure VM in the same Azure region as the database.
Level 130 is not directly related to In-Memory features. But level 130 generally provides faster query
performance than 120.
Key tables and columnstore indexes
dbo.FactResellerSalesXL_CCI is a table that has a clustered columnstore index, which has advanced
compression at the data level.
dbo.FactResellerSalesXL_PageCompressed is a table that has an equivalent regular clustered index, which is
compressed only at the page level.
Key queries to compare the columnstore index
There are several T-SQL query types that you can run to see performance improvements. In step 2 in the T-SQL
script, pay attention to this pair of queries. They differ only on one line:
FROM FactResellerSalesXL_PageCompressed a
FROM FactResellerSalesXL_CCI a
-- Execute a typical query that joins the Fact Table with dimension tables
-- Note this query will run on the Page Compressed table, Note down the time
SET STATISTICS IO ON
SET STATISTICS TIME ON
GO
SELECT c.Year
,e.ProductCategoryKey
,FirstName + ' ' + LastName AS FullName
,count(SalesOrderNumber) AS NumSales
,sum(SalesAmount) AS TotalSalesAmt
,Avg(SalesAmount) AS AvgSalesAmt
,count(DISTINCT SalesOrderNumber) AS NumOrders
,count(DISTINCT a.CustomerKey) AS CountCustomers
FROM FactResellerSalesXL_PageCompressed a
INNER JOIN DimProduct b ON b.ProductKey = a.ProductKey
INNER JOIN DimCustomer d ON d.CustomerKey = a.CustomerKey
Inner JOIN DimProductSubCategory e on e.ProductSubcategoryKey = b.ProductSubcategoryKey
INNER JOIN DimDate c ON c.DateKey = a.OrderDateKey
GROUP BY e.ProductCategoryKey,c.Year,d.CustomerKey,d.FirstName,d.LastName
GO
SET STATISTICS IO OFF
SET STATISTICS TIME OFF
GO
-- This is the same Prior query on a table with a clustered columnstore index CCI
-- The comparison numbers are even more dramatic the larger the table is (this is an 11 million row table only)
SET STATISTICS IO ON
SET STATISTICS TIME ON
GO
SELECT c.Year
,e.ProductCategoryKey
,FirstName + ' ' + LastName AS FullName
,count(SalesOrderNumber) AS NumSales
,sum(SalesAmount) AS TotalSalesAmt
,Avg(SalesAmount) AS AvgSalesAmt
,count(DISTINCT SalesOrderNumber) AS NumOrders
,count(DISTINCT a.CustomerKey) AS CountCustomers
FROM FactResellerSalesXL_CCI a
INNER JOIN DimProduct b ON b.ProductKey = a.ProductKey
INNER JOIN DimCustomer d ON d.CustomerKey = a.CustomerKey
Inner JOIN DimProductSubCategory e on e.ProductSubcategoryKey = b.ProductSubcategoryKey
INNER JOIN DimDate c ON c.DateKey = a.OrderDateKey
GROUP BY e.ProductCategoryKey,c.Year,d.CustomerKey,d.FirstName,d.LastName
GO
In a database with the P2 pricing tier, you can expect about nine times the performance gain for this query by
using the clustered columnstore index compared with the traditional index. With P15, you can expect about 57
times the performance gain by using the columnstore index.
Next steps
Quick Start 1: In-Memory OLTP Technologies for Faster T-SQL Performance
Use In-Memory OLTP in an existing Azure SQL application
Monitor In-Memory OLTP storage for In-Memory OLTP
Additional resources
Deeper information
Learn how Quorum doubles key database’s workload while lowering DTU by 70% with In-Memory OLTP in
SQL Database
Learn about In-Memory OLTP
Learn about columnstore indexes
Learn about real-time operational analytics
See Common Workload Patterns and Migration Considerations (which describes workload patterns where
In-Memory OLTP commonly provides significant performance gains)
Application design
In-Memory OLTP (In-Memory Optimization)
Use In-Memory OLTP in an existing Azure SQL application
Tools
Azure portal
SQL Server Management Studio (SSMS)
SQL Server Data Tools (SSDT)
Getting Started with Temporal Tables in Azure SQL
Database
2/2/2017 • 7 min to read • Edit Online
Temporal Tables are a new programmability feature of Azure SQL Database that allows you to track and analyze
the full history of changes in your data, without the need for custom coding. Temporal Tables keep data closely
related to time context so that stored facts can be interpreted as valid only within the specific period. This property
of Temporal Tables allows for efficient time-based analysis and getting insights from data evolution.
Temporal Scenario
This article illustrates the steps to utilize Temporal Tables in an application scenario. Suppose that you want to track
user activity on a new website that is being developed from scratch or on an existing website that you want to
extend with user activity analytics. In this simplified example, we assume that the number of visited web pages
during a period of time is an indicator that needs to be captured and monitored in the website database that is
hosted on Azure SQL Database. The goal of the historical analysis of user activity is to get inputs to redesign
website and provide better experience for the visitors.
The database model for this scenario is very simple - user activity metric is represented with a single integer field,
PageVisited, and is captured along with basic information on the user profile. Additionally, for time based
analysis, you would keep a series of rows for each user, where every row represents the number of pages a
particular user visited within a specific period of time.
Fortunately, you do not need to put any effort in your app to maintain this activity information. With Temporal
Tables, this process is automated - giving you full flexibility during website design and more time to focus on the
data analysis itself. The only thing you have to do is to ensure that WebSiteInfo table is configured as temporal
system-versioned. The exact steps to utilize Temporal Tables in this scenario are described below.
In SSDT, chose “Temporal Table (System-Versioned)” template when adding new items to the database project.
That will open table designer and enable you to easily specify the table layout:
You can also a create temporal table by specifying the Transact-SQL statements directly, as shown in the example
below. Note that the mandatory elements of every temporal table are the PERIOD definition and the
SYSTEM_VERSIONING clause with a reference to another user table that will store historical row versions:
When you create system-versioned temporal table, the accompanying history table with the default configuration
is automatically created. The default history table contains a clustered B-tree index on the period columns (end,
start) with page compression enabled. This configuration is optimal for the majority of scenarios in which temporal
tables are used, especially for data auditing.
In this particular case, we aim to perform time-based trend analysis over a longer data history and with bigger data
sets, so the storage choice for the history table is a clustered columnstore index. A clustered columnstore provides
very good compression and performance for analytical queries. Temporal Tables give you the flexibility to
configure indexes on the current and temporal tables completely independently.
NOTE
Columnstore indexes are only available in the premium service tier.
The following script shows how default index on history table can be changed to the clustered columnstore:
CREATE CLUSTERED COLUMNSTORE INDEX IX_WebsiteUserInfoHistory
ON dbo.WebsiteUserInfoHistory
WITH (DROP_EXISTING = ON);
Temporal Tables are represented in the Object Explorer with the specific icon for easier identification, while its
history table is displayed as a child node.
It is important to notice that the update query doesn’t need to know the exact time when the actual operation
occurred nor how historical data will be preserved for future analysis. Both aspects are automatically handled by
the Azure SQL Database. The following diagram illustrates how history data is being generated on every update.
You can easily modify this query to analyze the site visits as of a day ago, a month ago or at any point in the past
you wish.
To perform basic statistical analysis for the previous day, use the following example:
To search for activities of a specific user, within a period of time, use the CONTAINED IN clause:
DECLARE @hourAgo datetime2 = DATEADD(HOUR, -1, SYSUTCDATETIME());
DECLARE @twoHoursAgo datetime2 = DATEADD(HOUR, -2, SYSUTCDATETIME());
SELECT * FROM dbo.WebsiteUserInfo
FOR SYSTEM_TIME CONTAINED IN (@twoHoursAgo, @hourAgo)
WHERE [UserID] = 1;
Graphic visualization is especially convenient for temporal queries as you can show trends and usage patterns in
an intuitive way very easily:
Similarly, you can change column definition while your workload is active:
Finally, you can remove a column that you do not need anymore.
Alternatively, use latest SSDT to change temporal table schema while you are connected to the database (online
mode) or as part of the database project (offline mode).
Next steps
For detailed information on Temporal Tables, check out MSDN documentation. Visit Channel 9 to hear a real
customer temporal implemenation success story and watch a live temporal demonstration.
Manage historical data in Temporal Tables with
retention policy
4/19/2017 • 7 min to read • Edit Online
Temporal Tables may increase database size more than regular tables, especially if you retain historical data for a
longer period of time. Hence, retention policy for historical data is an important aspect of planning and managing
the lifecycle of every temporal table. Temporal Tables in Azure SQL Database come with easy-to-use retention
mechanism that helps you accomplish this task.
Temporal history retention can be configured at the individual table level, which allows users to create flexible
aging polices. Applying temporal retention is simple: it requires only one parameter to be set during table creation
or schema change.
After you define retention policy, Azure SQL Database starts checking regularly if there are historical rows that are
eligible for automatic data cleanup. Identification of matching rows and their removal from the history table occur
transparently, in the background task that is scheduled and run by the system. Age condition for the history table
rows is checked based on the column representing end of SYSTEM_TIME period. If retention period, for example, is
set to six months, table rows eligible for cleanup satisfy the following condition:
In the preceding example, we assumed that ValidTo column corresponds to the end of SYSTEM_TIME period.
Database flag is_temporal_history_retention_enabled is set to ON by default, but users can change it with
ALTER DATABASE statement. It is also automatically set to OFF after point in time restore operation. To enable
temporal history retention cleanup for your database, execute the following statement:
IMPORTANT
You can configure retention for temporal tables even if is_temporal_history_retention_enabled is OFF, but automatic
cleanup for aged rows is not triggered in that case.
Retention policy is configured during table creation by specifying value for the HISTORY_RETENTION_PERIOD
parameter:
CREATE TABLE dbo.WebsiteUserInfo
(
[UserID] int NOT NULL PRIMARY KEY CLUSTERED
, [UserName] nvarchar(100) NOT NULL
, [PagesVisited] int NOT NULL
, [ValidFrom] datetime2 (0) GENERATED ALWAYS AS ROW START
, [ValidTo] datetime2 (0) GENERATED ALWAYS AS ROW END
, PERIOD FOR SYSTEM_TIME (ValidFrom, ValidTo)
)
WITH
(
SYSTEM_VERSIONING = ON
(
HISTORY_TABLE = dbo.WebsiteUserInfoHistory,
HISTORY_RETENTION_PERIOD = 6 MONTHS
)
);
Azure SQL Database allows you to specify retention period by using different time units: DAYS, WEEKS, MONTHS,
and YEARS. If HISTORY_RETENTION_PERIOD is omitted, INFINITE retention is assumed. You can also use INFINITE
keyword explicitly.
In some scenarios, you may want to configure retention after table creation, or to change previously configured
value. In that case use ALTER TABLE statement:
IMPORTANT
Setting SYSTEM_VERSIONING to OFF does not preserve retention period value. Setting SYSTEM_VERSIONING to ON without
HISTORY_RETENTION_PERIOD specified explicitly results in the INFINITE retention period.
To review current state of the retention policy, use the following query that joins temporal retention enablement
flag at the database level with retention periods for individual tables:
SELECT DB.is_temporal_history_retention_enabled,
SCHEMA_NAME(T1.schema_id) AS TemporalTableSchema,
T1.name as TemporalTableName, SCHEMA_NAME(T2.schema_id) AS HistoryTableSchema,
T2.name as HistoryTableName,T1.history_retention_period,
T1.history_retention_period_unit_desc
FROM sys.tables T1
OUTER APPLY (select is_temporal_history_retention_enabled from sys.databases
where name = DB_NAME()) AS DB
LEFT JOIN sys.tables T2
ON T1.history_table_id = T2.object_id WHERE T1.temporal_type = 2
Excellent data compression and efficient retention cleanup makes clustered columnstore index a perfect choice for
scenarios when your workload rapidly generates high amount of historical data. That pattern is typical for intensive
transactional processing workloads that use temporal tables for change tracking and auditing, trend analysis, or IoT
data ingestion.
Index considerations
The cleanup task for tables with rowstore clustered index requires index to start with the column corresponding the
end of SYSTEM_TIME period. If such index doesn't exist, you cannot configure a finite retention period:
Msg 13765, Level 16, State 1
Setting finite retention period failed on system-versioned temporal table
'temporalstagetestdb.dbo.WebsiteUserInfo' because the history table
'temporalstagetestdb.dbo.WebsiteUserInfoHistory' does not contain required clustered index. Consider creating a
clustered columnstore or B-tree index starting with the column that matches end of SYSTEM_TIME period, on the
history table.
It is important to notice that the default history table created by Azure SQL Database already has clustered index,
which is compliant for retention policy. If you try to remove that index on a table with finite retention period,
operation fails with the following error:
Msg 13766, Level 16, State 1
Cannot drop the clustered index 'WebsiteUserInfoHistory.IX_WebsiteUserInfoHistory' because it is being used for
automatic cleanup of aged data. Consider setting HISTORY_RETENTION_PERIOD to INFINITE on the corresponding
system-versioned temporal table if you need to drop this index.
Cleanup on the clustered columnstore index works optimally if historical rows are inserted in the ascending order
(ordered by the end of period column), which is always the case when the history table is populated exclusively by
the SYSTEM_VERSIONIOING mechanism. If rows in the history table are not ordered by end of period column
(which may be the case if you migrated existing historical data), you should re-create clustered columnstore index
on top of B-tree rowstore index that is properly ordered, to achieve optimal performance.
Avoid rebuilding clustered columnstore index on the history table with the finite retention period, because it may
change ordering in the row groups naturally imposed by the system-versioning operation. If you need to rebuild
clustered columnstore index on the history table, do that by re-creating it on top of compliant B-tree index,
preserving ordering in the rowgroups necessary for regular data cleanup. The same approach should be taken if
you create temporal table with existing history table that has clustered column index without guaranteed data
order:
/*Create B-tree ordered by the end of period column*/
CREATE CLUSTERED INDEX IX_WebsiteUserInfoHistory ON WebsiteUserInfoHistory (ValidTo)
WITH (DROP_EXISTING = ON);
GO
/*Re-create clustered columnstore index*/
CREATE CLUSTERED COLUMNSTORE INDEX IX_WebsiteUserInfoHistory ON WebsiteUserInfoHistory
WITH (DROP_EXISTING = ON);
When finite retention period is configured for the history table with the clustered columnstore index, you cannot
create additional non-clustered B-tree indexes on that table:
The query plan includes additional filter applied to end of period column (ValidTo) in the Clustered Index Scan
operator on the history table (highlighted). This example assumes that one MONTH retention period was set on
WebsiteUserInfo table.
However, if you query history table directly, you may see rows that are older than specified retention period, but
without any guarantee for repeatable query results. The following picture shows query execution plan for the query
on the history table without additional filters applied:
Do not rely your business logic on reading history table beyond retention period as you may get inconsistent or
unexpected results. We recommend that you use temporal queries with FOR SYSTEM_TIME clause for analyzing
data in temporal tables.
In this article, you learn about the two primary methods for migrating a SQL Server 2005 or later database to
Azure SQL Database. The first method is simpler but requires some, possibly substantial, downtime during the
migration. The second method is more complex, but substantially eliminates downtime during the migration.
In both cases, you need to ensure that the source database is compatible with Azure SQL Database using the Data
Migration Assistant (DMA). SQL Database V12 is approaching feature parity with SQL Server, other than issues
related to server-level and cross-database operations. Databases and applications that rely on partially supported
or unsupported functions need some re-engineering to fix these incompatibilities before the SQL Server database
can be migrated.
NOTE
To migrate a non-SQL Server database, including Microsoft Access, Sybase, MySQL Oracle, and DB2 to Azure SQL Database,
see SQL Server Migration Assistant.
1. Assess the database for compatibility using the latest version of Data Migration Assistant (DMA).
2. Prepare any necessary fixes as Transact-SQL scripts.
3. Make a transactionally consistent copy of the source database being migrated - and ensure no further changes
are being made to the source database (or you can manually apply any such changes after the migration
completes). There are many methods to quiesce a database, from disabling client connectivity to creating a
database snapshot.
4. Deploy the Transact-SQL scripts to apply the fixes to the database copy.
5. Export the database copy to a .BACPAC file on a local drive.
6. Import the .BACPAC file as a new Azure SQL database using any of several BACPAC import tools, with
SQLPackage.exe being the recommended tool for best performance.
Optimizing data transfer performance during migration
The following list contains recommendations for best performance during the import process.
Choose the highest service level and performance tier that your budget allows to maximize the transfer
performance. You can scale down after the migration completes to save money.
Minimize the distance between your .BACPAC file and the destination data center.
Disable auto-statistics during migration
Partition tables and indexes
Drop indexed views, and recreate them once finished
Remove rarely queried historical data to another database and migrate this historical data to a separate Azure
SQL database. You can then query this historical data using elastic queries.
Optimize performance after the migration completes
Update statistics with full scan after the migration is completed.
IMPORTANT
Use the latest version of SQL Server Management Studio to remain synchronized with updates to Microsoft Azure and SQL
Database. Older versions of SQL Server Management Studio cannot set up SQL Database as a subscriber. Update SQL
Server Management Studio.
1. Set up Distribution
Using SQL Server Management Studio (SSMS)
Using Transact-SQL
2. Create Publication
Using SQL Server Management Studio (SSMS)
Using Transact-SQL
3. Create Subscription
Using SQL Server Management Studio (SSMS)
Using Transact-SQL
Some tips and differences for migrating to SQL Database
1. Use a local distributor
This causes a performance impact on the server.
If the performance impact is unacceptable, you can use another server but it adds complexity in
management and administration.
2. When selecting a snapshot folder, make sure the folder you select is large enough to hold a BCP of every table
you want to replicate.
3. Snapshot creation locks the associated tables until it is complete, so schedule your snapshot appropriately.
4. Only push subscriptions are supported in Azure SQL Database. You can only add subscribers from the source
database.
Next steps
Use the script on the Azure SQL EMEA Engineers blog to Monitor tempdb usage during migration.
Use the script on the Azure SQL EMEA Engineers blog to Monitor the transaction log space of your database
while migration is occurring.
For a SQL Server Customer Advisory Team blog about migrating using BACPAC files, see Migrating from SQL
Server to Azure SQL Database using BACPAC Files.
For information about working with UTC time after migration, see Modifying the default time zone for your
local time zone.
For information about changing the default language of a database after migration, see How to change the
default language of Azure SQL Database.
Resolving Transact-SQL differences during migration
to SQL Database
4/10/2017 • 5 min to read • Edit Online
When migrating your database from SQL Server to Azure SQL Server, you may discover that your database
requires some re-engineering before the SQL Server can be migrated. This topic provides guidance to assist you
in both performing this re-engineering and understanding the underlying reasons why the re-engineering is
necessary. To detect incompatibilities, use the Data Migration Assistant (DMA).
Overview
Most Transact-SQL features that applications use are fully supported in both Microsoft SQL Server and Azure
SQL Database. For example, the core SQL components such as data types, operators, string, arithmetic, logical,
and cursor functions, work identically in SQL Server and SQL Database. There are, however, a few T-SQL
differences in DDL (data-definition language) and DML (data manipulation language) elements resulting in T-
SQL statements and queries that are only partially supported (which we discuss later in this topic).
In addition, there are some features and syntax that is not supported at all because Azure SQL Database is
designed to isolate features from dependencies on the master database and the operating system. As such, most
server-level activities are inappropriate for SQL Database. T-SQL statements and options are not available if they
configure server-level options, operating system components, or specify file system configuration. When such
capabilities are required, an appropriate alternative is often available in some other way from SQL Database or
from another Azure feature or service.
For example, high availability is built into Azure, so configuring Always On is not necessary (although you may
want to configure Active Geo-Replication for faster recovery in the event of a disaster). So, T-SQL statements
related to availability groups are not supported by SQL Database, and the dynamic management views related to
Always On are also not supported.
For a list of the features that are supported and unsupported by SQL Database, see Azure SQL Database feature
comparison. The list on this page supplements that guidelines and features topic, and focuses on Transact-SQL
statements.
Next steps
For a list of the features that are supported and unsupported by SQL Database, see Azure SQL Database feature
comparison. The list on this page supplements that guidelines and features topic, and focuses on Transact-SQL
statements.
Copy an Azure SQL database
4/12/2017 • 5 min to read • Edit Online
Azure SQL Database provides several methods for creating a transactionally consistent copy of an existing Azure
SQL database on either the same server or a different server. You can copy a SQL database using the Azure
portal, PowerShell, or T-SQL.
Overview
A database copy is a snapshot of the source database as of the time of the copy request. You can select the same
server or a different server, its service tier and performance level, a different performance level within the same
service tier (edition). After the copy is complete, the copy becomes a fully functional, independent database. At
this point, you can upgrade or downgrade it to any edition. The logins, users, and permissions can be managed
independently.
NOTE
If you decide to cancel the copying while it is in progress, execute the DROP DATABASE statement on the new
database. Alternatively, executing the DROP DATABASE statement on the source database also cancels the copying
process.
Resolve logins
After the new database is online on the destination server, use the ALTER USER statement to remap the users
from the new database to logins on the destination server. To resolve orphaned users, see Troubleshoot
Orphaned Users. See also How to manage Azure SQL database security after disaster recovery.
All users in the new database maintain the permissions that they had in the source database. The user who
initiated the database copy becomes the database owner of the new database and is assigned a new security
identifier (SID). After the copying succeeds and before other users are remapped, only the login that initiated the
copying, the database owner (DBO), can log on to the new database.
See also How to manage Azure SQL database security after disaster recovery to learn about managing users and
logins when copying a database to a different logical server.
Next steps
For information on logins, see Manage logins and How to manage Azure SQL database security after disaster
recovery.
To export a database, see Export the database to a BACPAC
Import a BACPAC file to a new Azure SQL Database
4/12/2017 • 4 min to read • Edit Online
This article discusses importing a BACPAC file to a new Azure SQL database. This article discusses using the
following methods:
The Azure portal
the SqlPackage command-line utility
the New-AzureRmSqlDatabaseImport cmdlet
Overview
When you need to import a database from an archive or when migrating from another platform, you can import
the database schema and data from a BACPAC file. A BACPAC file is a ZIP file with an extension of BACPAC
containing the metadata and data from a SQL Server database. A BACPAC file can be imported from Azure blob
storage (standard storage only) or from local storage in an on-premises location. To maximize the import speed,
we recommend that you specify a higher service tier and performance level, such as a P6, and then scale to down
as appropriate after the import is successful. Also, the database compatibility level after the import is based on the
compatibility level of the source database.
IMPORTANT
After you migrate your database to Azure SQL Database, you can choose to operate the database at its current
compatibility level (level 100 for the AdventureWorks2008R2 database) or at a higher level. For more information on the
implications and options for operating a database at a specific compatibility level, see ALTER DATABASE Compatibility Level.
See also ALTER DATABASE SCOPED CONFIGURATION for information about additional database-level settings related to
compatibility levels. >
NOTE
To import a BACPAC to a new database, you must first create an Azure SQL Database logical server. For a tutorial showing
you how to migrate a SQL Server database to Azure SQL Database using SQLPackage, see Migrate a SQL Server Database
Azure portal
This article provides directions for creating an Azure SQL database from a BACPAC file stored in Azure blob
storage using the Azure portal. Import using the Azure portal only supports importing a BACPAC file from Azure
blob storage.
To import a database using the Azure portal, open the page for your database and click Import on the toolbar.
Specify the *.bacpac filename, provide the Azure storage account and container for the bacpac, and provide the
credentials to connect to the source database.
To monitor the progress of the import operation, open the page for the logical server containing the database
being imported. Scroll down to Operations and then click Import/Export history.
Monitor the progress of the import operation
1. Click SQL servers.
2. Click the server you are restoring to.
3. In the SQL server blade, in the Operations area, click Import/Export history:
4. To verify the database is live on the server, click SQL databases and verify the new database is Online.
SQLPackage
To import a SQL database using the SqlPackage command-line utility, see Import parameters and properties. The
SQLPackage utility ships with the latest versions of SQL Server Management Studio and SQL Server Data Tools for
Visual Studio, or you can download the latest version of SqlPackage directly from the Microsoft download center.
We recommend the use of the SQLPackage utility for scale and performance in most production environments.
For a SQL Server Customer Advisory Team blog about migrating using BACPAC files, see Migrating from SQL
Server to Azure SQL Database using BACPAC Files.
See the following SQLPackage command for a sample script for how to import the AdventureWorks2008R2
database from local storage to an Azure SQL Database logical server, called mynewserver20170403 in this
example. This script shows the creation of a new database called myMigratedDatabase, with a service tier of
Premium, and a Service Objective of P6. Change these values as appropriate to your environment.
PowerShell
Use the New-AzureRmSqlDatabaseImport cmdlet to submit an import database request to the Azure SQL
Database service. Depending on the size of your database, the import operation may take some time to complete.
To check the status of the import request, use the Get-AzureRmSqlDatabaseImportExportStatus cmdlet. Running
this immediately after the request usually returns Status: InProgress. When you see Status: Succeeded the
import is complete.
Next steps
To learn how to connect to and query an imported SQL Database, see Connect to SQL Database with SQL
Server Management Studio and perform a sample T-SQL query.
For a SQL Server Customer Advisory Team blog about migrating using BACPAC files, see Migrating from SQL
Server to Azure SQL Database using BACPAC Files.
For a discussion of the entire SQL Server database migration process, including performance
recommendations, see Migrate a SQL Server database to Azure SQL Database.
Export an Azure SQL database to a BACPAC file
4/10/2017 • 5 min to read • Edit Online
This article discusses exporting an Azure SQL database to a BACPAC file. This article discusses using the following
methods:
The Azure portal
the SqlPackage command-line utility
the New-AzureRmSqlDatabaseExport cmdlet
the Export a Data-tier Application wizard in SQL Server Management Studio.
IMPORTANT
Azure SQL Database Automated Export is now in preview and will be retired on March 1, 2017. Starting December 1, 2016,
you will no longer be able to configure automated export on any SQL database. All your existing automated export jobs will
continue to work until March 1, 2017. After December 1, 2016, you can use long-term backup retention or Azure
Automation to archive SQL databases periodically using PowerShell periodically according to a schedule of your choice. For a
sample script, you can download the sample PowerShell script from Github.
IMPORTANT
Azure SQL Database Automated Export is now in preview and will be retired on March 1, 2017. Starting December 1, 2016,
you will no longer be able to configure automated export on any SQL database. All your existing automated export jobs will
continue to work until March 1, 2017. After December 1, 2016, you can use long-term backup retention or Azure
Automation to archive SQL databases periodically using PowerShell periodically according to a schedule of your choice. For a
sample script, you can download the sample PowerShell script from Github.
Overview
When you need to export a database for archiving or for moving to another platform, you can export the database
schema and data to a BACPAC file. A BACPAC file is a ZIP file with an extension of BACPAC containing the
metadata and data from a SQL Server database. A BACPAC file can be stored in Azure blob storage or in local
storage in an on-premises location and later imported back into Azure SQL Database or into a SQL Server on-
premises installation.
IMPORTANT
If you are exporting from SQL Server as a prelude to migration to Azure SQL Database, see Migrate a SQL Server database
to Azure SQL Database.
Considerations
For an export to be transactionally consistent, you must ensure either that no write activity is occurring during
the export, or that you are exporting from a transactionally consistent copy of your Azure SQL database.
If you are exporting to blob storage, the maximum size of a BACPAC file is 200 GB. To archive a larger BACPAC
file, export to local storage.
Exporting a BACPAC file to Azure premium storage using the methods discussed in this article is not
supported.
If the export operation from Azure SQL Database exceeds 20 hours, it may be canceled. To increase
performance during export, you can:
Temporarily increase your service level.
Cease all read and write activity during the export.
Use a clustered index with non-null values on all large tables. Without clustered indexes, an export may
fail if it takes longer than 6-12 hours. This is because the export service needs to complete a table scan
to try to export entire table. A good way to determine if your tables are optimized for export is to run
DBCC SHOW_STATISTICS and make sure that the RANGE_HI_KEY is not null and its value has good
distribution. For details, see DBCC SHOW_STATISTICS.
NOTE
BACPACs are not intended to be used for backup and restore operations. Azure SQL Database automatically creates
backups for every user database. For details, see Business Continuity Overview and SQL Database backups.
Azure portal
To export a database using the Azure portal, open the page for your database and click Export on the toolbar.
Specify the *.bacpac filename, provide the Azure storage account and container for the export, and provide the
credentials to connect to the source database.
To monitor the progress of the export operation, open the page for the logical server containing the database
being exported. Scroll down to Operations and then click Import/Export history.
SQLPackage utility
To export a SQL database using the SqlPackage command-line utility, see Export parameters and properties. The
SQLPackage utility ships with the latest versions of SQL Server Management Studio and SQL Server Data Tools
for Visual Studio, or you can download the latest version of SqlPackage directly from the Microsoft download
center.
We recommend the use of the SQLPackage utility for scale and performance in most production environments.
For a SQL Server Customer Advisory Team blog about migrating using BACPAC files, see Migrating from SQL
Server to Azure SQL Database using BACPAC Files.
SQL Server Management Studio
The newest versions of SQL Server Management Studio also provide a wizard to export an Azure SQL Database to
a bacpac file. See the Export a Data-tier Application.
PowerShell
Use the New-AzureRmSqlDatabaseImport cmdlet to submit an export database request to the Azure SQL
Database service. Depending on the size of your database, the export operation may take some time to complete.
To check the status of the export request, use the Get-AzureRmSqlDatabaseImportExportStatus cmdlet. Running
this immediately after the request usually returns Status: InProgress. When you see Status: Succeeded the
export is complete.
Login-AzureRmAccount
Set-AzureRmContext -SubscriptionId $subscriptionId
# Database to export
$DatabaseName = "DATABASE-NAME"
$ResourceGroupName = "RESOURCE-GROUP-NAME"
$ServerName = "SERVER-NAME
$serverAdmin = "ADMIN-NAME"
$serverPassword = "ADMIN-PASSWORD"
$securePassword = ConvertTo-SecureString -String $serverPassword -AsPlainText -Force
$creds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $serverAdmin, $securePassword
$exportRequest
Next steps
To learn about long-term backup retention of an Azure SQL database backup as an alternative to exported a
database for archive purposes, see Long-term backup retention.
For a SQL Server Customer Advisory Team blog about migrating using BACPAC files, see Migrating from SQL
Server to Azure SQL Database using BACPAC Files.
To learn about importing a BACPAC to a SQL Server database, see Import a BACPCAC to a SQL Server
database.
To learn about exporting a BACPAC from a SQL Server database, see Export a Data-tier Application and
Migrate your first database.
Monitoring database performance in Azure SQL
Database
2/17/2017 • 2 min to read • Edit Online
Monitoring the performance of a SQL database in Azure starts with monitoring the resource utilization relative to
the level of database performance you choose. Monitoring helps you determine whether your database has excess
capacity or is having trouble because resources are maxed out, and then decide whether it's time to adjust the
performance level and service tier of your database. You can monitor your database using graphical tools in the
Azure portal or using SQL dynamic management views.
You can also configure alerts on the performance metrics. Click the Add alert button in the Metric window. Follow
the wizard to configure your alert. You have the option to alert if the metrics exceed a certain threshold or if the
metric falls below a certain threshold.
For example, if you expect the workload on your database to grow, you can choose to configure an email alert
whenever your database reaches 80% on any of the performance metrics. You can use this as an early warning to
figure out when you might have to switch to the next higher performance level.
The performance metrics can also help you determine if you are able to downgrade to a lower performance level.
Assume you are using a Standard S2 database and all performance metrics show that the database on average
does not use more than 10% at any given time. It is likely that the database will work well in Standard S1. However,
be aware of workloads that spike or fluctuate before making the decision to move to a lower performance level.
NOTE
sys.dm_db_resource_stats returns an empty result set when used in Web and Business edition databases, which are retired.
For elastic pools, you can monitor individual databases in the pool with the techniques described in this section. But
you can also monitor the pool as a whole. For information, see Monitor and manage an elastic pool.
SQL Database Advisor
2/1/2017 • 3 min to read • Edit Online
Azure SQL Database learns and adapts with your application and provides customized recommendations enabling
you to maximize the performance of your SQL databases. The SQL Database Advisor provides recommendations
for creating and dropping indexes, parameterizing queries, and fixing schema issues. The advisor assesses
performance by analyzing your SQL database's usage history. The recommendations that are best suited for
running your database’s typical workload are recommended.
The following recommendations are available for Azure SQL Database servers. Currently you can set the create
and drop index recommendations to be applied automatically, see Automatic index management for details.
201 Procedure or function '' expects parameter '', which was not
supplied.
Next steps
Monitor your recommendations and continue to apply them to refine performance. Database workloads are
dynamic and change continuously. SQL Database advisor continues to monitor and provide recommendations
that can potentially improve your database's performance.
See SQL Database Advisor in the Azure portal for steps on how to use SQL Database Advisor in the Azure
portal.
See Query Performance Insights to learn about and view the performance impact of your top queries.
Additional resources
Query Store
CREATE INDEX
Role-based access control
Azure SQL Database Query Performance Insight
1/31/2017 • 7 min to read • Edit Online
Managing and tuning the performance of relational databases is a challenging task that requires significant
expertise and time investment. Query Performance Insight allows you to spend less time troubleshooting
database performance by providing the following:
Deeper insight into your databases resource (DTU) consumption.
The top queries by CPU/Duration/Execution count, which can potentially be tuned for improved performance.
The ability to drill down into the details of a query, view its text and history of resource utilization.
Performance tuning annotations that show actions performed by SQL Azure Database Advisor
Prerequisites
Query Performance Insight requires that Query Store is active on your database. If Query Store is not running,
the portal prompts you to turn it on.
Permissions
The following role-based access control permissions are required to use Query Performance Insight:
Reader, Owner, Contributor, SQL DB Contributor, or SQL Server Contributor permissions are required to
view the top resource consuming queries and charts.
Owner, Contributor, SQL DB Contributor, or SQL Server Contributor permissions are required to view
query text.
The top queries view opens and the top CPU consuming queries are listed.
2. Click around the chart for details.
The top line shows overall DTU% for the database, while the bars show CPU% consumed by the selected
queries during the selected interval (for example, if Past week is selected each bar represents one day).
The bottom grid represents aggregated information for the visible queries.
Query ID - unique identifier of query inside database.
CPU per query during observable interval (depends on aggregation function).
Duration per query (depends on aggregation function).
Total number of executions for a particular query.
Select or clear individual queries to include or exclude them from the chart using checkboxes.
3. If your data becomes stale, click the Refresh button.
4. You can use sliders and zoom buttons to change observation interval and investigate spikes:
5. Optionally, if you want a different view, you can select Custom tab and set:
Metric (CPU, duration, execution count)
Time interval (Last 24 hours, Past week, Past month).
Number of queries.
Aggregation function.
Viewing individual query details
To view query details:
1. Click any query in the list of top queries.
2. The details view opens and the queries CPU consumption/Duration/Execution count is broken down over time.
3. Click around the chart for details.
Top chart shows line with overall database DTU%, and the bars are CPU% consumed by the selected
query.
Second chart shows total duration by the selected query.
Bottom chart shows total number of executions by the selected query.
4. Optionally, use sliders, zoom buttons or click Settings to customize how query data is displayed, or to pick a
different time period.
If you want to know more or apply advisor recommendation, click the icon. It will open details of action. If it’s an
active recommendation you can apply it straight away using command.
Multiple annotations.
It’s possible, that because of zoom level, annotations that are close to each other will get collapsed into one. This
will be represented by special icon, clicking it will open new blade where list of grouped annotations will be
shown. Correlating queries and performance tuning actions can help to better understand your workload.
Second case happens when Query Store is Off or parameters aren’t set optimally.
You can change the Retention and Capture policy and enable Query Store by executing commands below or
directly from portal:
Recommended retention and capture policy
There are two types of retention policies:
Size based - if set to AUTO it will clean data automatically when near max size is reached.
Time based - by default we will set it to 30 days, which means, if Query Store will run out of space, it will
delete query information older than 30 days
Capture policy could be set to:
All - Captures all queries.
Auto - Infrequent queries and queries with insignificant compile and execution duration are ignored.
Thresholds for execution count, compile and runtime duration are internally determined. This is the default
option.
None - Query Store stops capturing new queries, however runtime stats for already captured queries are still
collected.
We recommend setting all policies to AUTO and clean policy to 30 days:
Increase size of Query Store. This could be performed by connecting to a database and issuing following query:
Applying these settings will eventually make Query Store collecting new queries, however if you don’t want to
wait you can clear Query Store.
NOTE
Executing following query will delete all current information in the Query Store.
Summary
Query Performance Insight helps you understand the impact of your query workload and how it relates to
database resource consumption. With this feature, you will learn about the top consuming queries, and easily
identify the ones to fix before they become a problem.
Next steps
For additional recommendations about improving the performance of your SQL database, click
Recommendations on the Query Performance Insight blade.
Operating the Query Store in Azure SQL Database
2/2/2017 • 2 min to read • Edit Online
Query Store in Azure is a fully managed database feature that continuously collects and presents detailed historic
information about all queries. You can think about Query Store as similar to an airplane's flight data recorder that
significantly simplifies query performance troubleshooting both for cloud and on-premises customers. This article
explains specific aspects of operating Query Store in Azure. Using this pre-collected query data, you can quickly
diagnose and resolve performance problems and thus spend more time focusing on their business.
Query Store has been globally available in Azure SQL Database since November, 2015. Query Store is the
foundation for performance analysis and tuning features, such as SQL Database Advisor and Performance
Dashboard. At the moment of publishing this article, Query Store is running in more than 200,000 user databases
in Azure, collecting query-related information for several months, without interruption.
IMPORTANT
Microsoft is in the process of activating Query Store for all Azure SQL databases (existing and new).
MAX_STORAGE_SIZE_MB Specifies the limit for the 100 Enforced for new databases
data space that Query Store
can take inside z customer
database
QUERY_CAPTURE_MODE Specifies whether all queries AUTO Enforced for all databases
or only a subset of queries
are tracked
IMPORTANT
These defaults are automatically applied in the final stage of Query Store activation in all Azure SQL databases (see preceding
important note). After this light up, Azure SQL Database won’t be changing configuration values set by customers, unless
they negatively impact primary workload or reliable operations of the Query Store.
If you want to stay with your custom settings, use ALTER DATABASE with Query Store options to revert
configuration to the previous state. Check out Best Practices with the Query Store in order to learn how top chose
optimal configuration parameters.
Next steps
SQL Database Performance Insight
Additional resources
For more information check out the following articles:
A flight data recorder for your database
Monitoring Performance By Using the Query Store
Query Store Usage Scenarios
Monitoring Performance By Using the Query Store
Monitoring Azure SQL Database using dynamic
management views
1/17/2017 • 3 min to read • Edit Online
Microsoft Azure SQL Database enables a subset of dynamic management views to diagnose performance
problems, which might be caused by blocked or long-running queries, resource bottlenecks, poor query plans, and
so on. This topic provides information on how to detect common performance problems by using dynamic
management views.
SQL Database partially supports three categories of dynamic management views:
Database-related dynamic management views.
Execution-related dynamic management views.
Transaction-related dynamic management views.
For detailed information on dynamic management views, see Dynamic Management Views and Functions
(Transact-SQL) in SQL Server Books Online.
Permissions
In SQL Database, querying a dynamic management view requires VIEW DATABASE STATE permissions. The
VIEW DATABASE STATE permission returns information about all objects within the current database. To grant
the VIEW DATABASE STATE permission to a specific database user, run the following query:
GRANT VIEW DATABASE STATE TO database_user;
In an instance of on-premises SQL Server, dynamic management views return server state information. In SQL
Database, they return information regarding your current logical database only.
The following query returns the size of individual objects (in megabytes) in your database:
Monitoring connections
You can use the sys.dm_exec_connections view to retrieve information about the connections established to a
specific Azure SQL Database server and the details of each connection. In addition, the sys.dm_exec_sessions view
is helpful when retrieving information about all active user connections and internal tasks. The following query
retrieves information on the current connection:
SELECT
c.session_id, c.net_transport, c.encrypt_option,
c.auth_scheme, s.host_name, s.program_name,
s.client_interface_name, s.login_name, s.nt_domain,
s.nt_user_name, s.original_login_name, c.connect_time,
s.login_time
FROM sys.dm_exec_connections AS c
JOIN sys.dm_exec_sessions AS s
ON c.session_id = s.session_id
WHERE c.session_id = @@SPID;
NOTE
When executing the sys.dm_exec_requests and sys.dm_exec_sessions views, if you have VIEW DATABASE STATE
permission on the database, you see all executing sessions on the database; otherwise, you see only the current session.
See also
Introduction to SQL Database
Azure SQL Database and performance for single
databases
4/19/2017 • 30 min to read • Edit Online
Azure SQL Database offers four service tiers: Basic, Standard, Premium, and Premium RS. Each service tier strictly
isolates the resources that your SQL database can use, and guarantees predictable performance for that service
level. In this article, we offer guidance that can help you choose the service tier for your application. We also
discuss ways that you can tune your application to get the most from Azure SQL Database.
NOTE
This article focuses on performance guidance for single databases in Azure SQL Database. For performance guidance related
to elastic pools, see Price and performance considerations for elastic pools. Note, though, that you can apply many of the
tuning recommendations in this article to databases in an elastic pool, and get similar performance benefits.
Max DTUs 5
Max in- 1 GB 2 GB 4 GB 8 GB 14 GB 32 GB
memory OLTP
storage
* Max database size refers to the maximum size of the data in the database.
IMPORTANT
Customers using P11 and P15 performance levels can use up to 4 TB of included storage at no additional charge. This 4 TB
option is currently available in the following regions: US East2, West US, West Europe, South East Asia, Japan East, Australia
East, Canada Central, and Canada East.
To analyze the workload of an on-premises SQL Server database, modify this query to filter on the specific
database you want to analyze. For example, if you have an on-premises database named MyDatabase, this
Transact-SQL query returns the count of concurrent requests in that database:
This is just a snapshot at a single point in time. To get a better understanding of your workload and concurrent
request requirements, you'll need to collect many samples over time.
Maximum concurrent logins
You can analyze your user and application patterns to get an idea of the frequency of logins. You also can run real-
world loads in a test environment to make sure that you're not hitting this or other limits we discuss in this article.
There isn’t a single query or dynamic management view (DMV) that can show you concurrent login counts or
history.
If multiple clients use the same connection string, the service authenticates each login. If 10 users simultaneously
connect to a database by using the same username and password, there would be 10 concurrent logins. This limit
applies only to the duration of the login and authentication. If the same 10 users connect to the database
sequentially, the number of concurrent logins would never be greater than 1.
NOTE
Currently, this limit does not apply to databases in elastic pools.
Maximum sessions
To see the number of current active sessions, run this Transact-SQL query on your SQL database:
If you're analyzing an on-premises SQL Server workload, modify the query to focus on a specific database. This
query helps you determine possible session needs for the database if you are considering moving it to Azure SQL
Database.
Again, these queries return a point-in-time count. If you collect multiple samples over time, you’ll have the best
understanding of your session use.
For SQL Database analysis, you can get historical statistics on sessions by querying the sys.resource_stats view and
reviewing the active_session_count column.
SELECT
AVG(avg_cpu_percent) AS 'Average CPU use in percent',
MAX(avg_cpu_percent) AS 'Maximum CPU use in percent',
AVG(avg_data_io_percent) AS 'Average data I/O in percent',
MAX(avg_data_io_percent) AS 'Maximum data I/O in percent',
AVG(avg_log_write_percent) AS 'Average log write use in percent',
MAX(avg_log_write_percent) AS 'Maximum log write use in percent',
AVG(avg_memory_usage_percent) AS 'Average memory use in percent',
MAX(avg_memory_usage_percent) AS 'Maximum memory use in percent'
FROM sys.dm_db_resource_stats;
NOTE
You must be connected to the master database of your logical SQL database server to query sys.resource_stats in the
following examples.
This example shows you how the data in this view is exposed:
SELECT TOP 10 *
FROM sys.resource_stats
WHERE database_name = 'resource1'
ORDER BY start_time DESC
The next example shows you different ways that you can use the sys.resource_stats catalog view to get
information about how your SQL database uses resources:
1. To look at the past week’s resource use for the database userdb1, you can run this query:
SELECT *
FROM sys.resource_stats
WHERE database_name = 'userdb1' AND
start_time > DATEADD(day, -7, GETDATE())
ORDER BY start_time DESC;
2. To evaluate how well your workload fits the performance level, you need to drill down into each aspect of
the resource metrics: CPU, reads, writes, number of workers, and number of sessions. Here's a revised
query using sys.resource_stats to report the average and maximum values of these resource metrics:
SELECT
avg(avg_cpu_percent) AS 'Average CPU use in percent',
max(avg_cpu_percent) AS 'Maximum CPU use in percent',
avg(avg_data_io_percent) AS 'Average physical data I/O use in percent',
max(avg_data_io_percent) AS 'Maximum physical data I/O use in percent',
avg(avg_log_write_percent) AS 'Average log write use in percent',
max(avg_log_write_percent) AS 'Maximum log write use in percent',
avg(max_session_percent) AS 'Average % of sessions',
max(max_session_percent) AS 'Maximum % of sessions',
avg(max_worker_percent) AS 'Average % of workers',
max(max_worker_percent) AS 'Maximum % of workers'
FROM sys.resource_stats
WHERE database_name = 'userdb1' AND start_time > DATEADD(day, -7, GETDATE());
3. With this information about the average and maximum values of each resource metric, you can assess how
well your workload fits into the performance level you chose. Usually, average values from
sys.resource_stats give you a good baseline to use against the target size. It should be your primary
measurement stick. For an example, you might be using the Standard service tier with S2 performance
level. The average use percentages for CPU and I/O reads and writes are below 40 percent, the average
number of workers is below 50, and the average number of sessions is below 200. Your workload might fit
into the S1 performance level. It's easy to see whether your database fits in the worker and session limits.
To see whether a database fits into a lower performance level with regards to CPU, reads, and writes, divide
the DTU number of the lower performance level by the DTU number of your current performance level, and
then multiply the result by 100:
S1 DTU / S2 DTU * 100 = 20 / 50 * 100 = 40
The result is the relative performance difference between the two performance levels in percentage. If your
resource use doesn't exceed this amount, your workload might fit into the lower performance level.
However, you need to look at all ranges of resource use values, and determine, by percentage, how often
your database workload would fit into the lower performance level. The following query outputs the fit
percentage per resource dimension, based on the threshold of 40 percent that we calculated in this
example:
SELECT
(COUNT(database_name) - SUM(CASE WHEN avg_cpu_percent >= 40 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name) AS
'CPU Fit Percent'
,(COUNT(database_name) - SUM(CASE WHEN avg_log_write_percent >= 40 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name)
AS 'Log Write Fit Percent'
,(COUNT(database_name) - SUM(CASE WHEN avg_data_io_percent >= 40 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name)
AS 'Physical Data IO Fit Percent'
FROM sys.resource_stats
WHERE database_name = 'userdb1' AND start_time > DATEADD(day, -7, GETDATE());
Based on your database service level objective (SLO), you can decide whether your workload fits into the
lower performance level. If your database workload SLO is 99.9 percent and the preceding query returns
values greater than 99.9 percent for all three resource dimensions, your workload likely fits into the lower
performance level.
Looking at the fit percentage also gives you insight into whether you should move to the next higher
performance level to meet your SLO. For example, userdb1 shows the following CPU use for the past week:
AVERAGE CPU PERCENT MAXIMUM CPU PERCENT
24.5 100.00
The average CPU is about a quarter of the limit of the performance level, which would fit well into the
performance level of the database. But, the maximum value shows that the database reaches the limit of the
performance level. Do you need to move to the next higher performance level? Look at how many times
your workload reaches 100 percent, and then compare it to your database workload SLO.
SELECT
(COUNT(database_name) - SUM(CASE WHEN avg_cpu_percent >= 100 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name) AS
'CPU fit percent'
,(COUNT(database_name) - SUM(CASE WHEN avg_log_write_percent >= 100 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name)
AS 'Log write fit percent'
,(COUNT(database_name) - SUM(CASE WHEN avg_data_io_percent >= 100 THEN 1 ELSE 0 END) * 1.0) / COUNT(database_name)
AS 'Physical data I/O fit percent'
FROM sys.resource_stats
WHERE database_name = 'userdb1' AND start_time > DATEADD(day, -7, GETDATE());
If this query returns a value less than 99.9 percent for any of the three resource dimensions, consider either
moving to the next higher performance level or use application-tuning techniques to reduce the load on the
SQL database.
4. This exercise also considers your projected workload increase in the future.
Tuning techniques
In this section, we look at some techniques that you can use to tune Azure SQL Database to gain the best
performance for your application and run it at the lowest possible performance level. Some of these techniques
match traditional SQL Server tuning best practices, but others are specific to Azure SQL Database. In some cases,
you can examine the consumed resources for a database to find areas to further tune and extend traditional SQL
Server techniques to work in Azure SQL Database.
Azure portal tools
The following tools in the Azure portal can help you analyze and fix performance issues with your SQL database:
Query Performance Insight
SQL Database Advisor
The Azure portal has more information about both of these tools and how to use them. To efficiently diagnose and
correct problems, we recommend that you first try the tools in the Azure portal. We recommend that you use the
manual tuning approaches that we discuss next, for missing indexes and query tuning, in special cases.
Missing indexes
A common problem in OLTP database performance relates to the physical database design. Often, database
schemas are designed and shipped without testing at scale (either in load or in data volume). Unfortunately, the
performance of a query plan might be acceptable on a small scale but degrade substantially under production-
level data volumes. The most common source of this issue is the lack of appropriate indexes to satisfy filters or
other restrictions in a query. Often, missing indexes manifests as a table scan when an index seek could suffice.
In this example, the selected query plan uses a scan when a seek would suffice:
After it's created, that same SELECT statement picks a different plan, which uses a seek instead of a scan, and then
executes the plan more efficiently:
The key insight is that the I/O capacity of a shared, commodity system is more limited than that of a dedicated
server machine. There's a premium on minimizing unnecessary I/O to take maximum advantage of the system in
the DTU of each performance level of the Azure SQL Database service tiers. Appropriate physical database design
choices can significantly improve the latency for individual queries, improve the throughput of concurrent
requests handled per scale unit, and minimize the costs required to satisfy the query. For more information about
the missing index DMVs, see sys.dm_db_missing_index_details.
Query tuning and hinting
The query optimizer in Azure SQL Database is similar to the traditional SQL Server query optimizer. Most of the
best practices for tuning queries and understanding the reasoning model limitations for the query optimizer also
apply to Azure SQL Database. If you tune queries in Azure SQL Database, you might get the additional benefit of
reducing aggregate resource demands. Your application might be able to run at a lower cost than an untuned
equivalent because it can run at a lower performance level.
An example that is common in SQL Server and which also applies to Azure SQL Database is how the query
optimizer "sniffs" parameters. During compilation, the query optimizer evaluates the current value of a parameter
to determine whether it can generate a more optimal query plan. Although this strategy often can lead to a query
plan that is significantly faster than a plan compiled without known parameter values, currently it works
imperfectly both in SQL Server and in Azure SQL Database. Sometimes the parameter is not sniffed, and
sometimes the parameter is sniffed but the generated plan is suboptimal for the full set of parameter values in a
workload. Microsoft includes query hints (directives) so that you can specify intent more deliberately and override
the default behavior of parameter sniffing. Often, if you use hints, you can fix cases in which the default SQL Server
or Azure SQL Database behavior is imperfect for a specific customer workload.
The next example demonstrates how the query processor can generate a plan that is suboptimal both for
performance and resource requirements. This example also shows that if you use a query hint, you can reduce
query run time and resource requirements for your SQL database:
DECLARE @a int = 0;
SET NOCOUNT ON;
BEGIN TRANSACTION
WHILE @a < 20000
BEGIN
INSERT INTO psptest1(col2) values (1);
INSERT INTO psptest1(col2) values (@a);
SET @a += 1;
END
COMMIT TRANSACTION
CREATE INDEX i1 on psptest1(col2);
GO
CREATE TABLE t1 (col1 int primary key, col2 int, col3 binary(200));
GO
The setup code creates a table that has skewed data distribution. The optimal query plan differs based on which
parameter is selected. Unfortunately, the plan caching behavior doesn't always recompile the query based on the
most common parameter value. So, it's possible for a suboptimal plan to be cached and used for many values,
even when a different plan might be a better plan choice on average. Then the query plan creates two stored
procedures that are identical, except that one has a special query hint.
Example, part 1
Example, part 2
(We recommend that you wait at least 10 minutes before you begin part 2 of the example, so that the results are
distinct in the resulting telemetry data.)
DECLARE @i int = 0;
WHILE @i < 1000
BEGIN
EXEC psp2 @param2=2;
TRUNCATE TABLE t1;
SET @i += 1;
END
Each part of this example attempts to run a parameterized insert statement 1,000 times (to generate a sufficient
load to use as a test data set). When it executes stored procedures, the query processor examines the parameter
value that is passed to the procedure during its first compilation (parameter "sniffing"). The processor caches the
resulting plan and uses it for later invocations, even if the parameter value is different. The optimal plan might not
be used in all cases. Sometimes you need to guide the optimizer to pick a plan that is better for the average case
rather than the specific case from when the query was first compiled. In this example, the initial plan generates a
"scan" plan that reads all rows to find each value that matches the parameter:
Because we executed the procedure by using the value 1, the resulting plan was optimal for the value 1 but was
suboptimal for all other values in the table. The result likely isn't what you would want if you were to pick each
plan randomly, because the plan performs more slowly and uses more resources.
If you run the test with SET STATISTICS IO set to ON , the logical scan work in this example is done behind the
scenes. You can see that there are 1,148 reads done by the plan (which is inefficient, if the average case is to return
just one row):
The second part of the example uses a query hint to tell the optimizer to use a specific value during the
compilation process. In this case, it forces the query processor to ignore the value that is passed as the parameter,
and instead to assume UNKNOWN . This refers to a value that has the average frequency in the table (ignoring
skew). The resulting plan is a seek-based plan that is faster and uses fewer resources, on average, than the plan in
part 1 of this example:
You can see the effect in the sys.resource_stats table (there is a delay from the time that you execute the test and
when the data populates the table). For this example, part 1 executed during the 22:25:00 time window, and part 2
executed at 22:35:00. The earlier time window used more resources in that time window than the later one
(because of plan efficiency improvements).
NOTE
Although the volume in this example is intentionally small, the effect of suboptimal parameters can be substantial, especially
on larger databases. The difference, in extreme cases, can be between seconds for fast cases and hours for slow cases.
You can examine sys.resource_stats to determine whether the resource for a test uses more or fewer resources
than another test. When you compare data, separate the timing of tests so that they are not in the same 5-minute
window in the sys.resource_stats view. The goal of the exercise is to minimize the total amount of resources used,
and not to minimize the peak resources. Generally, optimizing a piece of code for latency also reduces resource
consumption. Make sure that the changes you make to an application are necessary, and that the changes don't
negatively affect the customer experience for someone who might be using query hints in the application.
If a workload has a set of repeating queries, often it makes sense to capture and validate the optimality of your
plan choices because it drives the minimum resource size unit required to host the database. After you validate it,
occasionally reexamine the plans to help you make sure that they have not degraded. You can learn more about
query hints (Transact-SQL).
Cross-database sharding
Because Azure SQL Database runs on commodity hardware, the capacity limits for a single database are lower
than for a traditional on-premises SQL Server installation. Some customers use sharding techniques to spread
database operations over multiple databases when the operations don't fit inside the limits of a single database in
Azure SQL Database. Most customers who use sharding techniques in Azure SQL Database split their data on a
single dimension across multiple databases. For this approach, you need to understand that OLTP applications
often perform transactions that apply to only one row or to a small group of rows in the schema.
NOTE
SQL Database now provides a library to assist with sharding. For more information, see Elastic Database client library
overview.
For example, if a database has customer name, order, and order details (like the traditional example Northwind
database that ships with SQL Server), you could split this data into multiple databases by grouping a customer
with the related order and order detail information. You can guarantee that the customer's data stays in a single
database. The application would split different customers across databases, effectively spreading the load across
multiple databases. With sharding, customers not only can avoid the maximum database size limit, but Azure SQL
Database also can process workloads that are significantly larger than the limits of the different performance
levels, as long as each individual database fits into its DTU.
Although database sharding doesn't reduce the aggregate resource capacity for a solution, it's highly effective at
supporting very large solutions that are spread over multiple databases. Each database can run at a different
performance level to support very large, "effective" databases with high resource requirements.
Functional partitioning
SQL Server users often combine many functions in a single database. For example, if an application has logic to
manage inventory for a store, that database might have logic associated with inventory, tracking purchase orders,
stored procedures, and indexed or materialized views that manage end-of-month reporting. This technique makes
it easier to administer the database for operations like backup, but it also requires you to size the hardware to
handle the peak load across all functions of an application.
If you use a scale-out architecture in Azure SQL Database, it's a good idea to split different functions of an
application into different databases. By using this technique, each application scales independently. As an
application becomes busier (and the load on the database increases), the administrator can choose independent
performance levels for each function in the application. At the limit, with this architecture, an application can be
larger than a single commodity machine can handle because the load is spread across multiple machines.
Batch queries
For applications that access data by using high-volume, frequent, ad hoc querying, a substantial amount of
response time is spent on network communication between the application tier and the Azure SQL Database tier.
Even when both the application and Azure SQL Database are in the same data center, the network latency between
the two might be magnified by a large number of data access operations. To reduce the network round trips for
the data access operations, consider using the option to either batch the ad hoc queries, or to compile them as
stored procedures. If you batch the ad hoc queries, you can send multiple queries as one large batch in a single trip
to Azure SQL Database. If you compile ad hoc queries in a stored procedure, you could achieve the same result as
if you batch them. Using a stored procedure also gives you the benefit of increasing the chances of caching the
query plans in Azure SQL Database so you can use the stored procedure again.
Some applications are write-intensive. Sometimes you can reduce the total I/O load on a database by considering
how to batch writes together. Often, this is as simple as using explicit transactions instead of auto-commit
transactions in stored procedures and ad hoc batches. For an evaluation of different techniques you can use, see
Batching techniques for SQL Database applications in Azure. Experiment with your own workload to find the right
model for batching. Be sure to understand that a model might have slightly different transactional consistency
guarantees. Finding the right workload that minimizes resource use requires finding the right combination of
consistency and performance trade-offs.
Application-tier caching
Some database applications have read-heavy workloads. Caching layers might reduce the load on the database
and might potentially reduce the performance level required to support a database by using Azure SQL Database.
With Azure Redis Cache, if you have a read-heavy workload, you can read the data once (or perhaps once per
application-tier machine, depending on how it is configured), and then store that data outside your SQL database.
This is a way to reduce database load (CPU and read I/O), but there is an effect on transactional consistency
because the data being read from the cache might be out of sync with the data in the database. Although in many
applications some level of inconsistency is acceptable, that's not true for all workloads. You should fully
understand any application requirements before you implement an application-tier caching strategy.
Next steps
For more information about service tiers, see SQL Database options and performance
For more information about elastic pools, see What is an Azure elastic pool?
For information about performance and elastic pools, see When to consider an elastic pool
How to use batching to improve SQL Database
application performance
4/19/2017 • 25 min to read • Edit Online
Batching operations to Azure SQL Database significantly improves the performance and scalability of your
applications. In order to understand the benefits, the first part of this article covers some sample test results that
compare sequential and batched requests to a SQL Database. The remainder of the article shows the techniques,
scenarios, and considerations to help you to use batching successfully in your Azure applications.
Batching strategies
Note about timing results in this topic
NOTE
Results are not benchmarks but are meant to show relative performance. Timings are based on an average of at least 10
test runs. Operations are inserts into an empty table. These tests were measured awhile ago, and they do not necessarily
correspond to throughput that you might experience today. The relative benefit of the batching technique should be similar.
Transactions
It seems strange to begin a review of batching by discussing transactions. But the use of client-side transactions has
a subtle server-side batching effect that improves performance. And transactions can be added with only a few
lines of code, so they provide a fast way to improve performance of sequential operations.
Consider the following C# code that contains a sequence of insert and update operations on a simple table.
The best way to optimize this code is to implement some form of client-side batching of these calls. But there is a
simple way to increase the performance of this code by simply wrapping the sequence of calls in a transaction.
Here is the same code that uses a transaction.
transaction.Commit();
}
Transactions are actually being used in both of these examples. In the first example, each individual call is an
implicit transaction. In the second example, an explicit transaction wraps all of the calls. Per the documentation for
the write-ahead transaction log, log records are flushed to the disk when the transaction commits. So by including
more calls in a transaction, the write to the transaction log can delay until the transaction is committed. In effect,
you are enabling batching for the writes to the server’s transaction log.
The following table shows some ad-hoc testing results. The tests performed the same sequential inserts with and
without transactions. For more perspective, the first set of tests ran remotely from a laptop to the database in
Microsoft Azure. The second set of tests ran from a cloud service and database that both resided within the same
Microsoft Azure datacenter (West US). The following table shows the duration in milliseconds of sequential inserts
with and without transactions.
On-Premises to Azure:
OPERATIONS NO TRANSACTION (MS) TRANSACTION (MS)
1 130 402
10 1208 1226
1 21 26
10 220 56
NOTE
Results are not benchmarks. See the note about timing results in this topic.
Based on the previous test results, wrapping a single operation in a transaction actually decreases performance. But
as you increase the number of operations within a single transaction, the performance improvement becomes
more marked. The performance difference is also more noticeable when all operations occur within the Microsoft
Azure datacenter. The increased latency of using SQL Database from outside the Microsoft Azure datacenter
overshadows the performance gain of using transactions.
Although the use of transactions can increase performance, continue to observe best practices for transactions and
connections. Keep the transaction as short as possible, and close the database connection after the work completes.
The using statement in the previous example assures that the connection is closed when the subsequent code block
completes.
The previous example demonstrates that you can add a local transaction to any ADO.NET code with two lines.
Transactions offer a quick way to improve the performance of code that makes sequential insert, update, and delete
operations. However, for the fastest performance, consider changing the code further to take advantage of client-
side batching, such as table-valued parameters.
For more information about transactions in ADO.NET, see Local Transactions in ADO.NET.
Table -valued parameters
Table-valued parameters support user-defined table types as parameters in Transact-SQL statements, stored
procedures, and functions. This client-side batching technique allows you to send multiple rows of data within the
table-valued parameter. To use table-valued parameters, first define a table type. The following Transact-SQL
statement creates a table type named MyTableType.
cmd.Parameters.Add(
new SqlParameter()
{
ParameterName = "@TestTvp",
SqlDbType = SqlDbType.Structured,
TypeName = "MyTableType",
Value = table,
});
cmd.ExecuteNonQuery();
}
In the previous example, the SqlCommand object inserts rows from a table-valued parameter, @TestTvp. The
previously created DataTable object is assigned to this parameter with the SqlCommand.Parameters.Add
method. Batching the inserts in one call significantly increases the performance over sequential inserts.
To improve the previous example further, use a stored procedure instead of a text-based command. The following
Transact-SQL command creates a stored procedure that takes the SimpleTestTableType table-valued parameter.
Then change the SqlCommand object declaration in the previous code example to the following.
In most cases, table-valued parameters have equivalent or better performance than other batching techniques.
Table-valued parameters are often preferable, because they are more flexible than other options. For example,
other techniques, such as SQL bulk copy, only permit the insertion of new rows. But with table-valued parameters,
you can use logic in the stored procedure to determine which rows are updates and which are inserts. The table
type can also be modified to contain an “Operation” column that indicates whether the specified row should be
inserted, updated, or deleted.
The following table shows ad-hoc test results for the use of table-valued parameters in milliseconds.
1 124 32
10 131 25
100 338 51
NOTE
Results are not benchmarks. See the note about timing results in this topic.
The performance gain from batching is immediately apparent. In the previous sequential test, 1000 operations took
129 seconds outside the datacenter and 21 seconds from within the datacenter. But with table-valued parameters,
1000 operations take only 2.6 seconds outside the datacenter and 0.4 seconds within the datacenter.
For more information on table-valued parameters, see Table-Valued Parameters.
SQL bulk copy
SQL bulk copy is another way to insert large amounts of data into a target database. .NET applications can use the
SqlBulkCopy class to perform bulk insert operations. SqlBulkCopy is similar in function to the command-line
tool, Bcp.exe, or the Transact-SQL statement, BULK INSERT. The following code example shows how to bulk copy
the rows in the source DataTable, table, to the destination table in SQL Server, MyTable.
There are some cases where bulk copy is preferred over table-valued parameters. See the comparison table of
Table-Valued parameters versus BULK INSERT operations in the topic Table-Valued Parameters.
The following ad-hoc test results show the performance of batching with SqlBulkCopy in milliseconds.
1 433 57
10 441 32
100 636 53
OPERATIONS ON-PREMISES TO AZURE (MS) AZURE SAME DATACENTER (MS)
NOTE
Results are not benchmarks. See the note about timing results in this topic.
In smaller batch sizes, the use table-valued parameters outperformed the SqlBulkCopy class. However,
SqlBulkCopy performed 12-31% faster than table-valued parameters for the tests of 1,000 and 10,000 rows. Like
table-valued parameters, SqlBulkCopy is a good option for batched inserts, especially when compared to the
performance of non-batched operations.
For more information on bulk copy in ADO.NET, see Bulk Copy Operations in SQL Server.
Multiple -row Parameterized INSERT statements
One alternative for small batches is to construct a large parameterized INSERT statement that inserts multiple rows.
The following code example demonstrates this technique.
cmd.ExecuteNonQuery();
}
This example is meant to show the basic concept. A more realistic scenario would loop through the required entities
to construct the query string and the command parameters simultaneously. You are limited to a total of 2100 query
parameters, so this limits the total number of rows that can be processed in this manner.
The following ad-hoc test results show the performance of this type of insert statement in milliseconds.
1 32 20
10 30 25
100 33 51
NOTE
Results are not benchmarks. See the note about timing results in this topic.
This approach can be slightly faster for batches that are less than 100 rows. Although the improvement is small,
this technique is another option that might work well in your specific application scenario.
DataAdapter
The DataAdapter class allows you to modify a DataSet object and then submit the changes as INSERT, UPDATE,
and DELETE operations. If you are using the DataAdapter in this manner, it is important to note that separate calls
are made for each distinct operation. To improve performance, use the UpdateBatchSize property to the number
of operations that should be batched at a time. For more information, see Performing Batch Operations Using
DataAdapters.
Entity framework
Entity Framework does not currently support batching. Different developers in the community have attempted to
demonstrate workarounds, such as override the SaveChanges method. But the solutions are typically complex and
customized to the application and data model. The Entity Framework codeplex project currently has a discussion
page on this feature request. To view this discussion, see Design Meeting Notes - August 2, 2012.
XML
For completeness, we feel that it is important to talk about XML as a batching strategy. However, the use of XML
has no advantages over other methods and several disadvantages. The approach is similar to table-valued
parameters, but an XML file or string is passed to a stored procedure instead of a user-defined table. The stored
procedure parses the commands in the stored procedure.
There are several disadvantages to this approach:
Working with XML can be cumbersome and error prone.
Parsing the XML on the database can be CPU-intensive.
In most cases, this method is slower than table-valued parameters.
For these reasons, the use of XML for batch queries is not recommended.
Batching considerations
The following sections provide more guidance for the use of batching in SQL Database applications.
Tradeoffs
Depending on your architecture, batching can involve a tradeoff between performance and resiliency. For example,
consider the scenario where your role unexpectedly goes down. If you lose one row of data, the impact is smaller
than the impact of losing a large batch of unsubmitted rows. There is a greater risk when you buffer rows before
sending them to the database in a specified time window.
Because of this tradeoff, evaluate the type of operations that you batch. Batch more aggressively (larger batches
and longer time windows) with data that is less critical.
Batch size
In our tests, there was typically no advantage to breaking large batches into smaller chunks. In fact, this subdivision
often resulted in slower performance than submitting a single large batch. For example, consider a scenario where
you want to insert 1000 rows. The following table shows how long it takes to use table-valued parameters to insert
1000 rows when divided into smaller batches.
BATCH SIZE ITERATIONS TABLE-VALUED PARAMETERS (MS)
1000 1 347
500 2 355
100 10 465
50 20 630
NOTE
Results are not benchmarks. See the note about timing results in this topic.
You can see that the best performance for 1000 rows is to submit them all at once. In other tests (not shown here)
there was a small performance gain to break a 10000 row batch into two batches of 5000. But the table schema for
these tests is relatively simple, so you should perform tests on your specific data and batch sizes to verify these
findings.
Another factor to consider is that if the total batch becomes too large, SQL Database might throttle and refuse to
commit the batch. For the best results, test your specific scenario to determine if there is an ideal batch size. Make
the batch size configurable at runtime to enable quick adjustments based on performance or errors.
Finally, balance the size of the batch with the risks associated with batching. If there are transient errors or the role
fails, consider the consequences of retrying the operation or of losing the data in the batch.
Parallel processing
What if you took the approach of reducing the batch size but used multiple threads to execute the work? Again, our
tests showed that several smaller multithreaded batches typically performed worse than a single larger batch. The
following test attempts to insert 1000 rows in one or more parallel batches. This test shows how more
simultaneous batches actually decreased performance.
BATCH SIZE [ITERATIONS] TWO THREADS (MS) FOUR THREADS (MS) SIX THREADS (MS)
NOTE
Results are not benchmarks. See the note about timing results in this topic.
There are several potential reasons for the degradation in performance due to parallelism:
There are multiple simultaneous network calls instead of one.
Multiple operations against a single table can result in contention and blocking.
There are overheads associated with multithreading.
The expense of opening multiple connections outweighs the benefit of parallel processing.
If you target different tables or databases, it is possible to see some performance gain with this strategy. Database
sharding or federations would be a scenario for this approach. Sharding uses multiple databases and routes
different data to each database. If each small batch is going to a different database, then performing the operations
in parallel can be more efficient. However, the performance gain is not significant enough to use as the basis for a
decision to use database sharding in your solution.
In some designs, parallel execution of smaller batches can result in improved throughput of requests in a system
under load. In this case, even though it is quicker to process a single larger batch, processing multiple batches in
parallel might be more efficient.
If you do use parallel execution, consider controlling the maximum number of worker threads. A smaller number
might result in less contention and a faster execution time. Also, consider the additional load that this places on the
target database both in connections and transactions.
Related performance factors
Typical guidance on database performance also affects batching. For example, insert performance is reduced for
tables that have a large primary key or many nonclustered indexes.
If table-valued parameters use a stored procedure, you can use the command SET NOCOUNT ON at the beginning
of the procedure. This statement suppresses the return of the count of the affected rows in the procedure. However,
in our tests, the use of SET NOCOUNT ON either had no effect or decreased performance. The test stored
procedure was simple with a single INSERT command from the table-valued parameter. It is possible that more
complex stored procedures would benefit from this statement. But don’t assume that adding SET NOCOUNT ON
to your stored procedure automatically improves performance. To understand the effect, test your stored
procedure with and without the SET NOCOUNT ON statement.
Batching scenarios
The following sections describe how to use table-valued parameters in three application scenarios. The first
scenario shows how buffering and batching can work together. The second scenario improves performance by
performing master-detail operations in a single stored procedure call. The final scenario shows how to use table-
valued parameters in an “UPSERT” operation.
Buffering
Although there are some scenarios that are obvious candidate for batching, there are many scenarios that could
take advantage of batching by delayed processing. However, delayed processing also carries a greater risk that the
data is lost in the event of an unexpected failure. It is important to understand this risk and consider the
consequences.
For example, consider a web application that tracks the navigation history of each user. On each page request, the
application could make a database call to record the user’s page view. But higher performance and scalability can
be achieved by buffering the users’ navigation activities and then sending this data to the database in batches. You
can trigger the database update by elapsed time and/or buffer size. For example, a rule could specify that the batch
should be processed after 20 seconds or when the buffer reaches 1000 items.
The following code example uses Reactive Extensions - Rx to process buffered events raised by a monitoring class.
When the buffer fills or a timeout is reached, the batch of user data is sent to the database with a table-valued
parameter.
The following NavHistoryData class models the user navigation details. It contains basic information such as the
user identifier, the URL accessed, and the access time.
public class NavHistoryData
{
public NavHistoryData(int userId, string url, DateTime accessTime)
{ UserId = userId; URL = url; AccessTime = accessTime; }
public int UserId { get; set; }
public string URL { get; set; }
public DateTime AccessTime { get; set; }
}
The NavHistoryDataMonitor class is responsible for buffering the user navigation data to the database. It contains a
method, RecordUserNavigationEntry, which responds by raising an OnAdded event. The following code shows the
constructor logic that uses Rx to create an observable collection based on the event. It then subscribes to this
observable collection with the Buffer method. The overload specifies that the buffer should be sent every 20
seconds or 1000 entries.
public NavHistoryDataMonitor()
{
var observableData =
Observable.FromEventPattern<NavHistoryDataEventArgs>(this, "OnAdded");
observableData.Buffer(TimeSpan.FromSeconds(20), 1000).Subscribe(Handler);
}
The handler converts all of the buffered items into a table-valued type and then passes this type to a stored
procedure that processes the batch. The following code shows the complete definition for both the
NavHistoryDataEventArgs and the NavHistoryDataMonitor classes.
public class NavHistoryDataEventArgs : System.EventArgs
{
public NavHistoryDataEventArgs(NavHistoryData data) { Data = data; }
public NavHistoryData Data { get; set; }
}
public NavHistoryDataMonitor()
{
var observableData =
Observable.FromEventPattern<NavHistoryDataEventArgs>(this, "OnAdded");
observableData.Buffer(TimeSpan.FromSeconds(20), 1000).Subscribe(Handler);
}
cmd.Parameters.Add(
new SqlParameter()
{
ParameterName = "@NavHistoryBatch",
SqlDbType = SqlDbType.Structured,
TypeName = "NavigationHistoryTableType",
Value = navHistoryBatch,
});
cmd.ExecuteNonQuery();
}
}
}
To use this buffering class, the application creates a static NavHistoryDataMonitor object. Each time a user accesses
a page, the application calls the NavHistoryDataMonitor.RecordUserNavigationEntry method. The buffering logic
proceeds to take care of sending these entries to the database in batches.
Master detail
Table-valued parameters are useful for simple INSERT scenarios. However, it can be more challenging to batch
inserts that involve more than one table. The “master/detail” scenario is a good example. The master table identifies
the primary entity. One or more detail tables store more data about the entity. In this scenario, foreign key
relationships enforce the relationship of details to a unique master entity. Consider a simplified version of a
PurchaseOrder table and its associated OrderDetail table. The following Transact-SQL creates the PurchaseOrder
table with four columns: OrderID, OrderDate, CustomerID, and Status.
Each order contains one or more product purchases. This information is captured in the PurchaseOrderDetail table.
The following Transact-SQL creates the PurchaseOrderDetail table with five columns: OrderID, OrderDetailID,
ProductID, UnitPrice, and OrderQty.
The OrderID column in the PurchaseOrderDetail table must reference an order from the PurchaseOrder table. The
following definition of a foreign key enforces this constraint.
In order to use table-valued parameters, you must have one user-defined table type for each target table.
Then define a stored procedure that accepts tables of these types. This procedure allows an application to locally
batch a set of orders and order details in a single call. The following Transact-SQL provides the complete stored
procedure declaration for this purchase order example.
CREATE PROCEDURE sp_InsertOrdersBatch (
@orders as PurchaseOrderTableType READONLY,
@details as PurchaseOrderDetailTableType READONLY )
AS
SET NOCOUNT ON;
In this example, the locally defined @IdentityLink table stores the actual OrderID values from the newly inserted
rows. These order identifiers are different from the temporary OrderID values in the @orders and @details table-
valued parameters. For this reason, the @IdentityLink table then connects the OrderID values from the @orders
parameter to the real OrderID values for the new rows in the PurchaseOrder table. After this step, the @IdentityLink
table can facilitate inserting the order details with the actual OrderID that satisfies the foreign key constraint.
This stored procedure can be used from code or from other Transact-SQL calls. See the table-valued parameters
section of this paper for a code example. The following Transact-SQL shows how to call the sp_InsertOrdersBatch.
declare @orders as PurchaseOrderTableType
declare @details as PurchaseOrderDetailTableType
INSERT @orders
([OrderID], [OrderDate], [CustomerID], [Status])
VALUES(1, '1/1/2013', 1125, 'Complete'),
(2, '1/13/2013', 348, 'Processing'),
(3, '1/12/2013', 2504, 'Shipped')
INSERT @details
([OrderID], [ProductID], [UnitPrice], [OrderQty])
VALUES(1, 10, $11.50, 1),
(1, 12, $1.58, 1),
(2, 23, $2.57, 2),
(3, 4, $10.00, 1)
This solution allows each batch to use a set of OrderID values that begin at 1. These temporary OrderID values
describe the relationships in the batch, but the actual OrderID values are determined at the time of the insert
operation. You can run the same statements in the previous example repeatedly and generate unique orders in the
database. For this reason, consider adding more code or database logic that prevents duplicate orders when using
this batching technique.
This example demonstrates that even more complex database operations, such as master-detail operations, can be
batched using table-valued parameters.
UPSERT
Another batching scenario involves simultaneously updating existing rows and inserting new rows. This operation
is sometimes referred to as an “UPSERT” (update + insert) operation. Rather than making separate calls to INSERT
and UPDATE, the MERGE statement is best suited to this task. The MERGE statement can perform both insert and
update operations in a single call.
Table-valued parameters can be used with the MERGE statement to perform updates and inserts. For example,
consider a simplified Employee table that contains the following columns: EmployeeID, FirstName, LastName,
SocialSecurityNumber:
In this example, you can use the fact that the SocialSecurityNumber is unique to perform a MERGE of multiple
employees. First, create the user-defined table type:
Next, create a stored procedure or write code that uses the MERGE statement to perform the update and insert. The
following example uses the MERGE statement on a table-valued parameter, @employees, of type
EmployeeTableType. The contents of the @employees table are not shown here.
MERGE Employee AS target
USING (SELECT [FirstName], [LastName], [SocialSecurityNumber] FROM @employees)
AS source ([FirstName], [LastName], [SocialSecurityNumber])
ON (target.[SocialSecurityNumber] = source.[SocialSecurityNumber])
WHEN MATCHED THEN
UPDATE SET
target.FirstName = source.FirstName,
target.LastName = source.LastName
WHEN NOT MATCHED THEN
INSERT ([FirstName], [LastName], [SocialSecurityNumber])
VALUES (source.[FirstName], source.[LastName], source.[SocialSecurityNumber]);
For more information, see the documentation and examples for the MERGE statement. Although the same work
could be performed in a multiple-step stored procedure call with separate INSERT and UPDATE operations, the
MERGE statement is more efficient. Database code can also construct Transact-SQL calls that use the MERGE
statement directly without requiring two database calls for INSERT and UPDATE.
Recommendation summary
The following list provides a summary of the batching recommendations discussed in this topic:
Use buffering and batching to increase the performance and scalability of SQL Database applications.
Understand the tradeoffs between batching/buffering and resiliency. During a role failure, the risk of losing an
unprocessed batch of business-critical data might outweigh the performance benefit of batching.
Attempt to keep all calls to the database within a single datacenter to reduce latency.
If you choose a single batching technique, table-valued parameters offer the best performance and flexibility.
For the fastest insert performance, follow these general guidelines but test your scenario:
For < 100 rows, use a single parameterized INSERT command.
For < 1000 rows, use table-valued parameters.
For >= 1000 rows, use SqlBulkCopy.
For update and delete operations, use table-valued parameters with stored procedure logic that determines the
correct operation on each row in the table parameter.
Batch size guidelines:
Use the largest batch sizes that make sense for your application and business requirements.
Balance the performance gain of large batches with the risks of temporary or catastrophic failures. What
is the consequence of retries or loss of the data in the batch?
Test the largest batch size to verify that SQL Database does not reject it.
Create configuration settings that control batching, such as the batch size or the buffering time window.
These settings provide flexibility. You can change the batching behavior in production without
redeploying the cloud service.
Avoid parallel execution of batches that operate on a single table in one database. If you do choose to divide a
single batch across multiple worker threads, run tests to determine the ideal number of threads. After an
unspecified threshold, more threads will decrease performance rather than increase it.
Consider buffering on size and time as a way of implementing batching for more scenarios.
Next steps
This article focused on how database design and coding techniques related to batching can improve your
application performance and scalability. But this is just one factor in your overall strategy. For more ways to
improve performance and scalability, see Azure SQL Database performance guidance for single databases and
Price and performance considerations for an elastic pool.
Extended events in SQL Database
4/10/2017 • 5 min to read • Edit Online
This topic explains how the implementation of extended events in Azure SQL Database is slightly different
compared to extended events in Microsoft SQL Server.
SQL Database gained the extended events feature in the second half of calendar 2015.
SQL Server has had extended events since 2008.
The feature set of extended events on SQL Database is a robust subset of the features on SQL Server.
XEvents is an informal nickname that is sometimes used for 'extended events' in blogs and other informal
locations.
Additional information about extended events, for Azure SQL Database and Microsoft SQL Server, is available at:
Quick Start: Extended events in SQL Server
Extended Events
Prerequisites
This topic assumes you already have some knowledge of:
Azure SQL Database service.
Extended events in Microsoft SQL Server.
The bulk of our documentation about extended events applies to both SQL Server and SQL Database.
Prior exposure to the following items is helpful when choosing the Event File as the target:
Azure Storage service
PowerShell
Using Azure PowerShell with Azure Storage - Provides comprehensive information about PowerShell
and the Azure Storage service.
Code samples
Related topics provide two code samples:
Ring Buffer target code for extended events in SQL Database
Short simple Transact-SQL script.
We emphasize in the code sample topic that, when you are done with a Ring Buffer target, you should
release its resources by executing an alter-drop ALTER EVENT SESSION ... ON DATABASE DROP TARGET ...;
statement. Later you can add another instance of Ring Buffer by
ALTER EVENT SESSION ... ON DATABASE ADD TARGET ... .
Event File target code for extended events in SQL Database
Phase 1 is PowerShell to create an Azure Storage container.
Phase 2 is Transact-SQL that uses the Azure Storage container.
Transact-SQL differences
When you execute the CREATE EVENT SESSION command on SQL Server, you use the ON SERVER clause.
But on SQL Database you use the ON DATABASE clause instead.
The ON DATABASE clause also applies to the ALTER EVENT SESSION and DROP EVENT SESSION Transact-
SQL commands.
A best practice is to include the event session option of STARTUP_STATE = ON in your CREATE EVENT
SESSION or ALTER EVENT SESSION statements.
The = ON value supports an automatic restart after a reconfiguration of the logical database due to a
failover.
NAME OF
CATALOG VIEW DESCRIPTION
sys.database_event_session_targets Returns a row for each event target for an event session.
sys.database_event_sessions Returns a row for each event session in the SQL Database
database.
In Microsoft SQL Server, similar catalog views have names that include .server_ instead of .database_. The name
pattern is like sys.server_event_%.
sys.dm_xe_database_session_object_columns Shows the configuration values for objects that are bound to
a session.
sys.dm_xe_database_sessions Returns a row for each event session that is scoped to the
current database.
In Microsoft SQL Server, similar catalog views are named without the _database portion of the name, such as:
sys.dm_xe_sessions, instead of name
sys.dm_xe_database_sessions.
DMVs common to both
For extended events there are additional DMVs that are common to both Azure SQL Database and Microsoft SQL
Server:
sys.dm_xe_map_values
sys.dm_xe_object_columns
sys.dm_xe_objects
sys.dm_xe_packages
SELECT
o.object_type,
p.name AS [package_name],
o.name AS [db_object_name],
o.description AS [db_obj_description]
FROM
sys.dm_xe_objects AS o
INNER JOIN sys.dm_xe_packages AS p ON p.guid = o.package_guid
WHERE
o.object_type in
(
'action', 'event', 'target'
)
ORDER BY
o.object_type,
p.name,
o.name;
Restrictions
There are a couple of security-related differences befitting the cloud environment of SQL Database:
Extended events are founded on the single-tenant isolation model. An event session in one database cannot
access data or events from another database.
You cannot issue a CREATE EVENT SESSION statement in the context of the master database.
Permission model
You must have Control permission on the database to issue a CREATE EVENT SESSION statement. The database
owner (dbo) has Control permission.
Storage container authorizations
The SAS token you generate for your Azure Storage container must specify rwl for the permissions. The rwl value
provides the following permissions:
Read
Write
List
Performance considerations
There are scenarios where intensive use of extended events can accumulate more active memory than is healthy
for the overall system. Therefore the Azure SQL Database system dynamically sets and adjusts limits on the
amount of active memory that can be accumulated by an event session. Many factors go into the dynamic
calculation.
If you receive an error message that says a memory maximum was enforced, some corrective actions you can take
are:
Run fewer concurrent event sessions.
Through your CREATE and ALTER statements for event sessions, reduce the amount of memory you specify
on the MAX_MEMORY clause.
Network latency
The Event File target might experience network latency or failures while persisting data to Azure Storage blobs.
Other events in SQL Database might be delayed while they wait for the network communication to complete. This
delay can slow your workload.
To mitigate this performance risk, avoid setting the EVENT_RETENTION_MODE option to NO_EVENT_LOSS
in your event session definitions.
Related links
Using Azure PowerShell with Azure Storage.
Azure Storage Cmdlets
Using Azure PowerShell with Azure Storage - Provides comprehensive information about PowerShell and the
Azure Storage service.
How to use Blob storage from .NET
CREATE CREDENTIAL (Transact-SQL)
CREATE EVENT SESSION (Transact-SQL)
Jonathan Kehayias' blog posts about extended events in Microsoft SQL Server
The Azure Service Updates webpage, narrowed by parameter to Azure SQL Database:
https://azure.microsoft.com/updates/?service=sql-database
Other code sample topics for extended events are available at the following links. However, you must routinely
check any sample to see whether the sample targets Microsoft SQL Server versus Azure SQL Database. Then you
can decide whether minor changes are needed to run the sample.
Improved query performance with compatibility Level
130 in Azure SQL Database
4/10/2017 • 17 min to read • Edit Online
Azure SQL Database is running transparently hundreds of thousands of databases at many different compatibility
levels, preserving and guaranteeing the backward compatibility to the corresponding version of Microsoft SQL
Server for all its customers!
In this article, we explore the benefits of running your Azure SQL Database at compatibility level 130, and using the
benefits of the new query optimizer and query processor features. We also address the possible side effects on the
query performance for the existing SQL applications.
As a reminder of history, the alignment of SQL versions to default compatibility levels are as follows:
100: in SQL Server 2008 and Azure SQL Database.
110: in SQL Server 2012 and Azure SQL Database.
120: in SQL Server 2014 and Azure SQL Database.
130: in SQL Server 2016 and Azure SQL Database.
IMPORTANT
The default compatibility level is 130 for newly created databases.
Databases created before mid-June 2016 have the compatibility level in place at their creation time. Databases that migrated
from an earlier version of Azure SQL Database have a compatibility level of either 100 or 110. The compatibility level of the
master database for a server created prior to mid-June 2016 has the compatibility level in place when the server was created
and cannot be changed. A different compatibility level between the master database and a user database is not something
that impacts functionality or performance for user databases.
SELECT compatibility_level
FROM sys.databases
WHERE name = '<YOUR DATABASE_NAME>’;
Before this change to level 130 happens for newly created databases, let’s review what this change is all about
through some basic query examples, and see how anyone can benefit from it.
Query processing in relational databases can be very complex and require a deep background in computer science
and mathematics to understand the inherent design choices and behaviors. In this document, the content has been
intentionally simplified to ensure that anyone with some minimum technical background can understand the
impact of the compatibility level change and determine how it can benefit applications.
Let’s have a quick look at what the compatibility level 130 brings at the table. You can find more details at ALTER
DATABASE Compatibility Level (Transact-SQL), but here is a short summary:
The Insert operation of an Insert-select statement can be multi-threaded or can have a parallel plan, while before
this operation was single-threaded.
Memory Optimized table and table variables queries can now have parallel plans, while before this operation
was also single-threaded.
Statistics for Memory Optimized table can now be sampled and are auto-updated. See What's New in Database
Engine: In-Memory OLTP for more details.
Batch mode v/s Row Mode changes with Column Store indexes
Sorts on a table with a Column Store index are now in batch mode.
Windowing aggregates now operate in batch mode such as T-SQL LAG/LEAD statements.
Queries on Column Store tables with Multiple distinct clauses operate in Batch mode.
Queries running under DOP=1 or with a serial plan also execute in Batch Mode.
Last, Cardinality Estimation improvements come with compatibility level 120, but for those of you running at a
lower Compatibility level (that is 100, or 110), the move to compatibility level 130 also brings these
improvements, and these can also benefit the query performance of your applications.
GO 200
GO 10
Now, let’s have a look to some of the Query Processing features coming with compatibility level 130.
Parallel INSERT
Executing the following T-SQL statements executes the INSERT operation under compatibility level 120 and 130,
which respectively executes the INSERT operation in a single threaded model (120), and in a multi-threaded model
(130).
By requesting the actual the query plan, looking at its graphical representation or its XML content, you can
determine which Cardinality Estimation function is at play. Looking at the plans side by side on figure 1, we can
clearly see that the Column Store INSERT execution goes from serial in 120 to parallel in 130. Also, note that the
change of the iterator icon in the 130 plan showing two parallel arrows, illustrating the fact that now the iterator
execution is indeed parallel. If you have large INSERT operations to complete, the parallel execution, linked to the
number of core you have at your disposal for the database, performs better; up to a 100 times faster depending on
your situation!
Figure 1: INSERT operation changes from serial to parallel with compatibility level 130.
SERIAL Batch Mode
Similarly, moving to compatibility level 130 when processing rows of data enables batch mode processing. First,
batch mode operations are only available when you have a column store index in place. Second, a batch typically
represents ~900 rows, and uses a code logic optimized for multicore CPU, higher memory throughput and directly
leverages the compressed data of the Column Store whenever possible. Under these conditions, SQL Server 2016
can process ~900 rows at once, instead of 1 row at the time, and as a consequence, the overall overhead cost of the
operation is now shared by the entire batch, reducing the overall cost by row. This shared number of operations
combined with the column store compression basically reduces the latency involved in a SELECT batch mode
operation. You can find more details about the column store and batch mode at Columnstore Indexes Guide.
-- Serial batch mode execution
By observing the query plans side by side on figure 2, we can see that the processing mode has changed with the
compatibility level, and as a consequence, when executing the queries in both compatibility level altogether, we can
see that most of the processing time is spent in row mode (86%) compared to the batch mode (14%), where 2
batches have been processed. Increase the dataset, increase the benefit.
Figure 2: SELECT operation changes from serial to batch mode with compatibility level 130.
Visible side by side on figure 3, we can see that the sort operation in row mode represents 81% of the cost, while
the batch mode only represents 19% of the cost (respectively 81% and 56% on the sort itself).
Figure 3: SORT operation changes from row to batch mode with compatibility level 130.
Obviously, these samples only contain tens of thousands of rows, which are nothing when looking at the data
available in most SQL Servers these days. Project these against millions of rows instead, and this can translate in
several minutes of execution spared every day pending the nature of your workload.
SELECT [c1]
FROM [dbo].[T_target]
WHERE [c1] > 20000;
GO
Once execution is complete, click the XML link, and look at the properties of the first iterator. Note the property
name called CardinalityEstimationModelVersion currently set on 70. It does not mean that the database
compatibility level is set to the SQL Server 7.0 version (it is set on 110 as visible in the preceding T-SQL
statements), but the value 70 represents the legacy Cardinality Estimation functionality available since SQL Server
7.0, which had no major revisions until SQL Server 2014 (which comes with a compatibility level of 120).
Figure 4: The CardinalityEstimationModelVersion is set to 70 when using a compatibility level of 110 or lower.
Alternatively, you can change the compatibility level to 130, and disable the use of the new Cardinality Estimation
function by using the LEGACY_CARDINALITY_ESTIMATION set to ON with ALTER DATABASE SCOPED
CONFIGURATION. This is the same as using 110 from a Cardinality Estimation function point of view, while using
the latest query processing compatibility level. Doing so, you can benefit from the new query processing features
coming with the latest compatibility level (that is batch mode), but still rely on the old Cardinality Estimation
functionality if necessary.
-- Old CE
ALTER DATABASE
SCOPED CONFIGURATION
SET LEGACY_CARDINALITY_ESTIMATION = ON;
GO
SELECT [c1]
FROM [dbo].[T_target]
WHERE [c1] > 20000;
GO
-- New CE
ALTER DATABASE
SCOPED CONFIGURATION
SET LEGACY_CARDINALITY_ESTIMATION = OFF;
GO
SELECT [c1]
FROM [dbo].[T_target]
WHERE [c1] > 20000;
GO
Figure 5: The CardinalityEstimationModelVersion is set to 130 when using a compatibility level of 130.
ALTER DATABASE
SCOPED CONFIGURATION
SET LEGACY_CARDINALITY_ESTIMATION = ON;
GO
SELECT T.[c2]
FROM
[dbo].[T_source] S
INNER JOIN [dbo].[T_target] T ON T.c1=S.c1
WHERE
S.[Color] = ‘Red’ AND
S.[c2] > 2000 AND
T.[c2] > 2000
OPTION (RECOMPILE);
GO
Executing this query effectively returns 200,704 rows, while the row estimate with the old Cardinality Estimation
functionality claims 194,284 rows. Obviously, as said before, these row count results also depend how often you
ran the previous samples, which populates the sample tables over and over again at each run. Obviously, the
predicates in your query also have an influence on the actual estimation aside from the table shape, data content,
and how this data correlate with each other.
Figure 6: The row count estimate is 194,284 or 6,000 rows off from the 200,704 rows expected.
In the same way, let’s now execute the same query with the new Cardinality Estimation functionality.
-- New CE row estimate with INNER JOIN and WHERE clause
ALTER DATABASE
SCOPED CONFIGURATION
SET LEGACY_CARDINALITY_ESTIMATION = OFF;
GO
SELECT T.[c2]
FROM
[dbo].[T_source] S
INNER JOIN [dbo].[T_target] T ON T.c1=S.c1
WHERE
S.[Color] = ‘Red’ AND
S.[c2] > 2000 AND
T.[c2] > 2000
OPTION (RECOMPILE);
GO
We now see that the row estimate is 202,877, or much closer and higher than the old Cardinality Estimation.
Figure 7: The row count estimate is now 202,877, instead of 194,284.
In reality, the result set is 200,704 rows (but all of it depends how often you did run the queries of the previous
samples, but more importantly, because the T-SQL uses the RAND() statement, the actual values returned can vary
from one run to the next). Therefore, in this particular example, the new Cardinality Estimation does a better job at
estimating the number of rows because 202,877 is much closer to 200,704, than 194,284! Last, if you change the
WHERE clause predicates to equality (rather than “>” for instance), this could make the estimates between the old
and new Cardinality function even more different, depending on how many matches you can get.
Obviously, in this case, being ~6000 rows off from actual count does not represent a lot of data in some situations.
Now, transpose this to millions of rows across several tables and more complex queries, and at times the estimate
can be off by millions of rows, and therefore, the risk of picking-up the wrong execution plan, or requesting
insufficient memory grants leading to TempDB spills, and so more I/O, are much higher.
If you have the opportunity, practice this comparison with your most typical queries and datasets, and see for
yourself by how the old and new estimates are affected, while some could become more off from the reality, or
some others closer to the actual row counts returned in the result sets. All of it depends on the shape of your
queries, the Azure SQL database characteristics, the nature and the size of your datasets, and the statistics available
about them. If you just created your Azure SQL Database instance, the query optimizer has to build its knowledge
from scratch instead of reusing statistics made of the previous query runs. So, the estimates are very contextual and
almost specific to every server and application situation. It is an important aspect to keep in mind!
Conclusion
Using Azure SQL Database to benefit from all SQL Server 2016 enhancements can clearly improve your query
executions. Of course, like any new feature, a proper evaluation must be done to determine the exact conditions
under which your database workload operates the best. Experience shows that most workload are expected to at
least run transparently under compatibility level 130, while using new query processing functions, and new
Cardinality Estimation. That said, realistically, there are always some exceptions and doing proper due diligence is
an important assessment to determine how much you can benefit from these enhancements. And again, the Query
Store can be of a great help in doing this work!
References
What’s New in Database Engine
Blog: Query Store: A flight data recorder for your database, by Borko Novakovic, June 8 2016
ALTER DATABASE Compatibility Level (Transact-SQL)
ALTER DATABASE SCOPED CONFIGURATION
Compatibility Level 130 for Azure SQL Database
Optimizing Your Query Plans with the SQL Server 2014 Cardinality Estimator
Columnstore Indexes Guide
Blog: Improved Query Performance with Compatibility Level 130 in Azure SQL Database, by Alain Lissoir, May 6
2016
Create and manage an elastic pool with the Azure
portal
4/19/2017 • 11 min to read • Edit Online
This topic shows you how to create and manage scalable elastic pools with the Azure portal. You can also create
and manage an Azure elastic pool with PowerShell, the REST API, or C#. You can also create and move databases
into and out of elastic pools using Transact-SQL.
NOTE
Elastic pools are generally available (GA) in all Azure regions except West India where it is currently in preview. GA of
elastic pools in this region will occur as soon as possible.
NOTE
You can also create an elastic pool by searching SQL elastic pool in the Marketplace or clicking +Add in the SQL
elastic pools browse blade. You are able to specify a new or existing server through this pool provisioning workflow.
1. In the Azure portal, click More services > SQL servers, and then click the server that contains the databases
you want to add to an elastic pool.
2. Click New pool.
-OR-
You may see a message saying there are recommended elastic pools for the server. Click the message to
see the recommended pools based on historical database usage telemetry, and then click the tier to see
more details and customize the pool. See Understand pool recommendations later in this topic for how
the recommendation is made.
3. The elastic pool blade appears, which is where you specify the settings for your pool. If you clicked New
pool in the previous step, the pricing tier is Standard by default and no databases is selected. You can
create an empty pool, or specify a set of existing databases from that server to move into the pool. If you
are creating a recommended pool, the recommended pricing tier, performance settings, and list of
databases are prepopulated, but you can still change them.
IMPORTANT
After you choose the pricing tier and commit your changes by clicking OK in the last step, you won't be able to change
the pricing tier of the pool. To change the pricing tier for an existing elastic pool, create an elastic pool in the desired
pricing tier and migrate the databases to this new pool.
IMPORTANT
The service takes the last 30 days of telemetry into account when recommending pools. For a database to be considered
as a candidate for an elastic pool, it must exist for at least 7 days. Databases that are already in an elastic pool are not
considered as candidates for elastic pool recommendations.
The service evaluates resource needs and cost effectiveness of moving the single databases in each service tier
into pools of the same tier. For example, all Standard databases on a server are assessed for their fit into a
Standard Elastic Pool. This means the service does not make cross-tier recommendations such as moving a
Standard database into a Premium pool.
After adding databases to the pool, recommendations are dynamically generated based on the historical usage
of the databases you have selected. These recommendations are shown in the eDTU and GB usage chart and in a
recommendation banner at the top of the Configure pool blade. These recommendations are intended to assist
you in creating an elastic pool optimized for your specific databases.
2. In the Edit Chart blade, select a time range (past hour, today, or past week), or click custom to select any
date range in the last two weeks. Select the chart type (bar or line), then select the resources to monitor.
NOTE
Only metrics with the same unit of measure can be displayed in the chart at the same time. For example, if you
select "eDTU percentage" then you can only select other metrics with percentage as the unit of measure.
3. Then click OK.
2. In the Edit chart blade, select a time range (past hour or past 24 hours), or click custom to select a
different day in the past 2 weeks to display.
3. Click the Compare databases by dropdown to select a different metric to use when comparing
databases.
IMPORTANT
Resource utilization monitoring for elastic pools has a lag of at least 20 minutes. Setting alerts of less than 30 minutes for
elastic pools is not currently supported. Any alerts set for Elastic Pools with a period (parameter called “-WindowSize” in
PowerShell API) of less than 30 minutes may not be triggered. Make sure that any alerts you define for Elastic Pools use a
period (WindowSize) of 30 minutes or more.
3. In the Add databases blade, select the database or databases to add to the pool. Then click Select.
The Configure pool blade now lists the database you selected to be added, with its status set to
Pending.
The Configure pool blade now lists the database you selected to be removed with its status set to
Pending.
3. In the Configure pool blade, click Save.
Next steps
To understand what an elastic pool is, see SQL Database elastic pool.
For guidance on using elastic pools, see Price and performance considerations for elastic pools.
To use elastic jobs to run Transact-SQL scripts against any number of databases in the pool, see Elastic jobs
overview.
To query across any number of databases in the pool, see Elastic query overview.
For transactions any number of databases in the pool, see Elastic transactions.
Create and manage an elastic pool with PowerShell
4/14/2017 • 11 min to read • Edit Online
This topic shows you how to create and manage scalable elastic pools with PowerShell. You can also create and
manage an Azure elastic pool the Azure portal, the REST API, or C#. You can also create and move databases into
and out of elastic pools using Transact-SQL.
NOTE
Many new features of SQL Database are only supported when you are using the Azure Resource Manager deployment
model, so examples use the Azure SQL Database PowerShell cmdlets for Resource Manager. The service management
(classic) deployment model Azure SQL Database Service Management cmdlets are supported for backward compatibility,
but we recommend you use the Resource Manager cmdlets.
Run the Add-AzureRmAccount cmdlet, and you will be presented with a sign-in screen to enter your credentials.
Use the same credentials that you use to sign in to the Azure portal.
Add-AzureRmAccount
If you have multiple subscriptions, use the Set-AzureRmContext cmdlet to select which subscription your
PowerShell session should use. To see what subscription the current PowerShell session is using, run Get-
AzureRmContext. To see all your subscriptions, run Get-AzureRmSubscription.
Login-AzureRmAccount
Set-AzureRmContext -SubscriptionId $subscriptionId
eDTU_limit Current max elastic pool DTU setting for this elastic pool
during this interval.
storage_limit Current max elastic pool storage limit setting for this elastic
pool in megabytes during this interval.
IMPORTANT
Resource utilization monitoring for elastic pools has a lag of at least 20 minutes. Setting alerts of less than 30 minutes for
elastic pools is not currently supported. Any alerts set for elastic pools with a period (parameter called “-WindowSize” in
PowerShell API) of less than 30 minutes may not be triggered. Make sure that any alerts you define for elastic pools use a
period (WindowSize) of 30 minutes or more.
This example adds an alert for getting notified when an elastic pool’s eDTU consumption goes above certain
threshold.
#$Target Resource ID
$ResourceID = '/subscriptions/' + $subscriptionId + '/resourceGroups/' +$resourceGroupName + '/providers/Microsoft.Sql/servers/' +
$serverName + '/elasticpools/' + $poolName
IMPORTANT
Resource utilization monitoring for elastic pools has a lag of at least 20 minutes. Setting alerts of less than 30 minutes for
elastic pools is not currently supported. Any alerts set for elastic pools with a period (parameter called “-WindowSize” in
PowerShell API) of less than 30 minutes may not be triggered. Make sure that any alerts you define for elastic pools use a
period (WindowSize) of 30 minutes or more.
This example adds an alert to each of the databases in an elastic pool for getting notified when that database’s
DTU consumption goes above certain threshold.
# Get resource usage metrics for a database in an elastic pool for the specified time interval.
foreach ($db in $dbList)
{
$dbResourceId = '/subscriptions/' + $subscriptionId + '/resourceGroups/' + $resourceGroupName + '/providers/Microsoft.Sql/servers/' +
$serverName + '/databases/' + $db.DatabaseName
# Get resource usage metrics for an elastic pool for the specified time interval.
$startTime = '4/27/2016 00:00:00' # start time in UTC
$endTime = '4/27/2016 01:00:00' # end time in UTC
# Construct the pool resource ID and retrive pool metrics at 5-minute granularity.
$poolResourceId = '/subscriptions/' + $subscriptionId + '/resourceGroups/' + $resourceGroupName + '/providers/Microsoft.Sql/servers/' +
$serverName + '/elasticPools/' + $poolName
$poolMetrics = (Get-AzureRmMetric -ResourceId $poolResourceId -TimeGrain ([TimeSpan]::FromMinutes(5)) -StartTime $startTime -EndTime
$endTime)
# Get resource usage metrics for a database in an elastic pool for the specified time interval.
$dbMetrics = @()
foreach ($db in $dbList)
{
$dbResourceId = '/subscriptions/' + $subscriptionId + '/resourceGroups/' + $resourceGroupName + '/providers/Microsoft.Sql/servers/' +
$serverName + '/databases/' + $db.DatabaseName
$dbMetrics = $dbMetrics + (Get-AzureRmMetric -ResourceId $dbResourceId -TimeGrain ([TimeSpan]::FromMinutes(5)) -StartTime $startTime
-EndTime $endTime)
}
#Optionally you can format the metrics and output as .csv file using the following script block.
$command = {
param($metricList, $outputFile)
Next steps
Create elastic jobs Elastic jobs let you run T-SQL scripts against any number of databases in the pool.
See Scaling out with Azure SQL Database: use elastic tools to scale out, move data, query, or create
transactions.
Monitor and manage an elastic pool with Transact-
SQL
3/10/2017 • 2 min to read • Edit Online
This topic shows you how to manage scalable elastic pools with Transact-SQL. You can also create and manage an
Azure elastic pool the Azure portal, PowerShell, the REST API, or C#. You can also create and move databases into
and out of elastic pools using Transact-SQL.
Use the Create Database (Azure SQL Database) and Alter Database(Azure SQL Database) commands to create and
move databases into and out of elastic pools. The elastic pool must exist before you can use these commands.
These commands affect only databases. Creation of new pools and the setting of pool properties (such as min and
max eDTUs) cannot be changed with T-SQL commands.
All databases in an elastic pool inherit the service tier of the elastic pool (Basic, Standard, Premium).
Next steps
After creating an elastic pool, you can manage elastic databases in the pool by creating elastic jobs. Elastic jobs
facilitate running T-SQL scripts against any number of databases in the pool. For more information, see Elastic
database jobs overview.
See Scaling out with Azure SQL Database: use elastic database tools to scale out, move data, query, or create
transactions.
Create and manage an elastic pool with C#
4/19/2017 • 8 min to read • Edit Online
This topic shows you how to create and manage scalable elastic pools with C#. You can also create and manage
an Azure elastic pool with the Azure portal, PowerShell, or the REST API. You can also create and move databases
into and out of elastic pools using Transact-SQL.
NOTE
Many new features of SQL Database are only supported when you are using the Azure Resource Manager deployment
model, so you should always use the latest Azure SQL Database Management Library for .NET (docs | NuGet
Package). The older classic deployment model-based libraries are supported for backward compatibility only, so we
recommend you use the newer Resource Manager based libraries.
This topic describes how to use C# to create and manage an Azure SQL elastic pool with the Azure SQL Database
Library for .NET. To create a single SQL database, see Use C# to create a SQL database with the SQL Database
Library for .NET.
The Azure SQL Database Library for .NET provides an Azure Resource Manager-based API that wraps the
Resource Manager-based SQL Database REST API.
NOTE
Many new features of SQL Database are only supported when you are using the Azure Resource Manager deployment
model, so you should always use the latest Azure SQL Database Management Library for .NET (docs | NuGet
Package). The older classic deployment model libraries are supported for backward compatibility only, so we recommend
you use the newer Resource Manager based libraries.
Prerequisites
To complete the steps in this article, you need the following:
An Azure subscription. If you need an Azure subscription simply click FREE ACCOUNT at the top of this page,
and then come back to finish this article.
Visual Studio. For a free copy of Visual Studio, see the Visual Studio Downloads page.
NOTE
The examples in this article use a synchronous form of each API request and block until completion of the REST call on the
underlying service. There are async methods available.
Replace the contents of Program.cs with the following, and update the {variables} with your app values (do not
include the {} ).
using Microsoft.Azure;
using Microsoft.Azure.Management.ResourceManager;
using Microsoft.Azure.Management.ResourceManager.Models;
using Microsoft.Azure.Management.Sql;
using Microsoft.Azure.Management.Sql.Models;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
namespace SqlElasticPoolConsoleApp
{
class Program
{
// Create management clients for the Azure resources your app needs to work with.
// This app works with Resource Groups, and Azure SQL Database.
static ResourceManagementClient _resourceMgmtClient;
static SqlManagementClient _sqlMgmtClient;
// Authentication token
static AuthenticationResult _token;
Console.WriteLine("Resource group...");
ResourceGroup rg = CreateOrUpdateResourceGroup(_resourceMgmtClient, _subscriptionId, _resourceGroupName,
_resourceGrouplocation);
Console.WriteLine("Resource group: " + rg.Id);
Console.WriteLine("Server...");
ServerGetResponse sgr = CreateOrUpdateServer(_sqlMgmtClient, _resourceGroupName, _serverlocation, _serverName, _serverAdmin,
_serverAdminPassword);
Console.WriteLine("Server: " + sgr.Server.Id);
Console.WriteLine("Server firewall...");
FirewallRuleGetResponse fwr = CreateOrUpdateFirewallRule(_sqlMgmtClient, _resourceGroupName, _serverName, _firewallRuleName,
_startIpAddress, _endIpAddress);
Console.WriteLine("Server firewall: " + fwr.FirewallRule.Id);
Console.WriteLine("Elastic pool...");
ElasticPoolCreateOrUpdateResponse epr = CreateOrUpdateElasticDatabasePool(_sqlMgmtClient, _resourceGroupName, _serverName,
_poolName, _poolEdition, _poolDtus, _databaseMinDtus, _databaseMaxDtus);
Console.WriteLine("Elastic pool: " + epr.ElasticPool.Id);
Console.WriteLine("Database...");
DatabaseCreateOrUpdateResponse dbr = CreateOrUpdateDatabase(_sqlMgmtClient, _resourceGroupName, _serverName,
_databaseName, _poolName);
Console.WriteLine("Database: " + dbr.Database.Id);
// Create elastic pool: configure create or update parameters and properties explicitly
ElasticPoolCreateOrUpdateParameters newPoolParameters = new ElasticPoolCreateOrUpdateParameters()
{
Location = currentServer.Location,
Properties = new ElasticPoolCreateOrUpdateProperties()
{
Edition = poolEdition,
Dtu = poolDtus,
DatabaseDtuMin = databaseMinDtus,
DatabaseDtuMax = databaseMaxDtus
}
};
# Sign in to Azure.
Add-AzureRmAccount
# If you have multiple subscriptions, uncomment and set to the subscription you want to work with.
#$subscriptionId = "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
#Set-AzureRmContext -SubscriptionId $subscriptionId
$appName = "{app-name}"
$uri = "http://{app-name}"
$secret = "{app-password}"
# If you still get a PrincipalNotFound error, then rerun the following until successful.
$roleassignment = New-AzureRmRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName
$azureAdApplication.ApplicationId.Guid
// Configure create or update parameters with existing property values, override those to be changed.
DatabaseCreateOrUpdateParameters updatePooledDbParameters = new DatabaseCreateOrUpdateParameters()
{
Location = currentDatabase.Location,
Properties = new DatabaseCreateOrUpdateProperties()
{
Edition = "Standard",
RequestedServiceObjectiveName = "ElasticPool",
ElasticPoolName = "ElasticPool1",
MaxSizeBytes = currentDatabase.Properties.MaxSizeBytes,
Collation = currentDatabase.Properties.Collation,
}
};
// Configure create or update parameters with existing property values, override those to be changed.
ElasticPoolCreateOrUpdateParameters updatePoolParameters = new ElasticPoolCreateOrUpdateParameters()
{
Location = currentPool.Location,
Properties = new ElasticPoolCreateOrUpdateProperties()
{
Edition = currentPool.Properties.Edition,
DatabaseDtuMax = 50, /* Setting DatabaseDtuMax to 50 limits the eDTUs that any one database can consume */
DatabaseDtuMin = 10, /* Setting DatabaseDtuMin above 0 limits the number of databases that can be stored in the pool */
Dtu = (int)currentPool.Properties.Dtu,
StorageMB = currentPool.Properties.StorageMB, /* For a Standard pool there is 1 GB of storage per eDTU. */
}
};
Additional Resources
For SQL error codes for SQL Database client applications, database connection error and other issues, see
Error messages.
Azure Resource Management APIs
For elastic pool guidance, see When should an elastic pool be used?
SQL Server authentication, access, and database-
level firewall rules
4/14/2017 • 12 min to read • Edit Online
In this tutorial, you learn how to use SQL Server Management Studio to work with SQL Server authentication,
logins, users, and database roles that grant access and permissions to Azure SQL Database servers and
databases. After you complete this tutorial, you will know how to:
Create logins and users based on SQL Server authentication
Add users to roles and grant permissions to roles
Use T-SQL to create a database-level and a server-level firewall rule
Connect as a user to a specific database using SSMS
View user permissions in the master database and in user databases
Time estimate: This tutorial takes approximately 45 minutes to complete (assuming you have already met the
prerequisites).
NOTE
This tutorial helps you to learn the content of these topics: SQL Database access and control, Logins, users, and database
roles, Principals, Database roles, and SQL Database firewall rules. For a tutorial about Azure Active Directory authentication,
see Getting started with Azure AD Authentication.
Prerequisites
An Azure account. You need an Azure account. You can open a free Azure account or Activate Visual
Studio subscriber benefits.
Azure create permissions. You must be able to connect to the Azure portal using an account that is a
member of either the subscription owner or contributor role. For more information on role-based access
control (RBAC), see Getting started with access management in the Azure portal.
SQL Server Management Studio. You can download and install the latest version of SQL Server
Management Studio (SSMS) at Download SQL Server Management Studio. Always use the latest version
of SSMS when connecting to Azure SQL Database as new capabilities are continually being released.
Base server and databases To install and configure a server and the two databases used in this tutorial,
click the Deploy to Azure button. Clicking the button opens the Deploy from a template blade; create a
new resource group, and provide the Admin Login Password for the new server that will be created:
2. Make note of the name for server admin on your logical server.
3. If you do not remember the password, click Reset password to set a new password.
4. If you need to get the connection information for this server, click Properties.
2. Click Connect.
3. In Object Explorer, expand Security, and then expand Logins to view the existing logins for your server -
the only login on a new server is the login for server admin account.
4. In Object Explorer, expand Databases, expand System databases, expand master, expand Security, and
then expand Users to view the user account that was created for the server admin login in this database.
NOTE
For information about the other user accounts that appear in the Users node, see Principals.
5. In Object Explorer, right-click master and then click New Query to open a query window connected to the
master database.
6. In the query window, execute the following query to return information about the user executing the
query.
SELECT USER;
7. In the query window, execute the following query to return information about the permissions of the
sqladmin user in the master database.
SELECT prm.permission_name
, prm.class_desc
, prm.state_desc
, p2.name as 'Database role'
, p3.name as 'Additional database role'
FROM sys.database_principals p
JOIN sys.database_permissions prm
ON p.principal_id = prm.grantee_principal_id
LEFT JOIN sys.database_principals p2
ON prm.major_id = p2.principal_id
LEFT JOIN sys.database_role_members r
ON p.principal_id = r.member_principal_id
LEFT JOIN sys.database_principals p3
ON r.role_principal_id = p3.principal_id
WHERE p.name = 'sqladmin';
NOTE
The server admin has permissions to connect to the master database, create logins and users, select information
from the sys.sql_logins table, and add users to the dbmanager and dbcreator database roles. These permissions are
in addition to permissions granted to the public role from which all users inherit permissions (such as permissions
to select information from certain tables). See Permissions for more information.
8. In Object Explorer, expand blankdb, expand Security, and then expand Users to view the user account
that was created for the server admin login in this database (and in each user database).
SELECT USER;
11. In the query window, execute the following query to return information about the permissions of the dbo
user.
SELECT prm.permission_name
, prm.class_desc
, prm.state_desc
, p2.name as 'Database role'
, p3.name as 'Additional database role'
FROM sys.database_principals AS p
JOIN sys.database_permissions AS prm
ON p.principal_id = prm.grantee_principal_id
LEFT JOIN sys.database_principals AS p2
ON prm.major_id = p2.principal_id
LEFT JOIN sys.database_role_members r
ON p.principal_id = r.member_principal_id
LEFT JOIN sys.database_principals AS p3
ON r.role_principal_id = p3.principal_id
WHERE p.name = 'dbo';
NOTE
The dbo user is a member of the public role and also a member of the db_owner fixed database role. See Database-
Level Roles for more information.
NOTE
Database-level users are also called contained users and increase the portability of your database. For information about
the benefits of portability, see Configure and manage Azure SQL Database security for geo-restore or failover to a
secondary server.
3. In the query window, execute the following query to return information about the permissions of user1.
SELECT prm.permission_name
, prm.class_desc
, prm.state_desc
, p2.name as 'Database role'
, p3.name as 'Additional database role'
FROM sys.database_principals AS p
JOIN sys.database_permissions AS prm
ON p.principal_id = prm.grantee_principal_id
LEFT JOIN sys.database_principals AS p2
ON prm.major_id = p2.principal_id
LEFT JOIN sys.database_role_members r
ON p.principal_id = r.member_principal_id
LEFT JOIN sys.database_principals AS p3
ON r.role_principal_id = p3.principal_id
WHERE p.name = 'user1';
NOTE
A new user in a database only has the permissions inherited from the public role.
4. Execute the following queries using the EXECUTE AS USER statement to attempt to query the
SalesLT.ProductCategory table in the sqldbtutorialdb database as user1 with only the permissions
inherited from the public role.
NOTE
By default, the public role does not grant SELECT permissions on user objects.
5. Execute the following statement to grant SELECT permissions on the SalesLT.ProductCategory table to
user1.
6. Execute the following queries to successfully query the SalesLT.ProductCategory table in the
sqldbtutorialdb database as user1.
NOTE
Database-level firewall rules increase the portability of your database. For information about the benefits of portability, see
Configure and manage Azure SQL Database security for geo-restore or failover to a secondary server.
IMPORTANT
To test a database-level firewall rule, connect from another computer (or delete the server-level firewall rule in the Azure
portal.)
1. Open SQL Server Management Studio on a computer for which you do not have a server-level firewall
rule.
2. In the Connect to Server window, enter the server name and authentication information to connect using
SQL Server authentication with the user1 account.
3. Click Options in the Connect to server dialog box to specify the database to which you want to connect
and then type sqldbtutorialdb in the Connect to Database drop-down box on the Connection
Properties tab.
4. Click Connect.
A dialog box appears informing you that the computer from which you are attempting to connect to SQL
Database does not have a firewall rule enabling access to the database.
5. Copy the client IP address from this dialog box for use in step 8.
6. Click OK to close the error dialog box, but do not close the Connect to Server dialog box.
7. Switch back to a computer for which you have already created a server-level firewall rule.
8. Connect to the sqldbtutorialdb database in SSMS as server admin and execute the following statement to
create a database-level firewall using the IP address (or address range) from step 5.
NOTE
After you create the database-level firewall rule, it may take up to 5 minutes to become active.
10. After you connect successfully, expand Databases in Object Explorer. Notice that user1 can only view the
sqldbtutorialdb database.
11. Expand sqldbtutorialdb, and then expand Tables. Notice that user1 only has permission to view a single
table, the SalesLT.ProductCategory table.
3. In the same query window, execute the following statement to add the blankdbadmin user to the
db_owner database role. This user can now perform all actions necessary to manage the blankdb database.
4. In the same query window, execute the following statement to create a database-level firewall by executing
sp_set_database_firewall_rule using the IP address from step 4 in the previous procedure (or a range of IP
addresses for users of this database):
5. Switch computers (to one for which you have created a database-level firewall rule) and connect to the
blankdb database using the blankdbadmin user account.
6. Open a query window to the blankdb database and execute the following statement to create a user called
blankdbuser1 in the blankdb database.
7. As necessary for your learning environment, create an additional database-level firewall rule for this user.
However, if you created the database-level firewall rule using an IP address range, this may not be
necessary.
IMPORTANT
The first server-level firewall rule must always be created in Azure (in the Azure portal, using PowerShell, or the REST API).
IMPORTANT
Creating logins in the master database and creating a user account from a login is required for the server admin to
delegate create database permissions to another user. However, creating logins and then creating users from logins
decreases the portability of your environment.
1. Switch to your computer with a connection to SQL Database using the server admin account.
2. Open a query window connected to the master database and execute the following statement to create a
login called dbcreator in the master database.
CREATE LOGIN dbcreator
WITH PASSWORD = 'p@ssw0rd';
4. In the same query window, execute the following query to add the dbcreator user to the dbmanager
database role. This user can now create and manage databases created by the user.
5. In the same query window, execute the following query to create a server-level firewall by executing
sp_set_firewall_rule using an IP address appropriate for your environment:
6. Switch computers (to one for which you have created a server-level firewall rule) and connect to the
master database using the dbcreator user account.
7. Open a query window to the master database and execute the following query to create a database called
foo.
a. Optionally, delete this database to save money using the following statement:
Complete script
To create the logins and users, add them to roles, grant them permissions, create database-level firewall rules,
and create server-level firewall rules, execute the following statements in the appropriate databases on your
server.
master database
Execute these statements in the master database using the server admin account, adding the appropriate IP
addresses or range.
sqldbtutorialdb database
Execute these statements in the sqldbtutorialdb database using the server admin account, adding the appropriate
IP addresses or range.
CREATE USER user1 WITH PASSWORD = 'p@ssw0rd';
GRANT SELECT ON OBJECT::[SalesLT].[ProductCategory] to user1;
EXEC sp_set_database_firewall_rule @name = N'sqldbtutorialdbFirewallRule',
@start_ip_address = 'x.x.x.x', @end_ip_address = 'x.x.x.x';
blankdb database
Execute these statements in the blankdb database using the server admin account, adding the appropriate IP
addresses or range.
Next steps
For an overview of access and control in SQL Database, see SQL Database access and control.
For an overview of logins, users, and database roles in SQL Database, see Logins, users, and database roles.
For more information about database principals, see Principals.
For more information about database roles, see Database roles.
For more information about firewall rules in SQL Database, see SQL Database firewall rules.
For a tutorial using Azure Active Directory authentication, see Azure AD authentication and authorization.
Azure AD authentication, access, and database-level
firewall rules
4/14/2017 • 10 min to read • Edit Online
In this how-to guide, you learn how to use SQL Server Management Studio to work with Azure Active Directory
authentication, logins, users, and database roles that grant access and permissions to Azure SQL Database
servers and databases. You learn to:
View user permissions in the master database and in user databases
Create logins and users based on Azure Active Directory authentication
Grant server-wide and database-specific permissions to users
Log in to a user database as a non-admin user
Create database-level firewall rules for database users
Create server-level firewall rules for server admins
Time estimate: This how-to guide takes approximately 45 minutes to complete (assuming you have already met
the prerequisites).
Prerequisites
An Azure account. You need an Azure account. You can open a free Azure account or Activate Visual
Studio subscriber benefits.
Azure create permissions. You must be able to connect to the Azure portal using an account that is a
member of either the subscription owner or contributor role. For more information on role-based access
control (RBAC), see Getting started with access management in the Azure portal.
SQL Server Management Studio. You can download and install the latest version of SQL Server
Management Studio (SSMS) at Download SQL Server Management Studio. Always use the latest version
of SSMS when connecting to Azure SQL Database as new capabilities are continually being released.
Base server and databases To install and configure a server and the two databases used in this how-to
guide, click the Deploy to Azure button. Clicking the button opens the Deploy from a template blade;
create a new resource group, and provide the Admin Login Password for the new server that will be
created:
NOTE
The completion of the related how-to guide for SQL Server authentication, SQL authentication, logins and user
accounts, database roles, permissions, server-level firewall rules, and database-level firewall rules, is optional -
however, there are concepts covered in that how-to guide that are not repeated here. The procedures in this how-
to guide related to server and database level firewalls are not required if you completed this related how-to guide
on the same computers (with the same IP addresses) and are marked as optional for that reason. Also, the
screenshots in this how-to guide assume that you have completed of this related how-to guide.
You have created and populated an Azure Active Directory. For more information, see Integrating your on-
premises identities with Azure Active Directory, Add your own domain name to Azure AD, Microsoft Azure
now supports federation with Windows Server Active Directory, Administering your Azure AD directory,
Manage Azure AD using Windows PowerShell, and Hybrid Identity Required Ports and Protocols.
NOTE
This how-to guide helps you to learn the content of these learn topics: SQL Database access and control, Logins, users, and
database roles, Principals, Database roles, SQL Database firewall rules, and Azure Active Directory authentication.
Provision an Azure Active Directory admin for your SQL logical server
In this section of the how-to guide, you view information about the security configuration for your logical server
in the Azure portal.
1. Open the SQL Server blade for your logical server and view the information in the Overview page. Notice
that an Azure Active Directory admin has not been configured.
2. Click Not configured in the Essentials pane to open the Active Directory admin blade.
3. Click Set admin to open the Add admin blade and then select an Active Directory user or group account
as the Active Directory admin for your server.
4. Click Select and then click Save.
NOTE
To review connection information for this server, go to Connect with SSMS. For this how-to guide series, the fully qualified
server name is 'sqldbtutorialserver.database.windows.net'.
3. In the Connect to Server dialog box, select one of the Active Directory authentication methods and then
provide the appropriate authentication information. For information on choosing a method, see Azure
Active Directory authentication and SSMS support for Azure AD MFA.
4. Enter the necessary information to connect to your SQL server using SQL Server Authentication and the
Server admin account.
5. Click Connect.
2. In Object Explorer, right-click master and then click New Query to open a query window connected to the
master database.
3. In the query window, execute the following query to return information about the user executing the
query. Notice that user@microsoft.com is returned for the user account executing this query (we see a
different result when we query a user database later in this procedure).
SELECT USER;
4. In the query window, execute the following query to return information about the permissions of the
Active Directory admin user. Notice that the Active Directory admin user has permissions to connect to the
master database, create logins and users, select information from the sys.sql_logins table, and add users to
the dbmanager and dbcreator database roles. These permissions are in addition to permissions granted to
the public role from which all users inherit permissions (such as permissions to select information from
certain tables). See Permissions for more information.
SELECT prm.permission_name
, prm.class_desc
, prm.state_desc
, p2.name as 'Database role'
, p3.name as 'Additional database role'
FROM sys.database_principals p
JOIN sys.database_permissions prm
ON p.principal_id = prm.grantee_principal_id
LEFT JOIN sys.database_principals p2
ON prm.major_id = p2.principal_id
LEFT JOIN sys.database_role_members r
ON p.principal_id = r.member_principal_id
LEFT JOIN sys.database_principals p3
ON r.role_principal_id = p3.principal_id
WHERE p.name = 'user@microsoft.com';
5. In Object Explorer, expand blankdb, expand Security, and then expand Users. Notice that there is no user
account called user@microsoft.com in this database.
6. In Object Explorer, right-click blankdb and then click New Query.
7. In the query window, execute the following query to return information about the user executing the
query. Notice that dbo is returned for the user account executing this query (by default, the Server admin
login is mapped to the dbo user account in each user database).
SELECT USER;
8. In the query window, execute the following query to return information about the permissions of the dbo
user. Notice that dbo is a member of the public role and also a member of the db_owner fixed database
role. See Database-Level Roles for more information.
SELECT prm.permission_name
, prm.class_desc
, prm.state_desc
, p2.name as 'Database role'
, p3.name as 'Additional database role'
FROM sys.database_principals AS p
JOIN sys.database_permissions AS prm
ON p.principal_id = prm.grantee_principal_id
LEFT JOIN sys.database_principals AS p2
ON prm.major_id = p2.principal_id
LEFT JOIN sys.database_role_members r
ON p.principal_id = r.member_principal_id
LEFT JOIN sys.database_principals AS p3
ON r.role_principal_id = p3.principal_id
WHERE p.name = 'dbo';
9. Optionally, repeat the previous three steps for the AdventureWorksLT user database.
NOTE
Database-level users (contained users) increase the portability of your database, a capability that we explore in later how-to
guides.
1. In Object Explorer, right-click AdventureWorksLT and then click New Query to open a query window
connected to the AdventureWorksLT database.
2. Execute the following statement to create a user account in the AdventureWorksLT database for a user in
the Microsoft domain called aaduser1.
SELECT prm.permission_name
, prm.class_desc
, prm.state_desc
, p2.name as 'Database role'
, p3.name as 'Additional database role'
FROM sys.database_principals AS p
JOIN sys.database_permissions AS prm
ON p.principal_id = prm.grantee_principal_id
LEFT JOIN sys.database_principals AS p2
ON prm.major_id = p2.principal_id
LEFT JOIN sys.database_role_members r
ON p.principal_id = r.member_principal_id
LEFT JOIN sys.database_principals AS p3
ON r.role_principal_id = p3.principal_id
WHERE p.name = 'aaduser1@microsoft.com';
4. Execute the following queries to attempt to query a table in the AdventureWorksLT database as user1.
6. Execute the following queries to attempt to query a table in the AdventureWorksLT database as user1.
In this section of the how-to guide, you attempt to log in using the new user account from a computer with a
different IP address, create a database-level firewall rule as the Server admin, and then successfully log in using
this new database-level firewall rule.
NOTE
Database-level firewall rules increase the portability of your database, a capability that we explore in later how-to guides.
1. On another computer for which you have not already created a server-level firewall rule, open SQL Server
Management Studio.
IMPORTANT
Always use the latest version of SSMS at Download SQL Server Management Studio.
2. In the Connect to Server window, enter the server name and authentication information to connect using
SQL Server authentication with the aaduser1@microsoft.com account.
3. Click Options in the Connect to server dialog box to specify the database to which you want to connect
and then type AdventureWorksLT in the Connect to Database drop-down box on the Connection
Properties tab.
4. Click Connect. A dialog box appears informing you that the computer from which you are attempting to
connect to SQL Database does not have a firewall rule enabling access to the database. The dialog box that
you receive has two variations depending upon steps you have previously taken with firewalls, but you
usually get the first dialog box shown.
NOTE
The newest versions of SSMS include the functionality to allow subscription owners and contributors to sign in to
Microsoft Azure and create a server-level firewall rule.
5. Copy the client IP address from this dialog box for use in step 7.
6. Click Cancel but do not close the Connect to Server dialog box.
7. Switch back to a computer for which you have already created a server-level firewall rule and connect to your
server using the Server admin account.
8. In a new query window connected to the AdventureWorksLT database as Server admin, execute the
following statement to create a database-level firewall by executing sp_set_database_firewall_rule using
the IP address from step 4:
9. Switch computers again and click Connect in the Connect to Server dialog box to connect to
AdventureWorksLT as aaduser1.
10. In Object Explorer, expand Databases, expand AdventureWorksLT, and then expand Tables. Notice that
user1 only has permission to view a single table, the SalesLT.ProductCategory table.
11. In Object Explorer, right-click SalesLT.ProductCategory and click Select Top 1000 Rows.
Next steps
For an overview of access and control in SQL Database, see SQL Database access and control.
For an overview of logins, users, and database roles in SQL Database, see Logins, users, and database roles.
For more information about database principals, see Principals.
For more information about database roles, see Database roles.
For more information about firewall rules in SQL Database, see SQL Database firewall rules.
Configure and manage Azure Active Directory
authentication with SQL Database or SQL Data
Warehouse
4/14/2017 • 16 min to read • Edit Online
This article shows you how to create and populate Azure AD, and then use Azure AD with Azure SQL Database and
SQL Data Warehouse. For an overview, see Azure Active Directory Authentication.
5. In the EDIT DIRECTORY box, select the Azure Active Directory that is associated with your SQL Server or
SQL Data Warehouse, and then click the arrow for next.
6. In the CONFIRM directory Mapping dialog box, confirm that "All co-administrators will be removed."
NOTE
When you change the directory, access to all co-administrators, Azure AD users and groups, and directory-backed
resource users are removed and they no longer have access to this subscription or its resources. Only you, as a
service administrator, can configure access for principals based on the new directory. This change might take a
substantial amount of time to propagate to all resources. Changing the directory, also changes the Azure AD
administrator for SQL Database and SQL Data Warehouse and disallow database access for any existing Azure AD
users. The Azure AD admin must be reset (as described below) and new Azure AD users must be created.
NOTE
Users that are not based on an Azure AD account (including the Azure SQL server administrator account), cannot create
Azure AD-based users, because they do not have permission to validate proposed database users with the Azure AD.
2. In the left banner select SQL servers, select your SQL server, and then in the SQL Server blade, at the top
click Settings.
3. In the Settings blade, click Active Directory admin.
4. In the Active Directory admin blade, click Active Directory admin, and then at the top, click Set admin.
5. In the Add admin blade, search for a user, select the user or group to be an administrator, and then click
Select. (The Active Directory admin blade shows all members and groups of your Active Directory. Users or
groups that are grayed out cannot be selected because they are not supported as Azure AD administrators. (See
the list of supported admins in Azure AD Features and Limitations above.) Role-based access control (RBAC)
applies only to the portal and is not propagated to SQL Server.
6. At the top of the Active Directory admin blade, click SAVE.
The process of changing the administrator may take several minutes. Then the new administrator appears in
the Active Directory admin box.
NOTE
When setting up the Azure AD admin, the new admin name (user or group) cannot already be present in the virtual
master database as a SQL Server authentication user. If present, the Azure AD admin setup will fail; rolling back its
creation and indicating that such an admin (name) already exists. Since such a SQL Server authentication user is not
part of the Azure AD, any effort to connect to the server using Azure AD authentication fails.
To later remove an Admin, at the top of the Active Directory admin blade, click Remove admin, and then click
Save.
PowerShell
To run PowerShell cmdlets, you need to have Azure PowerShell installed and running. For detailed information, see
How to install and configure Azure PowerShell.
To provision an Azure AD admin, execute the following Azure PowerShell commands:
Add-AzureRmAccount
Select-AzureRmSubscription
Cmdlets used to provision and manage Azure AD admin:
Use PowerShell command get-help to see more details for each of these commands, for example
get-help Set-AzureRmSqlServerActiveDirectoryAdministrator .
The following script provisions an Azure AD administrator group named DBA_Group (object id
40b79501-b343-44ed-9ce7-da4c8cc7353f ) for the demo_server server in a resource group named Group-23:
The DisplayName input parameter accepts either the Azure AD display name or the User Principal Name. For
example, DisplayName="John Smith" and DisplayName="johns@contoso.com" . For Azure AD groups only the Azure AD
display name is supported.
NOTE
The Azure PowerShell command Set-AzureRmSqlServerActiveDirectoryAdministrator does not prevent you from
provisioning Azure AD admins for unsupported users. An unsupported user can be provisioned, but can not connect to a
database.
NOTE
The Azure AD ObjectID is required when the DisplayName is not unique. To retrieve the ObjectID and DisplayName
values, use the Active Directory section of Azure Classic Portal, and view the properties of a user or group.
The following example returns information about the current Azure AD admin for Azure SQL server:
You can also provision an Azure Active Directory Administrator by using the REST APIs. For more information, see
Service Management REST API Reference and Operations for Azure SQL Databases Operations for Azure SQL
Databases
To create an Azure AD-based contained database user (other than the server administrator that owns the
database), connect to the database with an Azure AD identity, as a user with at least the ALTER ANY USER
permission. Then use the following Transact-SQL syntax:
Azure_AD_principal_name can be the user principal name of an Azure AD user or the display name for an Azure
AD group.
Examples: To create a contained database user representing an Azure AD federated or managed domain user:
To create a contained database user representing an Azure AD or federated domain group, provide the display
name of a security group:
To create a contained database user representing an application that connects using an Azure AD token:
TIP
You cannot directly create a user from an Azure Active Directory other than the Azure Active Directory that is associated
with your Azure subscription. However, members of other Active Directories that are imported users in the associated Active
Directory (known as external users) can be added to an Active Directory group in the tenant Active Directory. By creating a
contained database user for that AD group, the users from the external Active Directory can gain access to SQL Database.
For more information about creating contained database users based on Azure Active Directory identities, see
CREATE USER (Transact-SQL).
NOTE
Removing the Azure Active Directory administrator for Azure SQL server prevents any Azure AD authentication user from
connecting to the server. If necessary, unusable Azure AD users can be dropped manually by a SQL Database administrator.
NOTE
If you receive a Connection Timeout Expired, you may need to set the TransparentNetworkIPResolution parameter of
the connection string to false. For more information, see Connection timeout issue with .NET Framework 4.6.1 -
TransparentNetworkIPResolution.
When you create a database user, that user receives the CONNECT permission and can connect to that database
as a member of the PUBLIC role. Initially the only permissions available to the user are any permissions granted to
the PUBLIC role, or any permissions granted to any Windows groups that they are a member of. Once you
provision an Azure AD-based contained database user, you can grant the user additional permissions, the same
way as you grant permission to any other type of user. Typically grant permissions to database roles, and add
users to roles. For more information, see Database Engine Permission Basics. For more information about special
SQL Database roles, see Managing Databases and Logins in Azure SQL Database. A federated domain user that is
imported into a manage domain, must use the managed domain identity.
NOTE
Azure AD users are marked in the database metadata with type E (EXTERNAL_USER) and for groups with type X
(EXTERNAL_GROUPS). For more information, see sys.database_principals.
IMPORTANT
Support for Azure Active Directory authentication is available with SQL Server 2016 Management Studio and SQL Server
Data Tools in Visual Studio 2015. The August 2016 release of SSMS also includes support for Active Directory Universal
Authentication, which allows administrators to require Multi-Factor Authentication using a phone call, text message, smart
cards with pin, or mobile app notification.
4. Click the Options button, and on the Connection Properties page, in the Connect to database box, type the
name of the user database you want to connect to. (See the graphic in the previous option.)
string ConnectionString =
@"Data Source=n9lxnyuzhv.database.windows.net; Authentication=Active Directory Integrated; Initial Catalog=testdb;";
SqlConnection conn = new SqlConnection(ConnectionString);
conn.Open();
The connection string keyword Integrated Security=True is not supported for connecting to Azure SQL Database.
When making an ODBC connection, you will need to remove spaces and set Authentication to
'ActiveDirectoryIntegrated'.
Active Directory password authentication
To connect to a database using integrated authentication and an Azure AD identity, the Authentication keyword
must be set to Active Directory Password. The connection string must contain User ID/UID and Password/PWD
keywords and values. The following C# code sample uses ADO .NET.
string ConnectionString =
@"Data Source=n9lxnyuzhv.database.windows.net; Authentication=Active Directory Password; Initial Catalog=testdb;
UID=bob@contoso.onmicrosoft.com; PWD=MyPassWord!";
SqlConnection conn = new SqlConnection(ConnectionString);
conn.Open();
Learn more about Azure AD authentication methods using the demo code samples available at Azure AD
Authentication GitHub Demo.
Azure AD token
This authentication method allows middle-tier services to connect to Azure SQL Database or Azure SQL Data
Warehouse by obtaining a token from Azure Active Directory (AAD). It enables sophisticated scenarios including
certificate-based authentication. You must complete four basic steps to use Azure AD token authentication:
1. Register your application with Azure Active Directory and get the client id for your code.
2. Create a database user representing the application. (Completed earlier in step 6.)
3. Create a certificate on the client computer runs the application.
4. Add the certificate as a key for your application.
Sample connection string:
sqlcmd -S Target_DB_or_DW.testsrv.database.windows.net -G
sqlcmd -S Target_DB_or_DW.testsrv.database.windows.net -U bob@contoso.com -P MyAADPassword -G -l 30
Next steps
For an overview of access and control in SQL Database, see SQL Database access and control.
For an overview of logins, users, and database roles in SQL Database, see Logins, users, and database roles.
For more information about database principals, see Principals.
For more information about database roles, see Database roles.
For more information about firewall rules in SQL Database, see SQL Database firewall rules.
For a tutorial using SQL Server authentication, see SQL authentication and authorization.
For a tutorial using Azure Active Directory authentication, see Azure AD authentication and authorization.
Always Encrypted: Protect sensitive data in SQL
Database and store your encryption keys in the
Windows certificate store
4/14/2017 • 12 min to read • Edit Online
This article shows you how to secure sensitive data in a SQL database with database encryption by using the
Always Encrypted Wizard in SQL Server Management Studio (SSMS). It also shows you how to store your
encryption keys in the Windows certificate store.
Always Encrypted is a new data encryption technology in Azure SQL Database and SQL Server that helps protect
sensitive data at rest on the server, during movement between client and server, and while the data is in use,
ensuring that sensitive data never appears as plaintext inside the database system. After you encrypt data, only
client applications or app servers that have access to the keys can access plaintext data. For detailed information,
see Always Encrypted (Database Engine).
After configuring the database to use Always Encrypted, you will create a client application in C# with Visual Studio
to work with the encrypted data.
Follow the steps in this article to learn how to set up Always Encrypted for an Azure SQL database. In this article,
you will learn how to perform the following tasks:
Use the Always Encrypted wizard in SSMS to create Always Encrypted Keys.
Create a Column Master Key (CMK).
Create a Column Encryption Key (CEK).
Create a database table and encrypt columns.
Create an application that inserts, selects, and displays data from the encrypted columns.
Prerequisites
For this tutorial, you'll need:
An Azure account and subscription. If you don't have one, sign up for a free trial.
SQL Server Management Studio version 13.0.700.242 or later.
.NET Framework 4.6 or later (on the client computer).
Visual Studio.
If the New Firewall Rule window opens, sign in to Azure and let SSMS create a new firewall rule for you.
Create a table
In this section, you will create a table to hold patient data. This will be a normal table initially--you will configure
encryption in the next section.
1. Expand Databases.
2. Right-click the Clinic database and click New Query.
3. Paste the following Transact-SQL (T-SQL) into the new query window and Execute it.
IMPORTANT
Your application must use SqlParameter objects when passing plaintext data to the server with Always Encrypted columns.
Passing literal values without using SqlParameter objects will result in an exception.
1. Open Visual Studio and create a new C# console application. Make sure your project is set to .NET Framework
4.6 or later.
2. Name the project AlwaysEncryptedConsoleApp and click OK.
NOTE
This is the only change required in a client application specific to Always Encrypted. If you have an existing application that
stores its connection string externally (that is, in a config file), you might be able to enable Always Encrypted without
changing any code.
// Instantiate a SqlConnectionStringBuilder.
SqlConnectionStringBuilder connStringBuilder =
new SqlConnectionStringBuilder("replace with your connection string");
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;
namespace AlwaysEncryptedConsoleApp
{
class Program
class Program
{
// Update this line with your Clinic database connection string from the Azure portal.
static string connectionString = @"Replace with your connection string";
// Create a SqlConnectionStringBuilder.
SqlConnectionStringBuilder connStringBuilder =
new SqlConnectionStringBuilder(connectionString);
InsertPatient(new Patient() {
SSN = "999-99-0001", FirstName = "Orlando", LastName = "Gee", BirthDate = DateTime.Parse("01/04/1964") });
InsertPatient(new Patient() {
SSN = "999-99-0002", FirstName = "Keith", LastName = "Harris", BirthDate = DateTime.Parse("06/20/1977") });
InsertPatient(new Patient() {
SSN = "999-99-0003", FirstName = "Donna", LastName = "Carreras", BirthDate = DateTime.Parse("02/09/1973") });
InsertPatient(new Patient() {
SSN = "999-99-0004", FirstName = "Janet", LastName = "Gates", BirthDate = DateTime.Parse("08/31/1985") });
InsertPatient(new Patient() {
SSN = "999-99-0005", FirstName = "Lucy", LastName = "Harrington", BirthDate = DateTime.Parse("05/06/1993") });
string ssn;
// This very simple validation only checks that the user entered 11 characters.
// In production be sure to check all user input and use the best validation for your specific application.
do
{
Console.WriteLine("Please enter a valid SSN (ex. 123-45-6789):");
ssn = Console.ReadLine();
} while (ssn.Length != 11);
// The example allows duplicate SSN entries so we will return all records
// that match the provided value and store the results in selectedPatients.
Patient selectedPatient = SelectPatientBySSN(ssn);
// Check if any records were returned and display our query results.
if (selectedPatient != null)
{
Console.WriteLine("Patient found with SSN = " + ssn);
Console.WriteLine(selectedPatient.FirstName + " " + selectedPatient.LastName + "\tSSN: "
+ selectedPatient.SSN + "\tBirthdate: " + selectedPatient.BirthDate);
}
else
{
Console.WriteLine("No patients found with SSN = " + ssn);
}
sqlCmd.Parameters.Add(paramSSN);
sqlCmd.Parameters.Add(paramFirstName);
sqlCmd.Parameters.Add(paramLastName);
sqlCmd.Parameters.Add(paramBirthDate);
if (reader.HasRows)
{
while (reader.Read())
{
patients.Add(new Patient()
{
SSN = reader[0].ToString(),
FirstName = reader[1].ToString(),
LastName = reader["LastName"].ToString(),
BirthDate = (DateTime)reader["BirthDate"]
});
}
}
}
catch (Exception ex)
{
throw;
}
}
return patients;
}
sqlCmd.Parameters.Add(paramSSN);
if (reader.HasRows)
{
while (reader.Read())
{
patient = new Patient()
{
SSN = reader[0].ToString(),
FirstName = reader[1].ToString(),
LastName = reader["LastName"].ToString(),
BirthDate = (DateTime)reader["BirthDate"]
};
}
}
else
{
patient = null;
}
}
catch (Exception ex)
{
throw;
}
}
return patient;
}
// This method simply deletes all records in the Patients table to reset our demo.
static int ResetPatientsTable()
{
int returnValue = 0;
}
catch (Exception ex)
{
returnValue = 1;
}
}
return returnValue;
}
}
class Patient
{
public string SSN { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime BirthDate { get; set; }
}
}
You can see that the encrypted columns do not contain any plaintext data.
To use SSMS to access the plaintext data, you can add the Column Encryption Setting=enabled parameter to
the connection.
1. In SSMS, right-click your server in Object Explorer, and then click Disconnect.
2. Click Connect > Database Engine to open the Connect to Server window, and then click Options.
3. Click Additional Connection Parameters and type Column Encryption Setting=enabled.
You can now see the plaintext data in the encrypted columns.
NOTE
If you connect with SSMS (or any client) from a different computer, it will not have access to the encryption keys and will not
be able to decrypt the data.
Next steps
After you create a database that uses Always Encrypted, you may want to do the following:
Run this sample from a different computer. It won't have access to the encryption keys, so it will not have access
to the plaintext data and will not run successfully.
Rotate and clean up your keys.
Migrate data that is already encrypted with Always Encrypted.
Deploy Always Encrypted certificates to other client machines (see the "Making Certificates Available to
Applications and Users" section).
Related information
Always Encrypted (client development)
Transparent Data Encryption
SQL Server Encryption
Always Encrypted Wizard
Always Encrypted Blog
Always Encrypted: Protect sensitive data in SQL
Database and store your encryption keys in Azure
Key Vault
4/14/2017 • 14 min to read • Edit Online
This article shows you how to secure sensitive data in a SQL database with data encryption using the Always
Encrypted Wizard in SQL Server Management Studio (SSMS). It also includes instructions that will show you how
to store each encryption key in Azure Key Vault.
Always Encrypted is a new data encryption technology in Azure SQL Database and SQL Server that helps protect
sensitive data at rest on the server, during movement between client and server, and while the data is in use.
Always Encrypted ensures that sensitive data never appears as plaintext inside the database system. After you
configure data encryption, only client applications or app servers that have access to the keys can access plaintext
data. For detailed information, see Always Encrypted (Database Engine).
After you configure the database to use Always Encrypted, you will create a client application in C# with Visual
Studio to work with the encrypted data.
Follow the steps in this article and learn how to set up Always Encrypted for an Azure SQL database. In this article
you will learn how to perform the following tasks:
Use the Always Encrypted wizard in SSMS to create Always Encrypted keys.
Create a column master key (CMK).
Create a column encryption key (CEK).
Create a database table and encrypt columns.
Create an application that inserts, selects, and displays data from the encrypted columns.
Prerequisites
For this tutorial, you'll need:
An Azure account and subscription. If you don't have one, sign up for a free trial.
SQL Server Management Studio version 13.0.700.242 or later.
.NET Framework 4.6 or later (on the client computer).
Visual Studio.
Azure PowerShell, version 1.0 or later. Type (Get-Module azure -ListAvailable).Version to see what version
of PowerShell you are running.
Login-AzureRmAccount
$subscriptionId = (Get-AzureRmSubscription -SubscriptionName $subscriptionName).SubscriptionId
Set-AzureRmContext -SubscriptionId $subscriptionId
If the New Firewall Rule window opens, sign in to Azure and let SSMS create a new firewall rule for you.
Create a table
In this section, you will create a table to hold patient data. It's not initially encrypted--you will configure encryption
in the next section.
1. Expand Databases.
2. Right-click the Clinic database and click New Query.
3. Paste the following Transact-SQL (T-SQL) into the new query window and Execute it.
IMPORTANT
Your application must use SqlParameter objects when passing plaintext data to the server with Always Encrypted columns.
Passing literal values without using SqlParameter objects will result in an exception.
1. Open Visual Studio and create a new C# Console Application (Visual Studio 2015 and earlier) or Console
App (.NET Framework) (Visual Studio 2017 and later). Make sure your project is set to .NET Framework 4.6
or later.
2. Name the project AlwaysEncryptedConsoleAKVApp and click OK.
3. Install the following NuGet packages by going to Tools > NuGet Package Manager > Package Manager
Console.
Run these two lines of code in the Package Manager Console.
Install-Package Microsoft.SqlServer.Management.AlwaysEncrypted.AzureKeyVaultProvider
Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory
// Instantiate a SqlConnectionStringBuilder.
SqlConnectionStringBuilder connStringBuilder =
new SqlConnectionStringBuilder("replace with your connection string");
SqlColumnEncryptionAzureKeyVaultProvider azureKeyVaultProvider =
new SqlColumnEncryptionAzureKeyVaultProvider(GetToken);
providers.Add(SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, azureKeyVaultProvider);
SqlConnection.RegisterColumnEncryptionKeyStoreProviders(providers);
}
Always Encrypted sample console application
This sample demonstrates how to:
Modify your connection string to enable Always Encrypted.
Register Azure Key Vault as the application's key store provider.
Insert data into the encrypted columns.
Select a record by filtering for a specific value in an encrypted column.
Replace the contents of Program.cs with the following code. Replace the connection string for the global
connectionString variable in the line that directly precedes the Main method with your valid connection string from
the Azure portal. This is the only change you need to make to this code.
Run the app to see Always Encrypted in action.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Microsoft.SqlServer.Management.AlwaysEncrypted.AzureKeyVaultProvider;
namespace AlwaysEncryptedConsoleAKVApp
{
class Program
{
// Update this line with your Clinic database connection string from the Azure portal.
static string connectionString = @"<connection string from the portal>";
static string clientId = @"<client id from step 7 above>";
static string clientSecret = "<key from step 13 above>";
// Create a SqlConnectionStringBuilder.
SqlConnectionStringBuilder connStringBuilder =
new SqlConnectionStringBuilder(connectionString);
InsertPatient(new Patient()
{
SSN = "999-99-0001",
FirstName = "Orlando",
LastName = "Gee",
BirthDate = DateTime.Parse("01/04/1964")
});
InsertPatient(new Patient()
{
SSN = "999-99-0002",
FirstName = "Keith",
LastName = "Harris",
BirthDate = DateTime.Parse("06/20/1977")
});
InsertPatient(new Patient()
{
SSN = "999-99-0003",
FirstName = "Donna",
LastName = "Carreras",
BirthDate = DateTime.Parse("02/09/1973")
});
InsertPatient(new Patient()
{
SSN = "999-99-0004",
FirstName = "Janet",
LastName = "Gates",
BirthDate = DateTime.Parse("08/31/1985")
});
InsertPatient(new Patient()
{
SSN = "999-99-0005",
FirstName = "Lucy",
LastName = "Harrington",
BirthDate = DateTime.Parse("05/06/1993")
});
string ssn;
// This very simple validation only checks that the user entered 11 characters.
// In production be sure to check all user input and use the best validation for your specific application.
do
{
Console.WriteLine("Please enter a valid SSN (ex. 999-99-0003):");
ssn = Console.ReadLine();
} while (ssn.Length != 11);
// The example allows duplicate SSN entries so we will return all records
// that match the provided value and store the results in selectedPatients.
Patient selectedPatient = SelectPatientBySSN(ssn);
// Check if any records were returned and display our query results.
// Check if any records were returned and display our query results.
if (selectedPatient != null)
{
Console.WriteLine("Patient found with SSN = " + ssn);
Console.WriteLine(selectedPatient.FirstName + " " + selectedPatient.LastName + "\tSSN: "
+ selectedPatient.SSN + "\tBirthdate: " + selectedPatient.BirthDate);
}
else
{
Console.WriteLine("No patients found with SSN = " + ssn);
}
SqlColumnEncryptionAzureKeyVaultProvider azureKeyVaultProvider =
new SqlColumnEncryptionAzureKeyVaultProvider(GetToken);
providers.Add(SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, azureKeyVaultProvider);
SqlConnection.RegisterColumnEncryptionKeyStoreProviders(providers);
}
public async static Task<string> GetToken(string authority, string resource, string scope)
{
var authContext = new AuthenticationContext(authority);
AuthenticationResult result = await authContext.AcquireTokenAsync(resource, _clientCredential);
if (result == null)
throw new InvalidOperationException("Failed to obtain the access token");
return result.AccessToken;
}
sqlCmd.Parameters.Add(paramSSN);
sqlCmd.Parameters.Add(paramFirstName);
sqlCmd.Parameters.Add(paramLastName);
sqlCmd.Parameters.Add(paramBirthDate);
if (reader.HasRows)
{
while (reader.Read())
{
patients.Add(new Patient()
{
SSN = reader[0].ToString(),
FirstName = reader[1].ToString(),
LastName = reader["LastName"].ToString(),
BirthDate = (DateTime)reader["BirthDate"]
});
}
}
}
catch (Exception ex)
{
throw;
}
}
return patients;
}
static Patient SelectPatientBySSN(string ssn)
{
Patient patient = new Patient();
sqlCmd.Parameters.Add(paramSSN);
if (reader.HasRows)
{
while (reader.Read())
{
patient = new Patient()
{
SSN = reader[0].ToString(),
FirstName = reader[1].ToString(),
LastName = reader["LastName"].ToString(),
BirthDate = (DateTime)reader["BirthDate"]
};
}
}
else
{
patient = null;
}
}
catch (Exception ex)
{
throw;
}
}
return patient;
}
// This method simply deletes all records in the Patients table to reset our demo.
static int ResetPatientsTable()
{
int returnValue = 0;
}
catch (Exception ex)
{
returnValue = 1;
}
}
}
return returnValue;
}
}
class Patient
{
public string SSN { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime BirthDate { get; set; }
}
}
You can see that the encrypted columns do not contain any plaintext data.
To use SSMS to access the plaintext data, you can add the Column Encryption Setting=enabled parameter to the
connection.
1. In SSMS, right-click your server in Object Explorer and choose Disconnect.
2. Click Connect > Database Engine to open the Connect to Server window and click Options.
3. Click Additional Connection Parameters and type Column Encryption Setting=enabled.
4. Run the following query on the Clinic database.
You can now see the plaintext data in the encrypted columns.
Next steps
After you create a database that uses Always Encrypted, you may want to do the following:
Rotate and clean up your keys.
Migrate data that is already encrypted with Always Encrypted.
Related information
Always Encrypted (client development)
Transparent data encryption
SQL Server encryption
Always Encrypted wizard
Always Encrypted blog
Get started with SQL Database dynamic data masking
with the Azure Portal
4/14/2017 • 1 min to read • Edit Online
This topic shows you how to implement dynamic data masking with the Azure portal. You can also implement
dynamic data masking using Azure SQL Database cmdlets or the REST API.
Set up dynamic data masking for your database using the Azure Portal
1. Launch the Azure Portal at https://portal.azure.com.
2. Navigate to the settings blade of the database that includes the sensitive data you want to mask.
3. Click the Dynamic Data Masking tile which launches the Dynamic Data Masking configuration blade.
Alternatively, you can scroll down to the Operations section and click Dynamic Data Masking.
4. In the Dynamic Data Masking configuration blade you may see some database columns that the
recommendations engine has flagged for masking. In order to accept the recommendations, just click Add
Mask for one or more columns and a mask will be created based on the default type for this column. You
can change the masking function by clicking on the masking rule and editing the masking field format to a
different format of your choice. Be sure to click Save to save your settings.
5. To add a mask for any column in your database, at the top of the Dynamic Data Masking configuration
blade click Add Mask to open the Add Masking Rule configuration blade
6. Select the Schema, Table and Column to define the designated field that will be masked.
7. Choose a Masking Field Format from the list of sensitive data masking categories.
8. Click Save in the data masking rule blade to update the set of masking rules in the dynamic data masking
policy.
9. Type the SQL users or AAD identities that should be excluded from masking, and have access to the
unmasked sensitive data. This should be a semicolon-separated list of users. Note that users with
administrator privileges always have access to the original unmasked data.
TIP
To make it so the application layer can display sensitive data for application privileged users, add the SQL user or AAD
identity the application uses to query the database. It is highly recommended that this list contain a minimal number
of privileged users to minimize exposure of the sensitive data.
10. Click Save in the data masking configuration blade to save the new or updated masking policy.
Next steps
For an overview of dynamic data masking, see dynamic data masking.
You can also implement dynamic data masking using Azure SQL Database cmdlets or the REST API.
How to restore a single table from an Azure SQL
Database backup
4/10/2017 • 2 min to read • Edit Online
You may encounter a situation in which you accidentally modified some data in a SQL database and now you want
to recover the single affected table. This article describes how to restore a single table in a database from one of the
SQL Database automatic backups.
Preparation steps: Rename the table and restore a copy of the database
1. Identify the table in your Azure SQL database that you want to replace with the restored copy. Use Microsoft
SQL Management Studio to rename the table. For example, rename the table as <table name>_old.
NOTE
To avoid being blocked, make sure that there's no activity running on the table that you are renaming. If you
encounter issues, make sure that perform this procedure during a maintenance window.
2. Restore a backup of your database to a point in time that you want to recover to using the Point-In_Time
Restore steps.
NOTE
The name of the restored database will be in the DBName+TimeStamp format; for example,
Adventureworks2012_2016-01-01T22-12Z. This step doesn't overwrite the existing database name on the server.
This is a safety measure, and it's intended to allow you to verify the restored database before they drop their current
database and rename the restored database for production use.
Copying the table from the restored database by using the SQL
Database Migration tool
1. Download and install the SQL Database Migration Wizard.
2. Open the SQL Database Migration Wizard, on the Select Process page, select Database under
Analyze/Migrate, and then click Next.
3. In the Connect to Server dialog box, apply the following settings:
Server name: Your SQL server
Authentication: SQL Server Authentication
Login: Your login
Password: Your password
Database: Master DB (List all databases)
NOTE
By default the wizard saves your login information. If you don't want it to, select Forget Login Information.
4. In the Select Source dialog box, select the restored database name from the Preparation steps section as
your source, and then click Next.
5. In the Choose Objects dialog box, select the Select specific database objects option, and then select the
table(or tables) that you want to migrate to the target server.
6. On the Script Wizard Summary page, click Yes when you’re prompted about whether you’re ready to
generate a SQL script. You also have the option to save the TSQL Script for later use.
7. On the Results Summary page, click Next.
8. On the Setup Target Server Connection page, click Connect to Server, and then enter the details as
follows:
Server Name: Target server instance
Authentication: SQL Server authentication. Enter your login credentials.
Database: Master DB (List all databases). This option lists all the databases on the target server.
9. Click Connect, select the target database that you want to move the table to, and then click Next. This should
finish running the previously generated script, and you should see the newly moved table copied to the target
database.
Verification step
Query and test the newly copied table to make sure that the data is intact. Upon confirmation, you can drop the
renamed table form Preparation steps section. (for example, <table name>_old).
Next steps
SQL Database automatic backups
Configure and restore from Azure SQL Database
long-term backup retention
4/12/2017 • 6 min to read • Edit Online
You can configure the Azure Recovery Services vault to store Azure SQL database backups and then recover a
database using backups retained in the vault using the Azure portal or PowerShell.
Azure portal
The following sections show you how to use the Azure portal to configure the Azure Recovery Services vault,
view backups in the vault, and restore from the vault.
Configure the vault, register the server, and select databases
You configure an Azure Recovery Services vault to retain automated backups for a period longer than the
retention period for your service tier.
TIP
To delete backups in long-term backup retention, see Configure and use long-term backup retention.
4. To configure long-term backup retention, select that database in the grid and then click Configure on the
toolbar.
5. On the Configure page, click Configure required settings under Recovery service vault.
6. On the Recovery services vault page, select an existing vault, if any. Otherwise, if no recovery services
vault found for your subscription, click to exit the flow and create a recovery services vault.
9. Select your subscription and resource group, and then select the location for the vault. When done, click
Create.
IMPORTANT
The vault must be located in the same region as the Azure SQL logical server, and must use the same resource
group as the logical server.
10. After the new vault is created, execute the necessary steps to return to the Recovery services vault page.
11. On the Recovery services vault page, click the vault and then click Select.
12. On the Configure page, provide a valid name for the new retention policy, modify the default retention
policy as appropriate, and then click OK.
13. On the Long-term backup retention page for your database, click Save and then click OK to apply the
long-term backup retention policy to all selected databases.
14. Click Save to enable long-term backup retention using this new policy to the Azure Recovery Services
vault that you configured.
IMPORTANT
Once configured, backups show up in the vault within next seven days. Do not continue this tutorial until backups show
up in the vault.
3. Click OK to restore your database from the backup in the vault to the new database.
4. On the toolbar, click the notification icon to view the status of the restore job.
5. When the restore job is completed, open the SQL databases page to view the newly restored database.
NOTE
From here, you can connect to the restored database using SQL Server Management Studio to perform needed tasks,
such as to extract a bit of data from the restored database to copy into the existing database or to delete the existing
database and rename the restored database to the existing database name.
PowerShell
The following sections show you how to use PowerShell to configure the Azure Recovery Services vault, view
backups in the vault, and restore from the vault.
Create a recovery services vault
Use the New-AzureRmRecoveryServicesVault to create a recovery services vault.
IMPORTANT
The vault must be located in the same region as the Azure SQL logical server, and must use the same resource group as
the logical server.
#$resourceGroupName = "{resource-group-name}"
#$serverName = "{server-name}"
$serverLocation = (Get-AzureRmSqlServer -ServerName $serverName -ResourceGroupName $resourceGroupName).Location
$recoveryServiceVaultName = "{new-vault-name}"
Set your server to use the recovery vault for its long-term retention backups
Use the Set-AzureRmSqlServerBackupLongTermRetentionVault cmdlet to associate a previously created
recovery services vault with a specific Azure SQL server.
# Set your server to use the vault to for long-term backup retention
NOTE
Some cmdlets require that you set the vault context before running (Set-AzureRmRecoveryServicesVaultContext) so you
see this cmdlet in a few related snippets. You set the context because the policy is part of the vault. You can create
multiple retention policies for each vault and then apply the desired policy to specific databases.
# Retrieve the default retention policy for the AzureSQLDatabase workload type
$retentionPolicy = Get-AzureRmRecoveryServicesBackupRetentionPolicyObject -WorkloadType AzureSQLDatabase
# Set the retention value to two years (you can set to any time between 1 week and 10 years)
$retentionPolicy.RetentionDurationType = "Years"
$retentionPolicy.RetentionCount = 2
$retentionPolicyName = "my2YearRetentionPolicy"
# Set the vault context to the vault you are creating the policy for
Set-AzureRmRecoveryServicesVaultContext -Vault $vault
IMPORTANT
Once configured, backups show up in the vault within next seven days. Continue this tutorial after backups show up in
the vault.
#$resourceGroupName = "{resource-group-name}"
#$serverName = "{server-name}"
$databaseNeedingRestore = $databaseName
# the following commands find the container associated with the server 'myserver' under resource group 'myresourcegroup'
$container = Get-AzureRmRecoveryServicesBackupContainer -ContainerType AzureSQL -FriendlyName $vault.Name
NOTE
From here, you can connect to the restored database using SQL Server Management Studio to perform needed tasks,
such as to extract a bit of data from the restored database to copy into the existing database or to delete the existing
database and rename the restored database to the existing database name.
Next steps
To learn about service-generated automatic backups, see automatic backups
To learn about long-term backup retention, see long-term backup retention
To learn about restoring from backups, see restore from backup
Configure active geo-replication for Azure SQL
Database in the Azure portal and initiate failover
4/14/2017 • 3 min to read • Edit Online
This article shows you how to configure active geo-replication for SQL Database in the Azure portal and to initiate
failover.
To initiate failover with the Azure portal, see Initiate a planned or unplanned failover for Azure SQL Database with
the Azure portal.
NOTE
Active geo-replication (readable secondaries) is now available for all databases in all service tiers. In April 2017, the non-
readable secondary type will be retired, and existing non-readable databases will automatically be upgraded to readable
secondaries.
To configure active geo-replication by using the Azure portal, you need the following resource:
An Azure SQL database: The primary database that you want to replicate to a different geographical region.
NOTE
Active geo-replication must be between databases in the same subscription.
NOTE
If the partner database already exists (for example, as a result of terminating a previous geo-replication relationship) the
command fails.
1. In the Azure portal, browse to the database that you want to set up for geo-replication.
2. On the SQL database page, select Geo-Replication, and then select the region to create the secondary
database. You can select any region other than the region hosting the primary database, but we
recommend the paired region.
3. Select or configure the server and pricing tier for the secondary database.
4. Optionally, you can add a secondary database to an elastic pool. To create the secondary database in a pool,
click elastic pool and select a pool on the target server. A pool must already exist on the target server. This
workflow does not create a pool.
5. Click Create to add the secondary.
6. The secondary database is created and the seeding process begins.
7. When the seeding process is complete, the secondary database displays its status.
Initiate a failover
The secondary database can be switched to become the primary.
1. In the Azure portal, browse to the primary database in the Geo-Replication partnership.
2. On the SQL Database blade, select All settings > Geo-Replication.
3. In the SECONDARIES list, select the database you want to become the new primary and click Failover.
4. Click Yes to begin the failover.
The command immediately switches the secondary database into the primary role.
There is a short period during which both databases are unavailable (on the order of 0 to 25 seconds) while the
roles are switched. If the primary database has multiple secondary databases, the command automatically
reconfigures the other secondaries to connect to the new primary. The entire operation should take less than a
minute to complete under normal circumstances.
NOTE
If the primary is online and committing transactions when the command is issued some data loss may occur.
Next steps
To learn more about active geo-replication, see Active geo-replication.
For a business continuity overview and scenarios, see Business continuity overview.
Configure active geo-replication for Azure SQL
Database with Transact-SQL
2/16/2017 • 7 min to read • Edit Online
This article shows you how to configure active geo-replication for an Azure SQL Database with Transact-SQL.
To initiate failover using Transact-SQL, see Initiate a planned or unplanned failover for Azure SQL Database with
Transact-SQL.
NOTE
Active geo-replication (readable secondaries) is now available for all databases in all service tiers. In April 2017 the non-
readable secondary type will be retired and existing non-readable databases will automatically be upgraded to readable
secondaries.
IMPORTANT
It is recommended that you always use the latest version of Management Studio to remain synchronized with updates to
Microsoft Azure and SQL Database. Update SQL Server Management Studio.
NOTE
If a database exists on the specified partner server with the same name as the primary database the command will fail.
IMPORTANT
Download the latest version of SQL Server Management Studio. It is recommended that you always use the latest
version of Management Studio to remain in sync with updates to the Azure portal.
2. Open the Databases folder, expand the System Databases folder, right-click on master, and then click New
Query.
3. Use the following ALTER DATABASE statement to make a local database into a Geo-Replication primary
with a non-readable secondary database on MySecondaryServer1 where MySecondaryServer1 is your
friendly server name.
IMPORTANT
There is no self-service method of in-place upgrading of a non-readable secondary to readable. If you drop your only
secondary, then the primary database will remain unprotected until the new secondary is fully synchronized. If your
application’s SLA requires that the primary is always protected, you should consider creating a parallel secondary in a
different server before applying the upgrade steps above. Note each primary can have up to 4 secondary databases.
1. First, connect to the secondary server and drop the non-readable secondary database:
2. Now connect to the primary server and add a new readable secondary
Next steps
To learn more about active geo-replication, see - Active geo-replication
For a business continuity overview and scenarios, see Business continuity overview
Initiate a planned or unplanned failover for Azure
SQL Database with Transact-SQL
2/16/2017 • 4 min to read • Edit Online
This article shows you how to initiate failover to a secondary SQL Database using Transact-SQL. To configure Geo-
Replication, see Configure Geo-Replication for Azure SQL Database.
To initiate failover, you need the following:
A login that is DBManager on the primary, have db_ownership of the local database that you will geo-replicate,
and be DBManager on the partner server(s) to which you will configure Geo-Replication.
SQL Server Management Studio (SSMS)
IMPORTANT
It is recommended that you always use the latest version of Management Studio to remain synchronized with updates to
Microsoft Azure and SQL Database. Update SQL Server Management Studio.
NOTE
In rare cases, it is possible that the operation cannot complete and may appear stuck. In this case, the user can execute the
force failover command and accept data loss.
NOTE
If the command is issued when the both primary and secondary are online the old primary will become the new secondary
immediately without data synchronization. If the primary is committing transactions when the command is issued some data
loss may occur.
Next steps
After failover, ensure the authentication requirements for your server and database are configured on the new
primary. For details, see SQL Database security after disaster recovery.
To learn recovering after a disaster using Active Geo-Replication, including pre and post recovery steps and
performing a disaster recovery drill, see Disaster Recovery
For a Sasha Nosov blog post about Active Geo-Replication, see Spotlight on new Geo-Replication capabilities
For information about designing cloud applications to use Active Geo-Replication, see Designing cloud
applications for business continuity using Geo-Replication
For information about using Active Geo-Replication with elastic pools, see Elastic Pool disaster recovery
strategies.
For an overview of business continurity, see Business Continuity Overview
Restore an Azure SQL Database or failover to a
secondary
4/14/2017 • 5 min to read • Edit Online
Azure SQL Database offers the following capabilities for recovering from an outage:
Active Geo-Replication
Geo-Restore
To learn about business continuity scenarios and the features supporting these scenarios, see Business continuity.
Prepare for the event of an outage
For success with recovery to another data region using either Active Geo-Replication or geo-redundant backups,
you need to prepare a server in another data center outage to become the new primary server should the need
arise as well as have well defined steps documented and tested to ensure a smooth recovery. These preparation
steps include:
Identify the logical server in another region to become the new primary server. With Active Geo-Replication,
this will be at least one and perhaps each of the secondary servers. For Geo-Restore, this will generally be a
server in the paired region for the region in which your database is located.
Identify, and optionally define, the server-level firewall rules needed on for users to access the new primary
database.
Determine how you are going to redirect users to the new primary server, such as by changing connection
strings or by changing DNS entries.
Identify, and optionally create, the logins that must be present in the master database on the new primary
server, and ensure these logins have appropriate permissions in the master database, if any. For more
information, see SQL Database security after disaster recovery
Identify alert rules that will need to be updated to map to the new primary database.
Document the auditing configuration on the current primary database
Perform a disaster recovery drill. To simulate an outage for Geo-Restore, you can delete or rename the source
database to cause application connectivity failure. To simulate an outage for Active Geo-Replication, you can
disable the web application or virtual machine connected to the database or failover the database to cause
application connectity failures.
Next steps
To learn about Azure SQL Database automated backups, see SQL Database automated backups
To learn about business continuity design and recovery scenarios, see Continuity scenarios
To learn about using automated backups for recovery, see restore a database from the service-initiated
backups
Performing Disaster Recovery Drill
3/10/2017 • 2 min to read • Edit Online
It is recommended that validation of application readiness for recovery workflow is performed periodically.
Verifying the application behavior and implications of data loss and/or the disruption that failover involves is a
good engineering practice. It is also a requirement by most industry standards as part of business continuity
certification.
Performing a disaster recovery drill consists of:
Simulating data tier outage
Recovering
Validate application integrity post recovery
Depending on how you designed your application for business continuity, the workflow to execute the drill can
vary. Below we describe the best practices conducting a disaster recovery drill in the context of Azure SQL
Database.
Geo-Restore
To prevent the potential data loss when conducting a disaster recovery drill, we recommend performing the drill
using a test environment by creating a copy of the production environment and using it to verify the application’s
failover workflow.
Outage simulation
To simulate the outage you can delete or rename the source database. This will cause application connectivity
failure.
Recovery
Perform the Geo-Restore of the database into a different server as described here.
Change the application configuration to connect to the recovered database(s) and follow the Configure a
database after recovery guide to complete the recovery.
Validation
Complete the drill by verifying the application integrity post recovery (i.e. connection strings, logins, basic
functionality testing or other validations part of standard application signoffs procedures).
Geo-Replication
For a database that is protected using Geo-Replication the drill exercise will involve planned failover to the
secondary database. The planned failover ensures that the primary and the secondary databases remain in sync
when the roles are switched. Unlike the unplanned failover, this operation will not result in data loss, so the drill can
be performed in the production environment.
Outage simulation
To simulate the outage you can disable the web application or virtual machine connected to the database. This will
result in the connectivity failures for the web clients.
Recovery
Make sure the application configuration in the DR region points to the former secondary which will become
fully accessible new primary.
Perform planned failover to make the secondary database a new primary
Follow the Configure a database after recovery guide to complete the recovery.
Validation
Complete the drill by verifying the application integrity post recovery (i.e. connection strings, logins, basic
functionality testing or other validations part of standard application signoffs procedures).
Next steps
To learn about business continuity scenarios, see Continuity scenarios
To learn about Azure SQL Database automated backups, see SQL Database automated backups
To learn about using automated backups for recovery, see restore a database from the service-initiated backups
To learn about faster recovery options, see Active-Geo-Replication
Load data from CSV into Azure SQL Database (flat
files)
4/10/2017 • 2 min to read • Edit Online
You can use the bcp command-line utility to import data from a CSV file into Azure SQL Database.
(Optional) To export your own data from a SQL Server database, open a command prompt and run the following
command. Replace TableName, ServerName, DatabaseName, Username, and Password with your own information.
sqlcmd.exe -S <server name> -d <database name> -U <username> -P <password> -I -Q "SELECT * FROM DimDate2 ORDER BY 1;"
20150101 1 3
20150201 1 3
20150301 1 3
20150401 2 4
20150501 2 4
20150601 2 4
20150701 3 1
20150801 3 1
20150801 3 1
20151001 4 2
DATEID CALENDARQUARTER FISCALQUARTER
20151101 4 2
20151201 4 2
Next steps
To migrate a SQL Server database, see SQL Server database migration.
Tutorial: Copy data from Blob Storage to SQL
Database using Data Factory
4/12/2017 • 4 min to read • Edit Online
In this tutorial, you create a data factory with a pipeline to copy data from Blob storage to SQL database.
The Copy Activity performs the data movement in Azure Data Factory. It is powered by a globally available service
that can copy data between various data stores in a secure, reliable, and scalable way. See Data Movement
Activities article for details about the Copy Activity.
NOTE
For a detailed overview of the Data Factory service, see the Introduction to Azure Data Factory article.
John, Doe
Jane, Doe
2. Use tools such as Azure Storage Explorer to create the adftutorial container and to upload the emp.txt file
to the container.
3. Use the following SQL script to create the emp table in your Azure SQL Database.
If you have SQL Server 2012/2014 installed on your computer: follow instructions from Managing
Azure SQL Database using SQL Server Management Studio to connect to your Azure SQL server and run the
SQL script. This article uses the classic Azure portal, not the new Azure portal, to configure firewall for an
Azure SQL server.
If your client is not allowed to access the Azure SQL server, you need to configure firewall for your Azure
SQL server to allow access from your machine (IP Address). See this article for steps to configure the firewall
for your Azure SQL server.
You have completed the prerequisites. You can create a data factory using one of the following ways. Click one of
the options in the drop-down list at the top or the following links to perform the tutorial.
Copy Wizard
Azure portal
Visual Studio
PowerShell
Azure Resource Manager template
REST API
.NET API
NOTE
The data pipeline in this tutorial copies data from a source data store to a destination data store. It does not transform input
data to produce output data. For a tutorial on how to transform data using Azure Data Factory, see Tutorial: Build your first
pipeline to transform data using Hadoop cluster.
You can chain two activities (run one activity after another) by setting the output dataset of one activity as the input dataset
of the other activity. See Scheduling and execution in Data Factory for detailed information.
Getting Started with Azure SQL Data Sync (Preview)
4/10/2017 • 5 min to read • Edit Online
In this tutorial, you learn the fundamentals of Azure SQL Data Sync using the Azure Classic Portal.
This tutorial assumes minimal prior experience with SQL Server and Azure SQL Database. In this tutorial, you create
a hybrid (SQL Server and SQL Database instances) sync group fully configured and synchronizing on the schedule
you set.
NOTE
The complete technical documentation set for Azure SQL Data Sync, formerly located on MSDN, is available as a .pdf.
Download it here.
Next steps
For additional information on SQL Database and SQL Data Sync see:
Download the complete SQL Data Sync technical documentation
SQL Database Overview
Database Lifecycle Management
Connect to SQL Database using C and C++
4/14/2017 • 5 min to read • Edit Online
This post is aimed at C and C++ developers trying to connect to Azure SQL DB. It is broken down into sections so
you can jump to the section that best captures your interest.
At this point, you have configured your Azure SQL DB and are ready to connect from your C++ code.
Alternatively, you could create a DSN file using the wizard that is launched when no command arguments are
provided. We recommend that you try this option as well. You can use this DSN file for automation and protecting
your authentication settings:
Congratulations! You have now successfully connected to Azure SQL using C++ and ODBC on Windows. You can
continue reading to do the same for Linux platform as well.
sudo su
sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/mssql-ubuntu-test/ xenial main" > /etc/apt/sources.list.d/mssqlpreview.list'
sudo apt-key adv --keyserver apt-mo.trafficmanager.net --recv-keys 417A0893
apt-get update
apt-get install msodbcsql
apt-get install unixodbc-dev-utf16 #this step is optional but recommended*
Launch Visual Studio. Under Tools -> Options -> Cross Platform -> Connection Manager, add a connection to your
Linux box:
After connection over SSH is established, create an Empty project (Linux) template:
You can then add a new C source file and replace it with this content. Using the ODBC APIs SQLAllocHandle,
SQLSetConnectAttr, and SQLDriverConnect, you should be able to initialize and establish a connection to your
database. Like with the Windows ODBC sample, you need to replace the SQLDriverConnect call with the details
from your database connection string parameters copied from the Azure portal previously.
retcode = SQLDriverConnect(
hdbc, NULL, "Driver=ODBC Driver 13 for SQL"
"Server;Server=<yourserver>;Uid=<yourusername>;Pwd=<"
"yourpassword>;database=<yourdatabase>",
SQL_NTS, outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_NOPROMPT);
To launch your application, bring up the Linux Console from the Debug menu:
If your connection was successful, you should now see the current database name printed in the Linux Console:
Congratulations! You have successfully completed the tutorial and can now connect to your Azure SQL DB from
C++ on Windows and Linux platforms.
Next steps
Review the SQL Database Development Overview
More information on the ODBC API Reference
Additional resources
Design Patterns for Multi-tenant SaaS Applications with Azure SQL Database
Explore all the capabilities of SQL Database
Connect Excel to an Azure SQL database and create a
report
4/14/2017 • 3 min to read • Edit Online
Connect Excel to a SQL database in the cloud and import data and create tables and charts based on values in the
database. In this tutorial you will set up the connection between Excel and a database table, save the file that stores
data and the connection information for Excel, and then create a pivot chart from the database values.
You'll need a SQL database in Azure before you get started. If you don't have one, see Create your first SQL
database to get a database with sample data up and running in a few minutes. In this article, you'll import sample
data into Excel from that article, but you can follow similar steps with your own data.
You'll also need a copy of Excel. This article uses Microsoft Excel 2016.
5. In the Select Database and Table dialog, select the database you want to work with from the list, and then
click the tables or views you want to work with (we chose vGetAllCategories), and then click Next.
The Save Data Connection File and Finish dialog box opens, where you provide information about the
Office database connection (*.odc) file that Excel uses. You can leave the defaults or customize your
selections.
6. You can leave the defaults, but note the File Name in particular. A Description, a Friendly Name, and
Search Keywords help you and other users remember what you're connecting to and find the connection.
Click Always attempt to use this file to refresh data if you want connection information stored in the odc
file so it can update when you connect to it, and then click Finish.
Next steps
Learn how to Connect to SQL Database with SQL Server Management Studio for advanced querying and
analysis.
Learn about the benefits of elastic pools.
Learn how to create a web application that connects to SQL Database on the back-end.
Troubleshoot, diagnose, and prevent SQL connection
errors and transient errors for SQL Database
4/10/2017 • 15 min to read • Edit Online
This article describes how to prevent, troubleshoot, diagnose, and mitigate connection errors and transient errors
that your client application encounters when it interacts with Azure SQL Database. Learn how to configure retry
logic, build the connection string, and adjust other connection settings.
One way you can test your retry logic is to disconnect your client computer from the network while the program is
running. The error will be:
SqlException.Number = 11001
Message: "No such host is known"
As part of the first retry attempt, your program can correct the misspelling, and then attempt to connect.
To make this practical, you unplug your computer from the network before you start your program. Then your
program recognizes a run time parameter that causes the program to:
1. Temporarily add 11001 to its list of errors to consider as transient.
2. Attempt its first connection as usual.
3. After the error is caught, remove 11001 from the list.
4. Display a message telling the user to plug the computer into the network.
Pause further execution by using either the Console.ReadLine method or a dialog with an OK button.
The user presses the Enter key after the computer plugged into the network.
5. Attempt again to connect, expecting success.
Te st b y m i ssp e l l i n g t h e d a t a b a se n a m e w h e n c o n n e c t i n g
Your program can purposely misspell the user name before the first connection attempt. The error will be:
SqlException.Number = 18456
Message: "Login failed for user 'WRONG_MyUserName'."
As part of the first retry attempt, your program can correct the misspelling, and then attempt to connect.
To make this practical, your program could recognize a run time parameter that causes the program to:
1. Temporarily add 18456 to its list of errors to consider as transient.
2. Purposely add 'WRONG_' to the user name.
3. After the error is caught, remove 18456 from the list.
4. Remove 'WRONG_' from the user name.
5. Attempt again to connect, expecting success.
.NET SqlConnection parameters for connection retry
If your client program connects to to Azure SQL Database by using the .NET Framework class
System.Data.SqlClient.SqlConnection, you should use .NET 4.6.1 or later (or .NET Core) so you can leverage its
connection retry feature. Details of the feature are here.
When you build the connection string for your SqlConnection object, you should coordinate the values among
the following parameters:
ConnectRetryCount (Default is 1. Range is 0 through 255.)
ConnectRetryInterval (Default is 1 second. Range is 1 through 60.)
Connection Timeout (Default is 15 seconds. Range is 0 through 2147483647)
Specifically, your chosen values should make the following equality true:
Connection Timeout = ConnectRetryCount * ConnectionRetryInterval
For example, if the count = 3, and interval = 10 seconds, a timeout of only 29 seconds would not quite give the
system enough time for its 3rd and final retry at connecting: 29 < 3 * 10.
Connection versus command
The ConnectRetryCount and ConnectRetryInterval parameters let your SqlConnection object retry the
connect operation without telling or bothering your program, such as returning control to your program. The
retries can occur in the following situations:
mySqlConnection.Open method call
mySqlConnection.Execute method call
There is a subtlety. If a transient error occurs while your query is being executed, your SqlConnection object does
not retry the connect operation, and it certainly does not retry your query. However, SqlConnection very quickly
checks the connection before sending your query for execution. If the quick check detects a connection problem,
SqlConnection retries the connect operation. If the retry succeeds, you query is sent for execution.
Should ConnectRetryCount be combined with application retry logic?
Suppose your application has robust custom retry logic. It might retry the connect operation 4 times. If you add
ConnectRetryInterval and ConnectRetryCount =3 to your connection string, you will increase the retry count to
4 * 3 = 12 retries. You might not intend such a high number of retries.
7. In one format or another, paste the connection string information into your client program code.
For more information, see:
Connection Strings and Configuration Files.
Connection: IP address
You must configure the SQL Database server to accept communication from the IP address of the computer that
hosts your client program. You do this by editing the firewall settings through the Azure Portal.
If you forget to configure the IP address, your program will fail with a handy error message that states the
necessary IP address.
1. Log in to the Azure portal at http://portal.azure.com/.
2. In the left banner, click BROWSE ALL. The Browse blade is displayed.
3. Scroll and click SQL servers. The SQL servers blade is displayed.
4. For convenience, click the minimize control on the earlier Browse blade.
5. In the filter text box, start typing the name of your server. Your row is displayed.
6. Click the row for your server. A blade for your server is displayed.
7. On your server blade, click Settings. The Settings blade is displayed.
8. Click Firewall. The Firewall Settings blade is displayed.
9. Click Add Client IP. Type in a name for your new rule into the first text box.
10. Type in the low and high IP address values for the range you want to enable.
It can be handy to have the low value end with .0 and the high with .255.
11. Click Save.
For more information, see: How to: Configure firewall settings on SQL Database
Connection: Ports
Typically you only need to ensure that port 1433 is open for outbound communication, on the computer that hosts
you client program.
For example, when your client program is hosted on a Windows computer, the Windows Firewall on the host
enables you to open port 1433:
1. Open the Control Panel
2. > All Control Panel Items
3. > Windows Firewall
4. > Advanced Settings
5. > Outbound Rules
6. > Actions
7. > New Rule
If your client program is hosted on an Azure virtual machine (VM), you should read:
Ports beyond 1433 for ADO.NET 4.5 and SQL Database.
For background information about cofiguration of ports and IP address, see: Azure SQL Database firewall
Connection: ADO.NET 4.6.1
If your program uses ADO.NET classes like System.Data.SqlClient.SqlConnection to connect to Azure SQL
Database, we recommend that you use .NET Framework version 4.6.1 or higher.
ADO.NET 4.6.1:
For Azure SQL Database, there is improved reliability when you open a connection by using the
SqlConnection.Open method. The Open method now incorporates best effort retry mechanisms in response
to transient faults, for certain errors within the Connection Timeout period.
Supports connection pooling. This includes an efficient verification that the connection object it gives your
program is functioning.
When you use a connection object from a connection pool, we recommend that your program temporarily close
the connection when not immediately using it. Re-opening a connection is not expensive the way creating a new
connection is.
If you are using ADO.NET 4.0 or earlier, we recommend that you upgrade to the latest ADO.NET.
As of November 2015, you can download ADO.NET 4.6.1.
Diagnostics
Diagnostics: Test whether utilities can connect
If your program is failing to connect to Azure SQL Database, one diagnostic option is to try to connect with a utility
program. Ideally the utility would connect by using the same library that your program uses.
On any Windows computer, you can try these utilities:
SQL Server Management Studio (ssms.exe), which connects by using ADO.NET.
sqlcmd.exe, which connects by using ODBC.
Once connected, test whether a short SQL SELECT query works.
Diagnostics: Check the open ports
Suppose you suspect that connection attempts are failing due to port issues. On your computer you can run a
utility that reports on the port configurations.
On Linux the following utilities might be helpful:
netstat -nap
nmap -sS -O 127.0.0.1
(Change the example value to be your IP address.)
On Windows the PortQry.exe utility might be helpful. Here is an example execution that queried the port situation
on an Azure SQL Database server, and which was run on a laptop computer:
[C:\Users\johndoe\]
>> portqry.exe -n johndoesvr9.database.windows.net -p tcp -e 1433
querying...
TCP port 1433 (ms-sql-s service): LISTENING
[C:\Users\johndoe\]
>>
SELECT
object_name
,CAST(f.event_data as XML).value
('(/event/@timestamp)[1]', 'datetime2') AS [timestamp]
,CAST(f.event_data as XML).value
('(/event/data[@name="error"]/value)[1]', 'int') AS [error]
,CAST(f.event_data as XML).value
('(/event/data[@name="state"]/value)[1]', 'int') AS [state]
,CAST(f.event_data as XML).value
('(/event/data[@name="is_success"]/value)[1]', 'bit') AS [is_success]
,CAST(f.event_data as XML).value
('(/event/data[@name="database_name"]/value)[1]', 'sysname') AS [database_name]
FROM
sys.fn_xe_telemetry_blob_target_read_file('el', null, null, null) AS f
WHERE
object_name != 'login_event' -- Login events are numerous.
and
'2015-06-21' < CAST(f.event_data as XML).value
('(/event/@timestamp)[1]', 'datetime2')
ORDER BY
[timestamp] DESC
;
Enterprise Library 6
Enterprise Library 6 (EntLib60) is a framework of .NET classes that helps you implement robust clients of cloud
services, one of which is the Azure SQL Database service. You can locate topics dedicated to each area in which
EntLib60 can assist by first visiting:
Enterprise Library 6 - April 2013
Retry logic for handling transient errors is one area in which EntLib60 can assist:
4 - Perseverance, Secret of All Triumphs: Using the Transient Fault Handling Application Block
NOTE
The source code for EntLib60 is available for public download. Microsoft has no plans to make further feature updates or
maintenance updates to EntLib.
return true;
case 10928:
case 10929:
case 10053:
case 10054:
case 10060:
case 40197:
case 40540:
case 40613:
case 40143:
case 233:
case 64:
// DBNETLIB Error Code: 20
// The instance of SQL Server you attempted to connect to
// does not support encryption.
case (int)ProcessNetLibErrorCode.EncryptionNotSupported:
return true;
}
}
}
else if (ex is TimeoutException)
{
return true;
}
else
{
EntityException entityException;
if ((entityException = ex as EntityException) != null)
{
return this.IsTransient(entityException.InnerException);
}
}
}
return false;
}
Next steps
For troubleshooting other common Azure SQL Database connection issues, visit Troubleshoot connection
issues to Azure SQL Database.
SQL Server Connection Pooling (ADO.NET)
Retrying is an Apache 2.0 licensed general-purpose retrying library, written in Python, to simplify the task of
adding retry behavior to just about anything.
Troubleshoot connection issues to Azure SQL
Database
4/14/2017 • 4 min to read • Edit Online
When the connection to Azure SQL Database fails, you receive error messages. This article is a centralized topic that
helps you troubleshoot Azure SQL Database connectivity issues. It introduces the common causes of connection
issues, recommends a troubleshooting tool that helps you identity the problem, and provides troubleshooting
steps to solve transient errors and persistent or non-transient errors. Finally, it lists all the relevant articles for
Azure SQL Database connectivity issues.
If you encounter the connection issues, try the troubleshoot steps that are described in this article.
If your Azure issue is not addressed in this article, visit the Azure forums on MSDN and the Stack Overflow. You can
post your issue on these forums or to @AzureSupport on Twitter. Also, you can file an Azure support request by
selecting Get support on the Azure support site.
Cause
Connection problems may be caused by any of the following:
Failure to apply best practices and design guidelines during the application design process. See SQL Database
Development Overview to get started.
Azure SQL Database reconfiguration
Firewall settings
Connection time-out
Incorrect login information
Maximum limit reached on some Azure SQL Database resources
Generally, connection issues to Azure SQL Database can be classified as follows:
Transient errors (short-lived or intermittent)
Persistent or non-transient errors (errors that regularly recur)
Error code 40613: "Database <x> on server <y> is not currently available. Please retry the connection later. If the problem persists, contact
customer support, and provide them the session tracing ID of <z>"
NOTE
This error message is typically transient (short-lived).
This error occurs when the Azure database is being moved (or reconfigured) and your application loses its
connection to the SQL database. SQL database reconfiguration events occurs because of a planned event (for
example, a software upgrade) or an unplanned event (for example, a process crash, or load balancing). Most
reconfiguration events are generally short-lived and should be completed in less than 60 seconds at most.
However, these events can occasionally take longer to finish, such as when a large transaction causes a long-
running recovery.
Steps to resolve transient connectivity issues
1. Check the Microsoft Azure Service Dashboard for any known outages that occurred during the time during
which the errors were reported by the application.
2. Applications that connect to a cloud service such as Azure SQL Database should expect periodic reconfiguration
events and implement retry logic to handle these errors instead of surfacing these as application errors to users.
Review the Transient errors section and the best practices and design guidelines at SQL Database Development
Overview for more information and general retry strategies. Then, see code samples at Connection Libraries for
SQL Database and SQL Server for specifics.
3. As a database approaches its resource limits, it can seem to be a transient connectivity issue. See
Troubleshooting Performance Issues.
4. If connectivity problems continue, or if the duration for which your application encounters the error exceeds 60
seconds or if you see multiple occurrences of the error in a given day, file an Azure support request by selecting
Get Support on the Azure Support site.
Next steps
Troubleshoot Azure SQL Database performance issues
Search the documentation on Microsoft Azure
View the latest updates to the Azure SQL Database service
Additional resources
SQL Database Development Overview
General transient fault-handling guidance
Connection libraries for SQL Database and SQL Server
Use C# to create a SQL database with the SQL
Database Library for .NET
4/14/2017 • 5 min to read • Edit Online
Learn how to use C# to create an Azure SQL database with the Microsoft Azure SQL Management Library for .NET.
This article describes how to create a single database with SQL and C#. To create elastic pools, see Create an elastic
pool.
The Azure SQL Database Management Library for .NET provides an Azure Resource Manager-based API that wraps
the Resource Manager-based SQL Database REST API.
NOTE
Many new features of SQL Database are only supported when you are using the Azure Resource Manager deployment
model, so you should always use the latest Azure SQL Database Management Library for .NET (docs | NuGet
Package). The older classic deployment model based libraries are supported for backward compatibility only, so we
recommend you use the newer Resource Manager based libraries.
NOTE
This article creates a new, blank SQL database. Modify the CreateOrUpdateDatabase(...) method in the following sample to
copy databases, scale databases, create a database in a pool, etc. For more information, see DatabaseCreateMode and
DatabaseProperties classes.
using Microsoft.Azure;
using Microsoft.Azure.Management.ResourceManager;
using Microsoft.Azure.Management.ResourceManager.Models;
using Microsoft.Azure.Management.Sql;
using Microsoft.Azure.Management.Sql.Models;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
namespace SqlDbConsoleApp
{
class Program
{
// For details about these four (4) values, see
// https://azure.microsoft.com/documentation/articles/resource-group-authenticate-service-principal/
static string _subscriptionId = "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}";
static string _tenantId = "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}";
static string _applicationId = "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}";
static string _applicationSecret = "{your-password}";
// Create management clients for the Azure resources your app needs to work with.
// This app works with Resource Groups, and Azure SQL Database.
static ResourceManagementClient _resourceMgmtClient;
static SqlManagementClient _sqlMgmtClient;
// Authentication token
static AuthenticationResult _token;
Console.WriteLine("Resource group...");
ResourceGroup rg = CreateOrUpdateResourceGroup(_resourceMgmtClient, _subscriptionId, _resourceGroupName,
_resourceGrouplocation);
Console.WriteLine("Resource group: " + rg.Id);
Console.WriteLine("Server...");
ServerGetResponse sgr = CreateOrUpdateServer(_sqlMgmtClient, _resourceGroupName, _serverlocation, _serverName, _serverAdmin,
_serverAdminPassword);
Console.WriteLine("Server: " + sgr.Server.Id);
Console.WriteLine("Server firewall...");
FirewallRuleGetResponse fwr = CreateOrUpdateFirewallRule(_sqlMgmtClient, _resourceGroupName, _serverName, _firewallRuleName,
_startIpAddress, _endIpAddress);
Console.WriteLine("Server firewall: " + fwr.FirewallRule.Id);
Console.WriteLine("Database...");
DatabaseCreateOrUpdateResponse dbr = CreateOrUpdateDatabase(_sqlMgmtClient, _resourceGroupName, _serverName, _databaseName,
_databaseEdition, _databasePerfLevel);
Console.WriteLine("Database: " + dbr.Database.Id);
# If you have multiple subscriptions, uncomment and set to the subscription you want to work with.
#$subscriptionId = "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
#Set-AzureRmContext -SubscriptionId $subscriptionId
$appName = "{app-name}"
$uri = "http://{app-name}"
$secret = "{app-password}"
# If you still get a PrincipalNotFound error, then rerun the following until successful.
$roleassignment = New-AzureRmRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName
$azureAdApplication.ApplicationId.Guid
Next steps
Now that you've tried SQL Database and set up a database with C#, you're ready for the following articles:
Connect to SQL Database with SQL Server Management Studio and perform a sample T-SQL query
Additional Resources
SQL Database
Database Class
Use In-Memory OLTP to improve your application
performance in SQL Database
4/10/2017 • 4 min to read • Edit Online
In-Memory OLTP can be used to improve the performance of transaction processing, data ingestion, and transient
data scenarios, in Premium Azure SQL Databases without increasing the pricing tier.
NOTE
Learn how Quorum doubles key database’s workload while lowering DTU by 70% with SQL Database
For the TRANSACTION_ISOLATION_LEVEL, SNAPSHOT is the most common value for the natively compiled
stored procedure. However, a subset of the other values are also supported:
REPEATABLE READ
SERIALIZABLE
The LANGUAGE value must be present in the sys.languages view.
How to migrate a stored procedure
The migration steps are:
1. Obtain the CREATE PROCEDURE script to the regular interpreted stored procedure.
2. Rewrite its header to match the previous template.
3. Ascertain whether the stored procedure T-SQL code uses any features that are not supported for natively
compiled stored procedures. Implement workarounds if necessary.
For details see Migration Issues for Natively Compiled Stored Procedures.
4. Rename the old stored procedure by using SP_RENAME. Or simply DROP it.
5. Run your edited CREATE PROCEDURE T-SQL script.
Related links
In-Memory OLTP (In-Memory Optimization)
Introduction to Natively Compiled Stored Procedures
Memory Optimization Advisor
Get started with elastic database tools
4/21/2017 • 3 min to read • Edit Online
This document introduces you to the developer experience by helping you to run the sample app. The
sample creates a simple sharded application and explores key capabilities of elastic database tools. The
sample demonstrates functions of the elastic database client library.
To install the library, go to Microsoft.Azure.SqlDatabase.ElasticScale.Client. The library is installed with the
sample app that's described in the following section.
Prerequisites
Visual Studio 2012 or later with C#. Download a free version at Visual Studio Downloads.
NuGet 2.7 or later. To get the latest version, see Installing NuGet.
IMPORTANT
We recommend that you always use the latest version of Management Studio so that you stay synchronized with
updates to Azure and SQL Database. Update SQL Server Management Studio.
Cost
The elastic database tools are free. When you use elastic database tools, you don't receive any additional
charges on top of the cost of your Azure usage.
For example, the sample application creates new databases. The cost for this depends on the SQL Database
edition you choose and the Azure usage of your application.
For pricing information, see SQL Database pricing details.
Next steps
For more information about elastic database tools, see the following pages:
Elastic database tools documentation map
Code samples:
Elastic DB Tools for Azure SQL - Getting Started
Elastic DB Tools for Azure SQL - Entity Framework Integration
Shard Elasticity on Script Center
Blog: Elastic Scale announcement
Microsoft Virtual Academy: Implementing Scale-Out Using Sharding with the Elastic Database Client
Library Video
Channel 9: Elastic Scale overview video
Discussion forum: Azure SQL Database forum
To measure performance: Performance counters for shard map manager
Deploy a split-merge service
1/17/2017 • 12 min to read • Edit Online
The split-merge tool lets you move data between sharded databases. See Moving data between scaled-out cloud
databases
Prerequisites
1. Create an Azure SQL DB database that will be used as the split-merge status database. Go to the Azure portal.
Create a new SQL Database. Give the database a name and create a new administrator and password. Be sure
to record the name and password for later use.
2. Ensure that your Azure SQL DB server allows Azure Services to connect to it. In the portal, in the Firewall
Settings, ensure that the Allow access to Azure Services setting is set to On. Click the "save" icon.
3. Create an Azure Storage account that will be used for diagnostics output. Go to the Azure Portal. In the left bar,
click New, click Data + Storage, then Storage.
4. Create an Azure Cloud Service that will contain your Split-Merge service. Go to the Azure Portal. In the left bar,
click New, then Compute, Cloud Service, and Create.
IMPORTANT
At this time, the status database must use the Latin collation (SQL_Latin1_General_CP1_CI_AS). For more
information, see Windows Collation Name (Transact-SQL).
With Azure SQL DB, the connection string typically is of the form:
4. Enter this connection string in the cscfg file in both the SplitMergeWeb and SplitMergeWorker role
sections in the ElasticScaleMetadata setting.
5. For the SplitMergeWorker role, enter a valid connection string to Azure storage for the
WorkerRoleSynchronizationStorageAccountConnectionString setting.
Configure security
For detailed instructions to configure the security of the service, refer to the Split-Merge security configuration.
For the purposes of a simple test deployment for this tutorial, a minimal set of configuration steps will be
performed to get the service up and running. These steps enable only the one machine/account executing them to
communicate with the service.
Create a self-signed certificate
Create a new directory and from this directory execute the following command using a Developer Command
Prompt for Visual Studio window:
makecert ^
-n "CN=*.cloudapp.net" ^
-r -cy end -sky exchange -eku "1.3.6.1.5.5.7.3.1,1.3.6.1.5.5.7.3.2" ^
-a sha1 -len 2048 ^
-sr currentuser -ss root ^
-sv MyCert.pvk MyCert.cer
You are asked for a password to protect the private key. Enter a strong password and confirm it. You are then
prompted for the password to be used once more after that. Click Yes at the end to import it to the Trusted
Certification Authorities Root store.
Create a PFX file
Execute the following command from the same window where makecert was executed; use the same password
that you used to create the certificate:
Please note that for production deployments separate certificates should be used for the CA, for encryption, the
Server certificate and client certificates. For detailed instructions on this, see Security Configuration.
5. In the dialog box, enter a deployment label. For both 'Package' and 'Configuration', click 'From Local' and
choose the SplitMergeService.cspkg file and your .cscfg file that you configured earlier.
6. Ensure that the checkbox labeled Deploy even if one or more roles contain a single instance is checked.
7. Hit the tick button in the bottom right to begin the deployment. Expect it to take a few minutes to complete.
Troubleshoot the deployment
If your web role fails to come online, it is likely a problem with the security configuration. Check that the SSL is
configured as described above.
If your worker role fails to come online, but your web role succeeds, it is most likely a problem connecting to the
status database that you created earlier.
Make sure that the connection string in your .cscfg is accurate.
Check that the server and database exist, and that the user id and password are correct.
For Azure SQL DB, the connection string should be of the form:
Ensure that the server name does not begin with https://.
Ensure that your Azure SQL DB server allows Azure Services to connect to it. To do this, open
https://manage.windowsazure.com, click “SQL Databases” on the left, click “Servers” at the top, and select your
server. Click Configure at the top and ensure that the Azure Services setting is set to “Yes”. (See the
Prerequisites section at the top of this article).
2. Polls the web frontend for the split request status and
waits until the request completes.
NOTE
The SetupSampleSplitMergeEnvironment.ps1 script creates all these databases on the same server by default to
keep the script simple. This is not a restriction of the Split-Merge Service itself.
A SQL authentication login with read/write access to the DBs will be needed for the Split-Merge service to
move data and update the shard map. Since the Split-Merge Service runs in the cloud, it does not currently
support Integrated Authentication.
Make sure the Azure SQL server is configured to allow access from the IP address of the machine running
these scripts. You can find this setting under the Azure SQL server / configuration / allowed IP addresses.
3. Execute the SetupSampleSplitMergeEnvironment.ps1 script to create the sample environment.
Running this script will wipe out any existing shard map management data structures on the shard map
manager database and the shards. It may be useful to rerun the script if you wish to re-initialize the shard
map or shards.
Sample command line:
.\SetupSampleSplitMergeEnvironment.ps1
-UserName 'mysqluser'
-Password 'MySqlPassw0rd'
-ShardMapManagerServerName 'abcdefghij.database.windows.net'
4. Execute the Getmappings.ps1 script to view the mappings that currently exist in the sample environment.
.\GetMappings.ps1
-UserName 'mysqluser'
-Password 'MySqlPassw0rd'
-ShardMapManagerServerName 'abcdefghij.database.windows.net'
5. Execute the ExecuteSampleSplitMerge.ps1 script to execute a split operation (moving half the data on the
first shard to the second shard) and then a merge operation (moving the data back onto the first shard). If
you configured SSL and left the http endpoint disabled, ensure that you use the https:// endpoint instead.
Sample command line:
.\ExecuteSampleSplitMerge.ps1
-UserName 'mysqluser'
-Password 'MySqlPassw0rd'
-ShardMapManagerServerName 'abcdefghij.database.windows.net'
-SplitMergeServiceEndpoint 'https://mysplitmergeservice.cloudapp.net'
-CertificateThumbprint '0123456789abcdef0123456789abcdef01234567'
If you receive the below error, it is most likely a problem with your Web endpoint’s certificate. Try
connecting to the Web endpoint with your favorite Web browser and check if there is a certificate error.
Invoke-WebRequest : The underlying connection was closed: Could not establish trust relationship for the SSL/TLSsecure channel.
6. Experiment with other data types! All of these scripts take an optional -ShardKeyType parameter that allows
you to specify the key type. The default is Int32, but you can also specify Int64, Guid, or Binary.
Create requests
The service can be used either by using the web UI or by importing and using the SplitMerge.psm1 PowerShell
module which will submit your requests through the web role.
The service can move data in both sharded tables and reference tables. A sharded table has a sharding key column
and has different row data on each shard. A reference table is not sharded so it contains the same row data on
every shard. Reference tables are useful for data that does not change often and is used to JOIN with sharded
tables in queries.
In order to perform a split-merge operation, you must declare the sharded tables and reference tables that you
want to have moved. This is accomplished with the SchemaInfo API. This API is in the
Microsoft.Azure.SqlDatabase.ElasticScale.ShardManagement.Schema namespace.
1. For each sharded table, create a ShardedTableInfo object describing the table’s parent schema name
(optional, defaults to “dbo”), the table name, and the column name in that table that contains the sharding key.
2. For each reference table, create a ReferenceTableInfo object describing the table’s parent schema name
(optional, defaults to “dbo”) and the table name.
3. Add the above TableInfo objects to a new SchemaInfo object.
4. Get a reference to a ShardMapManager object, and call GetSchemaInfoCollection.
5. Add the SchemaInfo to the SchemaInfoCollection, providing the shard map name.
An example of this can be seen in the SetupSampleSplitMergeEnvironment.ps1 script.
The Split-Merge service does not create the target database (or schema for any tables in the database) for you.
They must be pre-created before sending a request to the service.
Troubleshooting
You may see the below message when running the sample powershell scripts:
Invoke-WebRequest : The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
This error means that your SSL certificate is not configured correctly. Please follow the instructions in section
'Connecting with a web browser'.
If you cannot submit requests you may see this:
In this case, check your configuration file, in particular the setting for
WorkerRoleSynchronizationStorageAccountConnectionString. This error typically indicates that the worker
role could not successfully initialize the metadata database on first use.
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For questions,
please reach out to us on the SQL Database forum and for feature requests, please add them to the SQL Database
feedback forum.
Split-merge security configuration
1/17/2017 • 12 min to read • Edit Online
To use the Split/Merge service, you must correctly configure security. The service is part of the Elastic Scale feature
of Microsoft Azure SQL Database. For more information, see Elastic Scale Split and Merge Service Tutorial.
Configuring certificates
Certificates are configured in two ways.
1. To Configure the SSL Certificate
2. To Configure Client Certificates
To obtain certificates
Certificates can be obtained from public Certificate Authorities (CAs) or from the Windows Certificate Service.
These are the preferred methods to obtain certificates.
If those options are not available, you can generate self-signed certificates.
%ProgramFiles(x86)%\Windows Kits\x.y\bin\x86
Get the WDK from Windows 8.1: Download kits and tools
Allowed IP addresses
Access to the service endpoints can be restricted to specific ranges of IP addresses.
<EndpointAcls>
<EndpointAcl role="SplitMergeWeb" endPoint="HttpIn" accessControl="DenyAll" />
<EndpointAcl role="SplitMergeWeb" endPoint="HttpsIn" accessControl="AllowAll" />
</EndpointAcls>
The rules in an access control group are configured in a section of the service configuration file.
The format is explained in Network Access Control Lists documentation. For example, to allow only IPs in the
range 100.100.0.0 to 100.100.255.255 to access the HTTPS endpoint, the rules would look like this:
<AccessControl name="Retricted">
<Rule action="permit" description="Some" order="1" remoteSubnet="100.100.0.0/16"/>
<Rule action="deny" description="None" order="2" remoteSubnet="0.0.0.0/0" />
</AccessControl>
<EndpointAcls>
<EndpointAcl role="SplitMergeWeb" endPoint="HttpsIn" accessControl="Restricted" />
Refer to the documentation for Dynamic IP Security in IIS for other supported values.
makecert ^
-n "CN=myservice.cloudapp.net" ^
-e MM/DD/YYYY ^
-r -cy end -sky exchange -eku "1.3.6.1.5.5.7.3.1" ^
-a sha1 -len 2048 ^
-sv MySSL.pvk MySSL.cer
To customize:
-n with the service URL. Wildcards ("CN=*.cloudapp.net") and alternative names
("CN=myservice1.cloudapp.net, CN=myservice2.cloudapp.net") are supported.
-e with the certificate expiration date Create a strong password and specify it when prompted.
Then, copy the same thumbprint as the SSL certificate in the CA certificate setting:
makecert ^
-n "CN=MyCA" ^
-e MM/DD/YYYY ^
-r -cy authority -h 1 ^
-a sha1 -len 2048 ^
-sr localmachine -ss my ^
MyCA.cer
To customize it
-e with the certification expiration date
Find CA public key
All client certificates must have been issued by a Certification Authority trusted by the service. Find the public key
to the Certification Authority that issued the client certificates that are going to be used for authentication in order
to upload it to the cloud service.
If the file with the public key is not available, export it from the certificate store:
Find certificate
Search for a client certificate issued by the same Certification Authority
Double-click the certificate.
Select the Certification Path tab in the Certificate dialog.
Double-click the CA entry in the path.
Take notes of the certificate properties.
Close the Certificate dialog.
Find certificate
Search for the CA noted above.
Click Actions -> All tasks -> Export…
Export certificate into a .CER with these options:
No, do not export the private key
Include all certificates in the certification path if possible.
Export all extended properties.
Update the value of the following setting with the same thumbprint:
Customizing:
-n with an ID for to the client that will be authenticated with this certificate
-e with the certificate expiration date
MyID.pvk and MyID.cer with unique filenames for this client certificate
This command will prompt for a password to be created and then used once. Use a strong password.
Customizing:
MyID.pvk and MyID.cer with the filename for the client certificate
Customizing:
MyID.pvk and MyID.cer with the filename for the encryption certificate
Find certificate
Follow these steps:
1. Run mmc.exe.
2. File -> Add/Remove Snap-in…
3. Select Certificates.
4. Click Add.
5. Choose the certificate store location.
6. Click Finish.
7. Click OK.
8. Expand Certificates.
9. Expand the certificate store node.
10. Expand the Certificate child node.
11. Select a certificate in the list.
Export certificate
In the Certificate Export Wizard:
1. Click Next.
2. Select Yes, then Export the private key.
3. Click Next.
4. Select the desired output file format.
5. Check the desired options.
6. Check Password.
7. Enter a strong password and confirm it.
8. Click Next.
9. Type or browse a filename where to store the certificate (use a .PFX extension).
10. Click Next.
11. Click Finish.
12. Click OK.
Import certificate
In the Certificate Import Wizard:
1. Select the store location.
Select Current User if only processes running under current user will access the service
Select Local Machine if other processes in this computer will access the service
2. Click Next.
3. If importing from a file, confirm the file path.
4. If importing a .PFX file:
a. Enter the password protecting the private key
b. Select import options
5. Select "Place" certificates in the following store
6. Click Browse.
7. Select the desired store.
8. Click Finish.
If the Trusted Root Certification Authority store was chosen, click Yes.
9. Click OK on all dialog windows.
Upload certificate
In the Azure Portal
1. Select Cloud Services.
2. Select the cloud service.
3. On the top menu, click Certificates.
4. On the bottom bar, click Upload.
5. Select the certificate file.
6. If it is a .PFX file, enter the password for the private key.
7. Once completed, copy the certificate thumbprint from the new entry in the list.
Credentials stored in this database are encrypted. However, as a best practice, ensure that both web and worker
roles of your service deployments are kept up to date and secure as they both have access to the metadata
database and the certificate used for encryption and decryption of stored credentials.
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For questions,
please reach out to us on the SQL Database forum and for feature requests, please add them to the SQL Database
feedback forum.
Adding a shard using Elastic Database tools
1/17/2017 • 2 min to read • Edit Online
// sm is a RangeShardMap object.
// Add a new shard to hold the range being added.
Shard shard2 = null;
As an alternative, you can use Powershell to create a new Shard Map Manager. An example is available here.
sm.SplitMapping(sm.GetMappingForKey(25), 25);
Important: Use this technique only if you are certain that the range for the updated mapping is empty. The
methods above do not check data for the range being moved, so it is best to include checks in your code. If rows
exist in the range being moved, the actual data distribution will not match the updated shard map. Use the split-
merge tool to perform the operation instead in these cases.
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For questions,
please reach out to us on the SQL Database forum and for feature requests, please add them to the SQL Database
feedback forum.
Using the RecoveryManager class to fix shard map
problems
4/14/2017 • 8 min to read • Edit Online
The RecoveryManager class provides ADO.Net applications the ability to easily detect and correct any
inconsistencies between the global shard map (GSM) and the local shard map (LSM) in a sharded database
environment.
The GSM and LSM track the mapping of each database in a sharded environment. Occasionally, a break occurs
between the GSM and the LSM. In that case, use the RecoveryManager class to detect and repair the break.
The RecoveryManager class is part of the Elastic Database client library.
For term definitions, see Elastic Database tools glossary. To understand how the ShardMapManager is used to
manage data in a sharded solution, see Shard map management.
In this example, the RecoveryManager is initialized from the ShardMapManager. The ShardMapManager
containing a ShardMap is also already initialized.
Since this application code manipulates the shard map itself, the credentials used in the factory method (in the
preceding example, smmConnectionString) should be credentials that have read-write permissions on the GSM
database referenced by the connection string. These credentials are typically different from credentials used to
open connections for data-dependent routing. For more information, see Using credentials in the elastic database
client.
rm.DetachShard(s.Location, customerMap);
The shard map reflects the shard location in the GSM before the deletion of the shard. Because the shard was
deleted, it is assumed this was intentional, and the sharding key range is no longer in use. If not, you can execute
point-in time restore. to recover the shard from an earlier point-in-time. (In that case, review the following section
to detect shard inconsistencies.) To recover, see Point in time recovery.
Since it is assumed the database deletion was intentional, the final administrative cleanup action is to delete the
entry to the shard in the shard map manager. This prevents the application from inadvertently writing information
to a range that is not expected.
rm.DetectMappingDifferences(location, shardMapName);
The RecoveryToken parameter enumerates the differences in the mappings between the GSM and the LSM for
the specific shard.
The MappingDifferenceResolution enumeration is used to indicate the method for resolving the difference
between the shard mappings.
MappingDifferenceResolution.KeepShardMapping is recommended that when the LSM contains the
accurate mapping and therefore the mapping in the shard should be used. This is typically the case If there is a
failover: the shard now resides on a new server. Since the shard must first be removed from the GSM (using the
RecoveryManager.DetachShard method), a mapping no longer exists on the GSM. Therefore, the LSM must be
used to re-establish the shard mapping.
rm.AttachShard(location, shardMapName)
The location parameter is the server name and database name, of the shard being attached.
The shardMapName parameter is the shard map name. This is only required when multiple shard maps are
managed by the same shard map manager. Optional.
This example adds a shard to the shard map that has been recently restored from an earlier point-in time. Since the
shard (namely the mapping for the shard in the LSM) has been restored, it is potentially inconsistent with the shard
entry in the GSM. Outside of this example code, the shard was restored and renamed to the original name of the
database. Since it was restored, it is assumed the mapping in the LSM is the trusted mapping.
rm.AttachShard(s.Location, customerMap);
var gs = rm.DetectMappingDifferences(s.Location);
foreach (RecoveryToken g in gs)
{
rm.ResolveMappingDifferences(g, MappingDifferenceResolution.KeepShardMapping);
}
Best practices
Geo-failover and recovery are operations typically managed by a cloud administrator of the application
intentionally utilizing one of Azure SQL Databases business continuity features. Business continuity planning
requires processes, procedures, and measures to ensure that business operations can continue without
interruption. The methods available as part of the RecoveryManager class should be used within this work flow to
ensure the GSM and LSM are kept up-to-date based on the recovery action taken. There are five basic steps to
properly ensuring the GSM and LSM reflect the accurate information after a failover event. The application code to
execute these steps can be integrated into existing tools and workflow.
1. Retrieve the RecoveryManager from the ShardMapManager.
2. Detach the old shard from the shard map.
3. Attach the new shard to the shard map, including the new shard location.
4. Detect inconsistencies in the mapping between the GSM and LSM.
5. Resolve differences between the GSM and the LSM, trusting the LSM.
This example performs the following steps:
1. Removes shards from the Shard Map that reflect shard locations before the failover event.
2. Attaches shards to the Shard Map reflecting the new shard locations (the parameter
"Configuration.SecondaryServer" is the new server name but the same database name).
3. Retrieves the recovery tokens by detecting mapping differences between the GSM and the LSM for each shard.
4. Resolves the inconsistencies by trusting the mapping from the LSM of each shard.
{
ShardLocation slNew = new ShardLocation(Configuration.SecondaryServer, s.Location.Database);
rm.DetachShard(s.Location);
rm.AttachShard(slNew);
var gs = rm.DetectMappingDifferences(slNew);
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For questions,
please reach out to us on the SQL Database forum and for feature requests, please add them to the SQL Database
feedback forum.
Migrate existing databases to scale-out
1/17/2017 • 4 min to read • Edit Online
Easily manage your existing scaled-out sharded databases using Azure SQL Database database tools (such as the
Elastic Database client library). You must first convert an existing set of databases to use the shard map manager.
Overview
To migrate an existing sharded database:
1. Prepare the shard map manager database.
2. Create the shard map.
3. Prepare the individual shards.
4. Add mappings to the shard map.
These techniques can be implemented using either the .NET Framework client library, or the PowerShell scripts
found at Azure SQL DB - Elastic Database tools scripts. The examples here use the PowerShell scripts.
For more information about the ShardMapManager, see Shard map management. For an overview of the elastic
database tools, see Elastic Database features overview.
The multi-tenant model assigns several tenants to a single database (and you can distribute groups of tenants
across multiple databases). Use this model when you expect each tenant to have small data needs. In this model,
we assign a range of tenants to a database using range mapping.
Or you can implement a multi-tenant database model using a list mapping to assign multiple tenants to a single
database. For example, DB1 is used to store information about tenant id 1 and 5, and DB2 stores data for tenant 7
and tenant 10.
Based on your choice, choose one of these options:
Option 1: create a shard map for a list mapping
Create a shard map using the ShardMapManager object.
Add-Shard
-ShardMap $ShardMap
-SqlServerName '<shard_server_name>'
-SqlDatabaseName '<shard_database_name>'
# The $ShardMap is the shard map created in step 2.
Step 4 option 3: map the data for multiple tenants on a single database
For each tenant, run the Add-ListMapping (option 1, above).
Summary
Once you have completed the setup, you can begin to use the Elastic Database client library. You can also use data
dependent routing and multi-shard query.
Next steps
Get the PowerShell scripts from Azure SQL DB-Elastic Database tools sripts.
The tools are also on GitHub: Azure/elastic-db-tools.
Use the split-merge tool to move data to or from a multi-tenant model to a single tenant model. See Split merge
tool.
Additional resources
For information on common data architecture patterns of multi-tenant software-as-a-service (SaaS) database
applications, see Design Patterns for Multi-tenant SaaS Applications with Azure SQL Database.
Questions and Feature Requests
For questions, please reach out to us on the SQL Database forum and for feature requests, please add them to the
SQL Database feedback forum.
Performance counters for shard map manager
2/2/2017 • 2 min to read • Edit Online
You can capture the performance of a shard map manager, especially when using data dependent routing.
Counters are created with methods of the Microsoft.Azure.SqlDatabase.ElasticScale.Client class.
Counters are used to track the performance of data dependent routing operations. These counters are accessible in
the Performance Monitor, under the "Elastic Database: Shard Management" category.
For the latest version: Go to Microsoft.Azure.SqlDatabase.ElasticScale.Client. See also Upgrade an app to use the
latest elastic database client library.
Prerequisites
To create the performance category and counters, the user must be a part of the local Administrators group on
the machine hosting the application.
To create a performance counter instance and update the counters, the user must be a member of either the
Administrators or Performance Monitor Users group.
ShardMapManagerFactory.CreatePerformanceCategoryAndCounters()
You can also use this PowerShell script to execute the method. The method creates the following performance
counters:
Cached mappings: Number of mappings cached for the shard map.
DDR operations/sec: Rate of data dependent routing operations for the shard map. This counter is updated
when a call to OpenConnectionForKey() results in a successful connection to the destination shard.
Mapping lookup cache hits/sec: Rate of successful cache lookup operations for mappings in the shard map.
Mapping lookup cache misses/sec: Rate of failed cache lookup operations for mappings in the shard map.
Mappings added or updated in cache/sec: Rate at which mappings are being added or updated in cache for
the shard map.
Mappings removed from cache/sec: Rate at which mappings are being removed from cache for the shard
map.
Performance counters are created for each cached shard map per process.
Notes
The following events trigger the creation of the performance counters:
Initialization of the ShardMapManager with eager loading, if the ShardMapManager contains any shard maps.
These include the GetSqlShardMapManager and the TryGetSqlShardMapManager methods.
Successful lookup of a shard map (using GetShardMap(), GetListShardMap() or GetRangeShardMap()).
Successful creation of shard map using CreateShardMap().
The performance counters will be updated by all cache operations performed on the shard map and mappings.
Successful removal of the shard map using DeleteShardMap()reults in deletion of the performance counters
instance.
Best practices
Creation of the performance category and counters should be performed only once before the creation of
ShardMapManager object. Every execution of the command CreatePerformanceCategoryAndCounters() clears
the previous counters (losing data reported by all instances) and creates new ones.
Performance counter instances are created per process. Any application crash or removal of a shard map from
the cache will result in deletion of the performance counters instances.
See also
Elastic Database features overview
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For questions,
please reach out to us on the SQL Database forum and for feature requests, please add them to the SQL Database
feedback forum.
Elastic Database client library with Entity Framework
3/7/2017 • 16 min to read • Edit Online
This document shows the changes in an Entity Framework application that are needed to integrate with the Elastic
Database tools. The focus is on composing shard map management and data-dependent routing with the Entity
Framework Code First approach. The Code First - New Database tutorial for EF serves as our running example
throughout this document. The sample code accompanying this document is part of elastic database tools' set of
samples in the Visual Studio Code Samples.
Requirements
When working with both the elastic database client library and Entity Framework APIs, we want to retain the
following properties:
Scale-out: To add or remove databases from the data tier of the sharded application as necessary for the
capacity demands of the application. This means control over the the creation and deletion of databases and
using the elastic database shard map manager APIs to manage databases, and mappings of shardlets.
Consistency: The application employs sharding, and uses the data dependent routing capabilities of the client
library. To avoid corruption or wrong query results, connections are brokered through the shard map manager.
This also retains validation and consistency.
Code First: To retain the convenience of EF’s code first paradigm. In Code First, classes in the application are
mapped transparently to the underlying database structures. The application code interacts with DbSets that
mask most aspects involved in the underlying database processing.
Schema: Entity Framework handles initial database schema creation and subsequent schema evolution
through migrations. By retaining these capabilities, adapting your app is easy as the data evolves.
The following guidance instructs how to satisfy these requirements for Code First applications using elastic
database tools.
// C'tor for data dependent routing. This call will open a validated connection
// routed to the proper shard by the shard map manager.
// Note that the base class c'tor call will fail for an open connection
// if migrations need to be done and SQL credentials are used. This is the reason for the
// separation of c'tors into the data-dependent routing case (this c'tor) and the internal c'tor for new shards.
public ElasticScaleContext(ShardMap shardMap, T shardingKey, string connectionStr)
: base(CreateDDRConnection(shardMap, shardingKey, connectionStr),
true /* contextOwnsConnection */)
{
}
// Only static methods are allowed in calls into base class c'tors.
private static DbConnection CreateDDRConnection(
ShardMap shardMap,
T shardingKey,
string connectionStr)
{
// No initialization
Database.SetInitializer<ElasticScaleContext<T>>(null);
// Ask shard map to broker a validated connection for the given key
SqlConnection conn = shardMap.OpenConnectionForKey<T>
(shardingKey, connectionStr, ConnectionOptions.Validate);
return conn;
}
Main points
A new constructor replaces the default constructor in the DbContext subclass
The new constructor takes the arguments that are required for data dependent routing through elastic
database client library:
the shard map to access the data-dependent routing interfaces,
the sharding key to identify the shardlet,
a connection string with the credentials for the data-dependent routing connection to the shard.
The call to the base class constructor takes a detour into a static method that performs all the steps
necessary for data-dependent routing.
It uses the OpenConnectionForKey call of the elastic database client interfaces on the shard map to
establish an open connection.
The shard map creates the open connection to the shard that holds the shardlet for the given sharding
key.
This open connection is passed back to the base class constructor of DbContext to indicate that this
connection is to be used by EF instead of letting EF create a new connection automatically. This way the
connection has been tagged by the elastic database client API so that it can guarantee consistency under
shard map management operations.
Use the new constructor for your DbContext subclass instead of the default constructor in your code. Here is an
example:
The new constructor opens the connection to the shard that holds the data for the shardlet identified by the value
of tenantid1. The code in the using block stays unchanged to access the DbSet for blogs using EF on the shard
for tenantid1. This changes semantics for the code in the using block such that all database operations are now
scoped to the one shard where tenantid1 is kept. For instance, a LINQ query over the blogs DbSet would only
return blogs stored on the current shard, but not the ones stored on other shards.
Transient faults handling
The Microsoft Patterns & Practices team published the The Transient Fault Handling Application Block. The library
is used with elastic scale client library in combination with EF. However, ensure that any transient exception returns
to a place where we can ensure that the new constructor is being used after a transient fault so that any new
connection attempt is made using the constructors we have tweaked. Otherwise, a connection to the correct shard
is not guaranteed, and there are no assurances the connection is maintained as changes to the shard map occur.
The following code sample illustrates how a SQL retry policy can be used around the new DbContext subclass
constructors:
SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
{
using (var db = new ElasticScaleContext<int>(
sharding.ShardMap,
tenantId1,
connStrBldr.ConnectionString))
{
var blog = new Blog { Name = name };
db.Blogs.Add(blog);
db.SaveChanges();
…
}
});
REWRITTEN CONSTRUCTOR
CURRENT CONSTRUCTOR FOR DATA BASE CONSTRUCTOR NOTES
// Enter a new shard - i.e. an empty database - to the shard map, allocate a first tenant to it
// and kick off EF intialization of the database to deploy schema
public void RegisterNewShard(string server, string database, string connStr, int key)
{
// Go into a DbContext to trigger migrations and schema deployment for the new shard.
// This requires an un-opened connection.
using (var db = new ElasticScaleContext<int>(connStrBldr.ConnectionString))
{
// Run a query to engage EF migrations
(from b in db.Blogs
select b).Count();
}
// Register the mapping of the tenant to the shard in the shard map.
// After this step, data-dependent routing on the shard map can be used
this.ShardMap.CreatePointMapping(key, shard);
}
This sample shows the method RegisterNewShard that registers the shard in the shard map, deploys the schema
through EF migrations, and stores a mapping of a sharding key to the shard. It relies on a constructor of the
DbContext subclass (ElasticScaleContext in the sample) that takes a SQL connection string as input. The code of
this constructor is straight-forward, as the following example shows:
// C'tor to deploy schema and migrations to a new shard
protected internal ElasticScaleContext(string connectionString)
: base(SetInitializerForConnection(connectionString))
{
}
// Only static methods are allowed in calls into base class c'tors
private static string SetInitializerForConnection(string connnectionString)
{
// We want existence checks so that the schema can get deployed
Database.SetInitializer<ElasticScaleContext<T>>(
new CreateDatabaseIfNotExists<ElasticScaleContext<T>>());
return connnectionString;
}
One might have used the version of the constructor inherited from the base class. But the code needs to ensure
that the default initializer for EF is used when connecting. Hence the short detour into the static method before
calling into the base class constructor with the connection string. Note that the registration of shards should run in
a different app domain or process to ensure that the initializer settings for EF do not conflict.
Limitations
The approaches outlined in this document entail a couple of limitations:
EF applications that use LocalDb first need to migrate to a regular SQL Server database before using elastic
database client library. Scaling out an application through sharding with Elastic Scale is not possible with
LocalDb. Note that development can still use LocalDb.
Any changes to the application that imply database schema changes need to go through EF migrations on all
shards. The sample code for this document does not demonstrate how to do this. Consider using Update-
Database with a ConnectionString parameter to iterate over all shards; or extract the T-SQL script for the
pending migration using Update-Database with the -Script option and apply the T-SQL script to your shards.
Given a request, it is assumed that all of its database processing is contained within a single shard as identified
by the sharding key provided by the request. However, this assumption does not always hold true. For example,
when it is not possible to make a sharding key available. To address this, the client library provides the
MultiShardQuery class that implements a connection abstraction for querying over several shards. Learning
to use the MultiShardQuery in combination with EF is beyond the scope of this document
Conclusion
Through the steps outlined in this document, EF applications can use the elastic database client library's capability
for data dependent routing by refactoring constructors of the DbContext subclasses used in the EF application.
This limits the changes required to those places where DbContext classes already exist. In addition, EF applications
can continue to benefit from automatic schema deployment by combining the steps that invoke the necessary EF
migrations with the registration of new shards and mappings in the shard map.
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For questions,
please reach out to us on the SQL Database forum and for feature requests, please add them to the SQL Database
feedback forum.
Upgrade an app to use the latest elastic database
client library
3/7/2017 • 3 min to read • Edit Online
New versions of the Elastic Database client library are available through NuGetand the NuGetPackage Manager
interface in Visual Studio. Upgrades contain bug fixes and support for new capabilities of the client library.
For the latest version: Go to Microsoft.Azure.SqlDatabase.ElasticScale.Client.
Rebuild your application with the new library, as well as change your existing Shard Map Manager metadata
stored in your Azure SQL Databases to support new features.
Performing these steps in order ensures that old versions of the client library are no longer present in your
environment when metadata objects are updated, which means that old-version metadata objects won’t be created
after upgrade.
Upgrade steps
1. Upgrade your applications. In Visual Studio, download and reference the latest client library version into all of
your development projects that use the library; then rebuild and deploy.
In your Visual Studio solution, select Tools --> NuGet Package Manager --> Manage NuGet Packages for
Solution.
(Visual Studio 2013) In the left panel, select Updates, and then select the Update button on the package Azure
SQL Database Elastic Scale Client Library that appears in the window.
(Visual Studio 2015) Set the Filter box to Upgrade available. Select the package to update, and click the
Update button.
(Visual Studio 2017) At the top of the dialog, select Updates. Select the package to update, and click the
Update button.
Build and Deploy.
2. Upgrade your scripts. If you are using PowerShell scripts to manage shards, download the new library
version and copy it into the directory from which you execute scripts.
3. Upgrade your split-merge service. If you use the elastic database split-merge tool to reorganize sharded data,
download and deploy the latest version of the tool. Detailed upgrade steps for the Service can be found here.
4. Upgrade your Shard Map Manager databases. Upgrade the metadata supporting your Shard Maps in Azure
SQL Database. There are two ways you can accomplish this, using PowerShell or C#. Both options are shown
below.
Option 1: Upgrade metadata using PowerShell
1. Download the latest command-line utility for NuGet from here and save to a folder.
2. Open a Command Prompt, navigate to the same folder, and issue the command:
nuget install Microsoft.Azure.SqlDatabase.ElasticScale.Client
3. Navigate to the subfolder containing the new client DLL version you have just downloaded, for example:
cd .\Microsoft.Azure.SqlDatabase.ElasticScale.Client.1.0.0\lib\net45
4. Download the elastic database client upgrade scriptlet from the Script Center, and save it into the same folder
containing the DLL.
5. From that folder, run “PowerShell .\upgrade.ps1” from the command prompt and follow the prompts.
Option 2: Upgrade metadata using C#
Alternatively, create a Visual Studio application that opens your ShardMapManager, iterates over all shards, and
performs the metadata upgrade by calling the methods UpgradeLocalStore and UpgradeGlobalStore as in this
example:
ShardMapManager smm =
ShardMapManagerFactory.GetSqlShardMapManager
(connStr, ShardMapManagerLoadPolicy.Lazy);
smm.UpgradeGlobalStore();
These techniques for metadata upgrades can be applied multiple times without harm. For example, if an older
client version inadvertently creates a shard after you have already updated, you can run upgrade again across all
shards to ensure that the latest metadata version is present throughout your infrastructure.
Note: New versions of the client library published to-date continue to work with prior versions of the Shard Map
Manager metadata on Azure SQL DB, and vice-versa. However to take advantage of some of the new features in
the latest client, metadata needs to be upgraded. Note that metadata upgrades will not affect any user-data or
application-specific data, only objects created and used by the Shard Map Manager. And applications continue to
operate through the upgrade sequence described above.
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For questions,
please reach out to us on the SQL Database forum and for feature requests, please add them to the SQL Database
feedback forum.
Installing Elastic Database jobs overview
2/23/2017 • 6 min to read • Edit Online
Elastic Database jobs can be installed via PowerShell or through the Azure Classic Portal.You can gain access to
create and manage jobs using the PowerShell API only if you install the PowerShell package. Additionally, the
PowerShell APIs provide significantly more functionality than the portal at this point in time.
If you have already installed Elastic Database jobs through the Portal from an existing elastic pool, the latest
Powershell preview includes scripts to upgrade your existing installation. It is highly recommended to upgrade
your installation to the latest Elastic Database jobs components in order to take advantage of new functionality
exposed via the PowerShell APIs.
Prerequisites
An Azure subscription. For a free trial, see Free trial.
Azure PowerShell. Install the latest version using the Web Platform Installer. For detailed information, see How
to install and configure Azure PowerShell.
NuGet Command-line Utility is used to install the Elastic Database jobs package. For more information, see
http://docs.nuget.org/docs/start-here/installing-nuget.
The Elastic Database jobs files are placed in the local directory in a folder named
Microsoft.Azure.SqlDatabase.Jobs.x.x.xxxx.x where x.x.xxxx.x reflects the version number. The
PowerShell cmdlets (including required client .dlls) are located in the tools\ElasticDatabaseJobs sub-
directory and the PowerShell scripts to install, upgrade and uninstall also reside in the tools sub-directory.
3. Navigate to the tools sub-directory under the Microsoft.Azure.SqlDatabase.Jobs.x.x.xxx.x folder by typing cd
tools, for example:
PS C:\*Microsoft.Azure.SqlDatabase.Jobs.x.x.xxxx.x*>cd tools
PS C:\*Microsoft.Azure.SqlDatabase.Jobs.x.x.xxxx.x*\tools>Unblock-File .\InstallElasticDatabaseJobsCmdlets.ps1
PS C:\*Microsoft.Azure.SqlDatabase.Jobs.x.x.xxxx.x*\tools>.\InstallElasticDatabaseJobsCmdlets.ps1
PS C:\*Microsoft.Azure.SqlDatabase.Jobs.x.x.xxxx.x*>cd tools
2. Execute the .\InstallElasticDatabaseJobs.ps1 PowerShell script and supply values for its requested variables.
This script will create the components described in Elastic Database jobs components and pricing along
with configuring the Azure Cloud Service to appropriately use the dependent components.
PS C:\*Microsoft.Azure.SqlDatabase.Jobs.x.x.xxxx.x*\tools>Unblock-File .\InstallElasticDatabaseJobs.ps1
PS C:\*Microsoft.Azure.SqlDatabase.Jobs.x.x.xxxx.x*\tools>.\InstallElasticDatabaseJobs.ps1
When you run this command a window opens asking for a user name and password. This is not your Azure
credentials, enter the user name and password that will be the administrator credentials you want to create for the
new server.
The parameters provided on this sample invocation can be modified for your desired settings. The following
provides more information on the behavior of each parameter:
PARAMETER DESCRIPTION
ResourceGroupLocation Provides the Azure location to be used for the newly created
Azure components. This parameter defaults to the Central US
location.
ServiceVmSize Provides the VM size for usage within the Cloud Service. This
parameter defaults to A0. Parameters values of A0/A1/A2/A3
are accepted which cause the worker role to use an
ExtraSmall/Small/Medium/Large size, respectively. Fo more
information on worker role sizes, see Elastic Database jobs
components and pricing.
SqlServerDatabaseSlo Provides the service level objective for a Standard edition. This
parameter defaults to S0. Parameter values of S0/S1/S2/S3
are accepted which cause the Azure SQL Database to use the
respective SLO. For more information on SQL Database SLOs,
see Elastic Database jobs components and pricing.
SqlServerAdministratorUserName Provides the admin user name for the newly created Azure
SQL Database server. When not specified, a PowerShell
credentials window will open to prompt for the credentials.
SqlServerAdministratorPassword Provides the admin password for the newly created Azure
SQL Database server. When not provided, a PowerShell
credentials window will open to prompt for the credentials.
For systems that target having large numbers of jobs running in parallel against a large number of databases, it is
recommended to specify parameters such as: -ServiceWorkerCount 2 -ServiceVmSize A2 -SqlServerDatabaseSlo
S2.
PS C:\*Microsoft.Azure.SqlDatabase.Jobs.dll.x.x.xxx.x*\tools>Unblock-File .\InstallElasticDatabaseJobs.ps1
PS C:\*Microsoft.Azure.SqlDatabase.Jobs.dll.x.x.xxx.x*\tools>.\InstallElasticDatabaseJobs.ps1 -ServiceWorkerCount 2 -ServiceVmSize A2 -
SqlServerDatabaseSlo S2
PS C:\*Microsoft.Azure.SqlDatabase.Jobs.dll.x.x.xxx.x*\tools>Unblock-File .\UpdateElasticDatabaseJobs.ps1
PS C:\*Microsoft.Azure.SqlDatabase.Jobs.dll.x.x.xxx.x*\tools>.\UpdateElasticDatabaseJobs.ps1 -ServiceVmSize A1 -ServiceWorkerCount 2
PARAMETER DESCRIPTION
ResourceGroupName Identifies the Azure resource group name used when the
Elastic Database job components were initially installed. This
parameter defaults to “__ElasticDatabaseJob”. Since it is not
recommended to change this value, you shouldn't have to
specify this parameter.
ServiceVmSize Provides the VM size for usage within the Cloud Service. This
parameter defaults to A0. Parameters values of A0/A1/A2/A3
are accepted which cause the worker role to use an
ExtraSmall/Small/Medium/Large size, respectively. Fo more
information on worker role sizes, see Elastic Database jobs
components and pricing.
5. Type a user name and password for a database admin. As part of the installation, a new Azure SQL
Database server is created. Within this new server, a new database, known as the control database, is
created and used to contain the meta data for Elastic Database jobs. The user name and password created
here are used for the purpose of logging in to the control database. A separate credential is used for script
execution against the databases within the pool.
6. Click the OK button. The components are created for you in a few minutes in a new Resource group. The
new resource group is pinned to the start board, as shown below. Once created, elastic database jobs
(Cloud Service, SQL Database, Service Bus, and Storage) are all created in the group.
7. If you attempt to create or manage a job while elastic database jobs is installing, when providing
Credentials you will see the following message.
If uninstallation is required, delete the resource group. See How to uninstall the Elastic Database job components.
Next steps
Ensure a credential with the appropriate rights for script execution is created on each database in the group, for
more information see Securing your SQL Database. See Creating and managing an Elastic Database jobs to get
started.
Create and manage scaled out Azure SQL Databases
using elastic jobs (preview)
2/16/2017 • 2 min to read • Edit Online
Elastic Database jobs simplify management of groups of databases by executing administrative operations such
as schema changes, credentials management, reference data updates, performance data collection or tenant
(customer) telemetry collection. Elastic Database jobs is currently available through the Azure portal and
PowerShell cmdlets. However, the Azure portal surfaces reduced functionality limited to execution across all
databases in an elastic pool (preview). To access additional features and execution of scripts across a group of
databases including a custom-defined collection or a shard set (created using Elastic Database client library), see
Creating and managing jobs using PowerShell. For more information about jobs, see Elastic Database jobs
overview.
Prerequisites
An Azure subscription. For a free trial, see Free trial.
An elastic pool. See About elastic pools.
Installation of elastic database job service components. See Installing the elastic database job service.
Creating jobs
1. Using the Azure portal, from an existing elastic database job pool, click Create job.
2. Type in the username and password of the database administrator (created at installation of Jobs) for the
jobs control database (metadata storage for jobs).
3. In the Create Job blade, type a name for the job.
4. Type the user name and password to connect to the target databases with sufficient permissions for script
execution to succeed.
5. Paste or type in the T-SQL script.
6. Click Save and then click Run.
Run idempotent jobs
When you run a script against a set of databases, you must be sure that the script is idempotent. That is, the script
must be able to run multiple times, even if it has failed before in an incomplete state. For example, when a script
fails, the job will be automatically retried until it succeeds (within limits, as the retry logic will eventually cease the
retrying). The way to do this is to use the an "IF EXISTS" clause and delete any found instance before creating a
new object. An example is shown here:
Alternatively, use an "IF NOT EXISTS" clause before creating a new instance:
IF NOT EXISTS (SELECT columns.name FROM sys.columns INNER JOIN sys.tables on columns.object_id = tables.object_id WHERE
tables.name = 'TestTable' AND columns.name = 'AdditionalInformation')
BEGIN
The PowerShell APIs for Elastic Database jobs (in preview), let you define a group of databases against which
scripts will execute. This article shows how to create and manage Elastic Database jobs using PowerShell
cmdlets. See Elastic jobs overview.
Prerequisites
An Azure subscription. For a free trial, see Free one-month trial.
A set of databases created with the Elastic Database tools. See Get started with Elastic Database tools.
Azure PowerShell. For detailed information, see How to install and configure Azure PowerShell.
Elastic Database jobs PowerShell package: See Installing Elastic Database jobs
Select your Azure subscription
To select the subscription you need your subscription Id (-SubscriptionId) or subscription name (-
SubscriptionName). If you have multiple subscriptions you can run the Get-AzureRmSubscription cmdlet and
copy the desired subscription information from the result set. Once you have your subscription information, run
the following commandlet to set this subscription as the default, namely the target for creating and managing
jobs:
The PowerShell ISE is recommended for usage to develop and execute PowerShell scripts against the Elastic
Database jobs.
Custom Collection Child Target Database target that is referenced from Add-AzureSqlJobChildTarget
a custom collection.
Remove-AzureSqlJobChildTarget
Use-AzureSqlJobConnection -CurrentAzureSubscription
To update credentials
When passwords change, use the Set-AzureSqlJobCredential cmdlet and set the CredentialName parameter.
$scriptCommandText = "
IF NOT EXISTS (SELECT name FROM sys.tables WHERE name = 'TestTable')
BEGIN
CREATE TABLE TestTable(
TestTableId INT PRIMARY KEY IDENTITY,
InsertionTime DATETIME2
);
END
GO
INSERT INTO TestTable(InsertionTime) VALUES (sysutcdatetime());
GO"
IF NOT EXISTS (SELECT columns.name FROM sys.columns INNER JOIN sys.tables on columns.object_id = tables.object_id WHERE
tables.name = 'TestTable' AND columns.name = 'AdditionalInformation')
BEGIN
ALTER TABLE TestTable
ADD AdditionalInformation NVARCHAR(400);
END
GO
To execute a job
This PowerShell script executes an existing job:
Update the following variable to reflect the desired job name to have executed:
Use the same Get-AzureSqlJobExecution cmdlet with the IncludeChildren parameter to view the state of child
job executions, namely the specific state for each job execution against each database targeted by the job.
Get-AzureSqlJobExecution
Retrieve all top level job executions, including inactive job executions:
Get-AzureSqlJobExecution -IncludeInactive
Retrieve all child job executions of a provided job execution ID, including inactive job executions:
Retrieve all job executions created using a schedule / job combination, including inactive jobs:
Retrieve all jobs targeting a specified shard map, including inactive jobs:
Retrieve all jobs targeting a specified custom collection, including inactive jobs:
Retrieve the list of job task executions within a specific job execution:
Cancel a job
Elastic Database Jobs supports cancellation requests of jobs. If Elastic Database Jobs detects a cancellation request
for a job currently being executed, it will attempt to stop the job.
There are two different ways that Elastic Database Jobs can perform a cancellation:
1. Cancel currently executing tasks: If a cancellation is detected while a task is currently running, a cancellation will
be attempted within the currently executing aspect of the task. For example: If there is a long running query
currently being performed when a cancellation is attempted, there will be an attempt to cancel the query.
2. Canceling task retries: If a cancellation is detected by the control thread before a task is launched for execution,
the control thread will avoid launching the task and declare the request as canceled.
If a job cancellation is requested for a parent job, the cancellation request will be honored for the parent job and
for all of its child jobs.
To submit a cancellation request, use the Stop-AzureSqlJobExecution cmdlet and set the JobExecutionId
parameter.
$dacpacUri = "{Uri}"
$dacpacName = "{Dacpac Name}"
$dacpac = New-AzureSqlJobContent -DacpacUri $dacpacUri -ContentName $dacpacName
Write-Output $dacpac
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For questions,
please reach out to us on the SQL Database forum and for feature requests, please add them to the SQL Database
feedback forum.
Getting started with Elastic Database jobs
4/10/2017 • 13 min to read • Edit Online
Elastic Database jobs (preview) for Azure SQL Database allows you to reliability execute T-SQL scripts that span
multiple databases while automatically retrying and providing eventual completion guarantees. For more
information about the Elastic Database job feature, please see the feature overview page.
This topic extends the sample found in Getting started with Elastic Database tools. When completed, you will:
learn how to create and manage jobs that manage a group of related databases. It is not required to use the
Elastic Scale tools in order to take advantage of the benefits of Elastic jobs.
Prerequisites
Download and run the Getting started with Elastic Database tools sample.
2. In the command window, type "1" and press Enter. This creates the shard map manager, and adds two
shards to the server. Then type "3" and press Enter; repeat this action four times. This inserts sample data
rows in your shards.
3. The Azure Portal should show three new databases:
At this point, we will create a custom database collection that reflects all the databases in the shard map.
This will allow us to create and execute a job that add a new table across shards.
Here we would usually create a shard map target, using the New-AzureSqlJobTarget cmdlet. The shard map
manager database must be set as a database target and then the specific shard map is specified as a target.
Instead, we are going to enumerate all the databases in the server and add the databases to the new custom
collection with the exception of master database.
Creates a custom collection and add all databases in the server to the
custom collection target with the exception of master.
$customCollectionName = "dbs_in_server"
New-AzureSqlJobTarget -CustomCollectionName $customCollectionName
$ResourceGroupName = "ddove_samples"
$ServerName = "samples"
$dbsinserver = Get-AzureRMSqlDatabase -ResourceGroupName $ResourceGroupName -ServerName $ServerName
$dbsinserver | %{
$currentdb = $_.DatabaseName
$ErrorActionPreference = "Stop"
Write-Output ""
Try
{
New-AzureSqlJobTarget -ServerName $ServerName -DatabaseName $currentdb | Write-Output
}
Catch
{
$ErrorMessage = $_.Exception.Message
$ErrorCategory = $_.CategoryInfo.Reason
else
{
throw $_
}
Try
{
if ($currentdb -eq "master")
{
Write-Host $currentdb "will not be added custom collection target" $CustomCollectionName "."
}
else
{
Add-AzureSqlJobChildTarget -CustomCollectionName $CustomCollectionName -ServerName $ServerName -DatabaseName $currentdb
Write-Host $currentdb "was added to" $CustomCollectionName "."
}
}
Catch
{
$ErrorMessage = $_.Exception.Message
$ErrorCategory = $_.CategoryInfo.Reason
else
{
throw $_
}
}
$ErrorActionPreference = "Continue"
}
Retrieve all top level job executions, including inactive job executions:
Get-AzureSqlJobExecution -IncludeInactive
Retrieve all child job executions of a provided job execution ID, including inactive job executions:
Retrieve all job executions created using a schedule / job combination, including inactive jobs:
Retrieve all jobs targeting a specified shard map, including inactive jobs:
Retrieve all jobs targeting a specified custom collection, including inactive jobs:
Retrieve the list of job task executions within a specific job execution:
Cancel a job
Elastic Database Jobs supports jobs cancellation requests. If Elastic Database Jobs detects a cancellation request
for a job currently being executed, it will attempt to stop the job.
There are two different ways that Elastic Database Jobs can perform a cancellation:
1. Canceling Currently Executing Tasks: If a cancellation is detected while a task is currently running, a
cancellation will be attempted within the currently executing aspect of the task. For example: If there is a long
running query currently being performed when a cancellation is attempted, there will be an attempt to cancel
the query.
2. Canceling Task Retries: If a cancellation is detected by the control thread before a task is launched for
execution, the control thread will avoid launching the task and declare the request as canceled.
If a job cancellation is requested for a parent job, the cancellation request will be honored for the parent job and
for all of its child jobs.
To submit a cancellation request, use the Stop-AzureSqlJobExecution cmdlet and set the JobExecutionId
parameter.
4. In the Data Connection Wizard type the server name and login credentials. Then click Next.
5. In the dialog box Select the database that contains the data you want, select the ElasticDBQuery
database.
6. Select the Customers table in the list view and click Next. Then click Finish.
7. In the Import Data form, under Select how you want to view this data in your workbook, select Table
and click OK.
All the rows from Customers table, stored in different shards populate the Excel sheet.
Next steps
You can now use Excel’s data functions. Use the connection string with your server name, database name and
credentials to connect your BI and data integration tools to the elastic query database. Make sure that SQL Server
is supported as a data source for your tool. Refer to the elastic query database and external tables just like any
other SQL Server database and SQL Server tables that you would connect to with your tool.
Cost
There is no additional charge for using the Elastic Database query feature. However, at this time this feature is
available only on premium databases as an end point, but the shards can be of any service tier.
For pricing information see SQL Database Pricing Details.
Additional resources
Not using elastic database tools yet? Check out our Getting Started Guide and Documentation Map. For
questions, please reach out to us on the SQL Database forum and for feature requests, please add them to the
SQL Database feedback forum.
Uninstall Elastic Database jobs components
1/17/2017 • 1 min to read • Edit Online
Elastic Database jobs components can be uninstalled using either the Portal or PowerShell.
$ResourceGroupName = "__ElasticDatabaseJob"
Switch-AzureMode AzureResourceManager
Write-Host "Removing the Azure Resource Group: $ResourceGroupName. This may take a few minutes.”
Remove-AzureResourceGroup -Name $ResourceGroupName -Force
Write-Host "Completed removing the Azure Resource Group: $ResourceGroupName. Elastic database job compoennts are now uninstalled."
Next steps
To re-install Elastic Database jobs, see Installing the Elastic Database job service
For an overview of Elastic Database jobs, see Elastic Database jobs overview.
Report across scaled-out cloud databases (preview)
4/10/2017 • 4 min to read • Edit Online
You can create reports from multiple Azure SQL databases from a single connection point using an elastic query.
The databases must be horizontally partitioned (also known as "sharded").
If you have an existing database, see Migrating existing databases to scaled-out databases.
To understand the SQL objects needed to query, see Query across horizontally partitioned databases.
Prerequisites
Download and run the Getting started with Elastic Database tools sample.
2. In the command window, type "1" and press Enter. This creates the shard map manager, and adds two shards
to the server. Then type "3" and press Enter; repeat the action four times. This inserts sample data rows in your
shards.
3. The Azure portal should show three new databases in your server:
At this point, cross-database queries are supported through the Elastic Database client libraries. For
example, use option 4 in the command window. The results from a multi-shard query are always a UNION
ALL of the results from all shards.
In the next section, we create a sample database endpoint that supports richer querying of the data across
shards.
"username" and "password" should be the same as login information used in step 6 of Download and run
the sample app in Getting started with elastic database tools.
External data sources
To create an external data source, execute the following command on the ElasticDBQuery database:
"CustomerIDShardMap" is the name of the shard map, if you created the shard map and shard map manager
using the elastic database tools sample. However, if you used your custom setup for this sample, then it should be
the shard map name you chose in your application.
External tables
Create an external table that matches the Customers table on the shards by executing the following command on
ElasticDBQuery database:
You will notice that the query aggregates results from all the shards and gives the following output:
4. In the Data Connection Wizard type the server name and login credentials. Then click Next.
5. In the dialog box Select the database that contains the data you want, select the ElasticDBQuery
database.
6. Select the Customers table in the list view and click Next. Then click Finish.
7. In the Import Data form, under Select how you want to view this data in your workbook, select Table
and click OK.
All the rows from Customers table, stored in different shards populate the Excel sheet.
You can now use Excel’s powerful data visualization functions. You can use the connection string with your server
name, database name and credentials to connect your BI and data integration tools to the elastic query database.
Make sure that SQL Server is supported as a data source for your tool. You can refer to the elastic query database
and external tables just like any other SQL Server database and SQL Server tables that you would connect to with
your tool.
Cost
There is no additional charge for using the Elastic Database Query feature.
For pricing information see SQL Database Pricing Details.
Next steps
For an overview of elastic query, see Elastic query overview.
For a vertical partitioning tutorial, see Getting started with cross-database query (vertical partitioning).
For syntax and sample queries for vertically partitioned data, see Querying vertically partitioned data)
For syntax and sample queries for horizontally partitioned data, see Querying horizontally partitioned data)
See sp_execute _remote for a stored procedure that executes a Transact-SQL statement on a single remote
Azure SQL Database or set of databases serving as shards in a horizontal partitioning scheme.
Get started with cross-database queries (vertical
partitioning) (preview)
2/21/2017 • 2 min to read • Edit Online
Elastic database query (preview) for Azure SQL Database allows you to run T-SQL queries that span multiple
databases using a single connection point. This topic applies to vertically partitioned databases.
When completed, you will: learn how to configure and use an Azure SQL Database to perform queries that span
multiple related databases.
For more information about the elastic database query feature, please see Azure SQL Database elastic database
query overview.
Prerequisites
You must possess ALTER ANY EXTERNAL DATA SOURCE permission. This permission is included with the ALTER
DATABASE permission. ALTER ANY EXTERNAL DATA SOURCE permissions are needed to refer to the underlying
data source.
Now, execute following query on the Customers database to create the CustomerInformation table and input
the sample data.
The "username" and "password" should be the username and password used to login into the Customers
database. Authentication using Azure Active Directory with elastic queries is not currently supported.
External data sources
To create an external data source, execute the following command on the Orders database:
External tables
Create an external table on the Orders database, which matches the definition of the CustomerInformation table:
Cost
Currently, the elastic database query feature is included into the cost of your Azure SQL Database.
For pricing information see SQL Database Pricing.
Next steps
For an overview of elastic query, see Elastic query overview.
For syntax and sample queries for vertically partitioned data, see Querying vertically partitioned data)
For a horizontal partitioning (sharding) tutorial, see Getting started with elastic query for horizontal
partitioning (sharding).
For syntax and sample queries for horizontally partitioned data, see Querying horizontally partitioned data)
See sp_execute _remote for a stored procedure that executes a Transact-SQL statement on a single remote
Azure SQL Database or set of databases serving as shards in a horizontal partitioning scheme.
SQL Database Advisor using the Azure portal
2/16/2017 • 4 min to read • Edit Online
You can use the Azure SQL Database Advisor in the Azure portal to review and implement recommendations for
your existing SQL Databases that can improve current query performance.
Viewing recommendations
The recommendations page is where you view the top recommendations based on their potential impact to
improve performance. You can also view the status of the historical operations. Select a recommendation or status
to see more details.
To view and apply recommendations, you need the correct role-based access control permissions in Azure. Reader,
SQL DB Contributor permissions are required to view recommendations, and Owner, SQL DB Contributor
permissions are required to execute any actions; create or drop indexes and cancel index creation.
1. Sign in to the Azure portal.
2. Click More services > SQL databases, and select your database.
3. Click Performance recommendation to view available recommendations for the selected database.
NOTE
To get recommendations a database needs to have about a day of usage, and there needs to be some activity. There also
needs to be some consistent activity. The SQL Database Advisor can more easily optimize for consistent query patterns than
it can for random spotty bursts of activity. If recommendations are not available, the Performance recommendation page
should provide a message explaining why.
IMPACT DESCRIPTION
Applying recommendations
SQL Database Advisor gives you full control over how recommendations are enabled using any of the following
three options:
Apply individual recommendations one at a time.
Enable the advisor to automatically apply recommendations (currently applies to index recommendations only).
To implement a recommendation manually, run the recommended T-SQL script against your database .
Select any recommendation to view its details and then click View script to review the exact details of how the
recommendation is created.
The database remains online while the advisor applies the recommendation -- using SQL Database Advisor never
takes a database offline.
Apply an individual recommendation
You can review and accept recommendations one at a time.
1. On the Recommendations blade, click a recommendation.
2. On the Details blade click Apply.
Monitoring operations
Applying a recommendation might not happen instantaneously. The portal provides details regarding the status of
recommendation operations. The following are possible states that an index can be in:
STATUS DESCRIPTION
Reverting The recommendation was applied, but has been deemed non-
performant and is being automatically reverted.
Summary
SQL Database Advisor provides recommendations for improving SQL database performance. By providing T-SQL
scripts, as well as individual and fully-automatic (currently index only), the advisor provides helpful assistance in
optimizing your database and ultimately improving query performance.
Next steps
Monitor your recommendations and continue to apply them to refine performance. Database workloads are
dynamic and change continuously. SQL Database advisor will continue to monitor and provide recommendations
that can potentially improve your database's performance.
See SQL Database Advisor for an overview of SQL Database Advisor.
See Query Performance Insights to learn about viewing the performance impact of your top queries.
Additional resources
Query Store
CREATE INDEX
Role-based access control
SQL Database Performance Insight
4/19/2017 • 1 min to read • Edit Online
Azure SQL Database provides performance tools to help you identify and improve the performance of your
databases by providing intelligent tuning actions and recommendations.
1. Browse to your database in the Azure Portal and click All settings > Performance ** > **Overview to open
the Performance page.
2. Click Recommendations to open the SQL Database Advisor, and click Queries to open Query
Performance Insight.
Performance Overview
Clicking on Overview or on the Performance tile will take you to the performance dashboard for your database.
This view provides a summary of your database performance, and helps you with performance tuning and
troubleshooting.
The Recommendations tile provides a breakdown of tuning recommendations for your database (top 3
recommendations are shown if there are more). Clicking this tile takes you to SQL Database Advisor.
The Tuning activity tile provides a summary of the ongoing and completed tuning actions for your database,
giving you a quick view into the history of tuning activity. Clicking this tile takes you to the full tuning history
view for your database.
The Auto-tuning tile shows the auto-tuning configuration for your database (which tuning actions are
configured to be automatically applied to your database). Clicking this tile opens the automation configuration
dialog.
The Database queries tile shows the summary of the query performance for your database (overall DTU usage
and top resource consuming queries). Clicking this tile takes you to Query Performance Insight.
Additional resources
Azure SQL Database performance guidance for single databases
When should an elastic pool be used?
SQL Database performance tuning tips
4/19/2017 • 1 min to read • Edit Online
You can change the service tier of a standalone database or increase the eDTUs of an elastic pool at any time to
improve performance, but you may want to identify opportunities to improve and optimize query performance
first. Missing indexes and poorly optimized queries are common reasons for poor database performance. This
article provides guidance for performance tuning in SQL Database.
If your Azure issue is not addressed in this article, visit the Azure forums on MSDN and the Stack Overflow. You
can post your issue on these forums or to @AzureSupport on Twitter. Also, you can file an Azure support request
by selecting Get support on the Azure support site.
IMPORTANT
It is recommended that you always use the latest version of Management Studio to remain synchronized with updates to
Microsoft Azure and SQL Database. Update SQL Server Management Studio.
Overview
This article shows you how to set up Azure SQL Database alerts using the Azure portal. This article also provides
best practices for values and thresholds.
You can receive an alert based on monitoring metrics for, or events on, your Azure services.
Metric values - The alert triggers when the value of a specified metric crosses a threshold you assign in either
direction. That is, it triggers both when the condition is first met and then afterwards when that condition is no
longer being met.
Activity log events - An alert can trigger on every event, or, only when a certain number of events occur.
You can configure an alert to do the following when it triggers:
send email notifications to the service administrator and co-administrators
send email to additional emails that you specify.
call a webhook
start execution of an Azure runbook (only from the Azure portal)
You can configure and get information about alert rules using
Azure portal
PowerShell
command-line interface (CLI)
Azure Monitor REST API
Next steps
Get an overview of Azure monitoring including the types of information you can collect and monitor.
Learn more about configuring webhooks in alerts.
Learn more about Azure Automation Runbooks.
Get an overview of diagnostic logs and collect detailed high-frequency metrics on your service.
Get an overview of metrics collection to make sure your service is available and responsive.
Monitor In-Memory OLTP Storage
2/16/2017 • 1 min to read • Edit Online
When using In-Memory OLTP, data in memory-optimized tables and table variables resides in In-Memory OLTP
storage. Each Premium service tier has a maximum In-Memory OLTP storage size, which is documented in the
SQL Database Service Tiers article. Once this limit is exceeded, insert and update operations may start failing (with
error 41823). At that point you will need to either delete data to reclaim memory, or upgrade the performance tier
of your database.
Determine whether data will fit within the in-memory storage cap
Determine the storage cap: consult the SQL Database Service Tiers article for the storage caps of the different
Premium service tiers.
Estimating memory requirements for a memory-optimized table works the same way for SQL Server as it does in
Azure SQL Database. Take a few minutes to review that topic on MSDN.
Note that the table and table variable rows, as well as indexes, count toward the max user data size. In addition,
ALTER TABLE needs enough room to create a new version of the entire table and its indexes.
Next steps
For monitoring guidance, see Monitoring Azure SQL Database using dynamic management views.
Event File target code for extended events in SQL
Database
4/14/2017 • 9 min to read • Edit Online
You want a complete code sample for a robust way to capture and report information for an extended event.
In Microsoft SQL Server, the Event File target is used to store event outputs into a local hard drive file. But such
files are not available to Azure SQL Database. Instead we use the Azure Storage service to support the Event File
target.
This topic presents a two-phase code sample:
PowerShell, to create an Azure Storage container in the cloud.
Transact-SQL:
To assign the Azure Storage container to an Event File target.
To create and start the event session, and so on.
Prerequisites
An Azure account and subscription. You can sign up for a free trial.
Any database you can create a table in.
Optionally you can create an AdventureWorksLT demonstration database in minutes.
SQL Server Management Studio (ssms.exe), ideally its latest monthly update version. You can download the
latest ssms.exe from:
Topic titled Download SQL Server Management Studio.
A direct link to the download.
You must have the Azure PowerShell modules installed.
The modules provide commands such as - New-AzureStorageAccount.
## TODO: Before running, find all 'TODO' and make each edit!!
#--------------- 1 -----------------------
Add-AzureAccount
#-------------- 2 ------------------------
'
TODO: Edit the values assigned to these variables, especially the first few!
'
$subscriptionName = 'YOUR_SUBSCRIPTION_NAME'
$policySasExpiryTime = '2016-01-28T23:44:56Z'
$policySasStartTime = '2015-08-01'
$storageAccountName = 'gmstorageaccountxevent'
$storageAccountLocation = 'West US'
$contextName = 'gmcontext'
$containerName = 'gmcontainerxevent'
$policySasToken = 'gmpolicysastoken'
#--------------- 3 -----------------------
#-------------- 4 ------------------------
'
Clean up the old Azure Storage Account after any previous run,
before continuing this new run.'
If ($storageAccountName)
{
Remove-AzureStorageAccount -StorageAccountName $storageAccountName
}
#--------------- 5 -----------------------
[System.DateTime]::Now.ToString()
'
Create a storage account.
This might take several minutes, will beep when ready.
...PLEASE WAIT...'
New-AzureStorageAccount `
-StorageAccountName $storageAccountName `
-Location $storageAccountLocation
[System.DateTime]::Now.ToString()
[System.Media.SystemSounds]::Beep.Play()
'
Get the primary access key for your storage account.
'
$primaryAccessKey_ForStorageAccount = `
(Get-AzureStorageKey `
-StorageAccountName $storageAccountName).Primary
"`$primaryAccessKey_ForStorageAccount = $primaryAccessKey_ForStorageAccount"
#--------------- 6 -----------------------
# The context will be needed to create a container within the storage account.
'Create a context object from the storage account and its primary access key.
'
$context = New-AzureStorageContext `
-StorageAccountName $storageAccountName `
-StorageAccountKey $primaryAccessKey_ForStorageAccount
$containerObjectInStorageAccount = New-AzureStorageContainer `
-Name $containerName `
-Context $context
New-AzureStorageContainerStoredAccessPolicy `
-Container $containerName `
-Context $context `
-Policy $policySasToken `
-Permission $policySasPermission `
-ExpiryTime $policySasExpiryTime `
-StartTime $policySasStartTime
'
Generate a SAS token for the container.
'
Try
{
$sasTokenWithPolicy = New-AzureStorageContainerSASToken `
-Name $containerName `
-Context $context `
-Policy $policySasToken
}
Catch
{
$Error[0].Exception.ToString()
}
#-------------- 7 ------------------------
'Display the values that YOU must edit into the Transact-SQL script next!:
'
"storageAccountName: $storageAccountName"
"containerName: $containerName"
"sasTokenWithPolicy: $sasTokenWithPolicy"
'
REMINDER: sasTokenWithPolicy here might start with "?" character, which you must exclude from Transact-SQL.
'
'
(Later, return here to delete your Azure Storage account. See the preceding - Remove-AzureStorageAccount -StorageAccountName
$storageAccountName)'
'
Now shift to the Transact-SQL portion of the two-part code sample!'
# EOFile
Take note of the few named values that the PowerShell script prints when it ends. You must edit those values into
the Transact-SQL script that follows as phase 2.
WARNING
The SAS key value generated by the preceding PowerShell script might begin with a '?' (question mark). When you use the
SAS key in the following T-SQL script, you must remove the leading '?'. Otherwise your efforts might be blocked by security.
Transact-SQL code
---- TODO: First, run the PowerShell portion of this two-part code sample.
---- TODO: Second, find every 'TODO' in this Transact-SQL file, and edit each.
---- Transact-SQL code for Event File target on Azure SQL Database.
IF EXISTS
(SELECT * FROM sys.objects
WHERE type = 'U' and name = 'gmTabEmployee')
BEGIN
DROP TABLE gmTabEmployee;
END
GO
IF NOT EXISTS
(SELECT * FROM sys.symmetric_keys
WHERE symmetric_key_id = 101)
BEGIN
CREATE MASTER KEY ENCRYPTION BY PASSWORD = '0C34C960-6621-4682-A123-C7EA08E3FC46' -- Or any newid().
END
GO
IF EXISTS
(SELECT * FROM sys.database_scoped_credentials
-- TODO: Assign AzureStorageAccount name, and the associated Container name.
WHERE name = 'https://gmstorageaccountxevent.blob.core.windows.net/gmcontainerxevent')
BEGIN
DROP DATABASE SCOPED CREDENTIAL
-- TODO: Assign AzureStorageAccount name, and the associated Container name.
[https://gmstorageaccountxevent.blob.core.windows.net/gmcontainerxevent] ;
END
GO
CREATE
DATABASE SCOPED
CREDENTIAL
-- use '.blob.', and not '.queue.' or '.table.' etc.
-- TODO: Assign AzureStorageAccount name, and the associated Container name.
[https://gmstorageaccountxevent.blob.core.windows.net/gmcontainerxevent]
WITH
IDENTITY = 'SHARED ACCESS SIGNATURE', -- "SAS" token.
-- TODO: Paste in the long SasToken string here for Secret, but exclude any leading '?'.
SECRET = 'sv=2014-02-14&sr=c&si=gmpolicysastoken&sig=EjAqjo6Nu5xMLEZEkMkLbeF7TD9v1J8DNB2t8gOKTts%3D'
;
GO
IF EXISTS
(SELECT * from sys.database_event_sessions
WHERE name = 'gmeventsessionname240b')
BEGIN
DROP
EVENT SESSION
gmeventsessionname240b
ON DATABASE;
END
GO
CREATE
EVENT SESSION
gmeventsessionname240b
ON DATABASE
ADD EVENT
sqlserver.sql_statement_starting
(
ACTION (sqlserver.sql_text)
WHERE statement LIKE 'UPDATE gmTabEmployee%'
)
ADD TARGET
package0.event_file
(
-- TODO: Assign AzureStorageAccount name, and the associated Container name.
-- Also, tweak the .xel file name at end, if you like.
SET filename =
'https://gmstorageaccountxevent.blob.core.windows.net/gmcontainerxevent/anyfilenamexel242b.xel'
)
WITH
WITH
(MAX_MEMORY = 10 MB,
MAX_DISPATCH_LATENCY = 3 SECONDS)
;
GO
ALTER
EVENT SESSION
gmeventsessionname240b
ON DATABASE
STATE = START;
GO
UPDATE gmTabEmployee
SET EmployeeKudosCount = EmployeeKudosCount + 2
WHERE EmployeeDescr = 'Jane Doe';
UPDATE gmTabEmployee
SET EmployeeKudosCount = EmployeeKudosCount + 13
WHERE EmployeeDescr = 'Jane Doe';
ALTER
EVENT SESSION
gmeventsessionname240b
ON DATABASE
STATE = STOP;
GO
SELECT
*, 'CLICK_NEXT_CELL_TO_BROWSE_ITS_RESULTS!' as [CLICK_NEXT_CELL_TO_BROWSE_ITS_RESULTS],
CAST(event_data AS XML) AS [event_data_XML] -- TODO: In ssms.exe results grid, double-click this cell!
FROM
sys.fn_xe_file_target_read_file
(
-- TODO: Fill in Storage Account name, and the associated Container name.
'https://gmstorageaccountxevent.blob.core.windows.net/gmcontainerxevent/anyfilenamexel242b',
null, null, null
);
GO
DROP
EVENT SESSION
gmeventsessionname240b
ON DATABASE;
GO
If the target fails to attach when you run, you must stop and restart the event session:
Output
When the Transact-SQL script completes, click a cell under the event_data_XML column header. One element is
displayed which shows one UPDATE statement.
Here is one element that was generated during testing:
UPDATE gmTabEmployee
SET EmployeeKudosCount = EmployeeKudosCount + 2
WHERE EmployeeDescr = 'Jane Doe';
UPDATE gmTabEmployee
SET EmployeeKudosCount = EmployeeKudosCount + 13
WHERE EmployeeDescr = 'Jane Doe';
The preceding Transact-SQL script used the following system function to read the event_file:
sys.fn_xe_file_target_read_file (Transact-SQL)
An explanation of advanced options for the viewing of data from extended events is available at:
Advanced Viewing of Target Data from Extended Events
More information
For more info about accounts and containers in the Azure Storage service, see:
How to use Blob storage from .NET
Naming and Referencing Containers, Blobs, and Metadata
Working with the Root Container
Lesson 1: Create a stored access policy and a shared access signature on an Azure container
Lesson 2: Create a SQL Server credential using a shared access signature
Ring Buffer target code for extended events in SQL
Database
4/14/2017 • 5 min to read • Edit Online
You want a complete code sample for the easiest quick way to capture and report information for an extended
event during a test. The easiest target for extended event data is the Ring Buffer target.
This topic presents a Transact-SQL code sample that:
1. Creates a table with data to demonstrate with.
2. Creates a session for an existing extended event, namely sqlserver.sql_statement_starting.
The event is limited to SQL statements that contain a particular Update string: statement LIKE
'%UPDATE tabEmployee%'.
Chooses to send the output of the event to a target of type Ring Buffer, namely package0.ring_buffer.
3. Starts the event session.
4. Issues a couple of simple SQL UPDATE statements.
5. Issues an SQL SELECT to retrieve event output from the Ring Buffer.
sys.dm_xe_database_session_targets and other dynamic management views (DMVs) are joined.
6. Stops the event session.
7. Drops the Ring Buffer target, to release its resources.
8. Drops the event session and the demo table.
Prerequisites
An Azure account and subscription. You can sign up for a free trial.
Any database you can create a table in.
Optionally you can create an AdventureWorksLT demonstration database in minutes.
SQL Server Management Studio (ssms.exe), ideally its latest monthly update version. You can download the
latest ssms.exe from:
Topic titled Download SQL Server Management Studio.
A direct link to the download.
Code sample
With very minor modification, the following Ring Buffer code sample can be run on either Azure SQL Database or
Microsoft SQL Server. The difference is the presence of the node '_database' in the name of some dynamic
management views (DMVs), used in the FROM clause in Step 5. For example:
sys.dm_xe_database_session_targets
sys.dm_xe_session_targets
GO
---- Transact-SQL.
---- Step set 1.
SET NOCOUNT ON;
GO
IF EXISTS
(SELECT * FROM sys.objects
WHERE type = 'U' and name = 'tabEmployee')
BEGIN
DROP TABLE tabEmployee;
END
GO
IF EXISTS
(SELECT * from sys.database_event_sessions
WHERE name = 'eventsession_gm_azuresqldb51')
BEGIN
DROP EVENT SESSION eventsession_gm_azuresqldb51
ON DATABASE;
END
GO
CREATE
EVENT SESSION eventsession_gm_azuresqldb51
ON DATABASE
ADD EVENT
sqlserver.sql_statement_starting
(
ACTION (sqlserver.sql_text)
WHERE statement LIKE '%UPDATE tabEmployee%'
)
ADD TARGET
package0.ring_buffer
(SET
max_memory = 500 -- Units of KB.
);
GO
UPDATE tabEmployee
SET EmployeeKudosCount = EmployeeKudosCount + 1015;
SELECT
se.name AS [session-name],
ev.event_name,
ac.action_name,
st.target_name,
se.session_source,
st.target_data,
CAST(st.target_data AS XML) AS [target_data_XML]
FROM
sys.dm_xe_database_session_event_actions AS ac
UPDATE tabEmployee
SET EmployeeKudosCount = EmployeeKudosCount + 102;
UPDATE tabEmployee
SET EmployeeKudosCount = EmployeeKudosCount + 1015;
UPDATE tabEmployee
SET EmployeeKudosCount = EmployeeKudosCount + 102;
UPDATE tabEmployee
SET EmployeeKudosCount = EmployeeKudosCount + 1015;
The definition of your event session is updated, but not dropped. Later you can add another instance of the Ring
Buffer to your event session:
More information
The primary topic for extended events on Azure SQL Database is:
Extended event considerations in SQL Database, which contrasts some aspects of extended events that differ
between Azure SQL Database versus Microsoft SQL Server.
Other code sample topics for extended events are available at the following links. However, you must routinely
check any sample to see whether the sample targets Microsoft SQL Server versus Azure SQL Database. Then you
can decide whether minor changes are needed to run the sample.
Code sample for Azure SQL Database: Event File target code for extended events in SQL Database
Managing Azure SQL Databases using Azure
Automation
4/14/2017 • 1 min to read • Edit Online
This guide will introduce you to the Azure Automation service, and how it can be used to simplify management of
your Azure SQL databases.
Next steps
Now that you've learned the basics of Azure Automation and how it can be used to manage Azure SQL databases,
follow these links to learn more about Azure Automation.
Azure Automation Overview
My first runbook
Azure Automation learning map
Azure Automation: Your SQL Agent in the Cloud
Use SQL Server Management Studio in Azure
RemoteApp to connect to SQL Database
4/14/2017 • 4 min to read • Edit Online
IMPORTANT
Azure RemoteApp is being discontinued. Read the announcement for details.
Introduction
This tutorial shows you how to use SQL Server Management Studio (SSMS) in Azure RemoteApp to connect to SQL
Database. It walks you through the process of setting up SQL Server Management Studio in Azure RemoteApp,
explains the benefits, and shows security features that you can use in Azure Active Directory.
Estimated time to complete: 45 minutes
8. Add users
On the User Access tab you can select the users that will have access to this Azure RemoteApp collection which only
includes SSMS.
9. Install the Azure RemoteApp client application
You can download and install a Azure RemoteApp client here: Download | Azure RemoteApp
Next steps
After completing all the above steps, you will be able to run the Azure RemoteApp client and log-in with an
assigned user. You will be presented with SSMS as one of your applications, and you can run it as you would if it
were installed on your computer with access to Azure SQL server.
For more information on how to make the connection to SQL Database, see Connect to SQL Database with SQL
Server Management Studio and perform a sample T-SQL query.
That's everything for now. Enjoy!
Configure Azure SQL Database multi-factor
authentication for SQL Server Management Studio
4/14/2017 • 2 min to read • Edit Online
This topic shows you how to configure Azure SQL Database multi-factor authentication for SQL Server
Management Studio.
For an overview of Azure SQL Database multi-factor authentication, see Overview of Azure SQL Database multi-
factor authentication for SQL Server Management Studio.
Configuration steps
1. Configure an Azure Active Directory - For more information, see Integrating your on-premises identities
with Azure Active Directory, Add your own domain name to Azure AD, Microsoft Azure now supports federation
with Windows Server Active Directory, Administering your Azure AD directory, and Manage Azure AD using
Windows PowerShell.
2. Configure MFA - For step-by-step instructions, see Configuring Azure Multi-Factor Authentication.
3. Configure SQL Database or SQL Data Warehouse for Azure AD Authentication - For step-by-step
instructions, see Connecting to SQL Database or SQL Data Warehouse By Using Azure Active Directory
Authentication.
4. Download SSMS - On the client computer, download the latest SSMS (at least August 2016), from Download
SQL Server Management Studio (SSMS).
2. As usual for SQL Database and SQL Data Warehouse you must click Options and specify the database on the
Options dialog box. Then click Connect.
3. When the Sign in to your account dialog box appears, provide the account and password of your Azure
Active Directory identity.
NOTE
For Universal Authentication with an account which does not require MFA, you connect at this point. For users
requiring MFA, continue with the following steps.
4. Two MFA setup dialog boxes might appear. This one time operation depends on the MFA administrator
setting, and therefore may be optional. For an MFA enabled domain this step is sometimes pre-defined (for
example, the domain requires users to use a smartcard and pin).
5. The second possible one time dialog box allows you to select the details of your authentication method. The
possible options are configured by your administrator.
6. The Azure Active Directory sends the confirming information to you. When you receive the verification code,
enter it into the Enter verification code box, and click Sign in.
When verification is complete, SSMS connects normally presuming valid credentials and firewall access.
Next steps
For an overview of Azure SQL Database multi-factor authentication, see Overview of Azure SQL Database
multi-factor authentication for SQL Server Management Studio.
Grant others access to your database: SQL Database Authentication and Authorization: Granting Access
Make sure others can connect through the firewall: Configure an Azure SQL Database server-level firewall rule
using the Azure portal
SQL Database FAQ
4/19/2017 • 9 min to read • Edit Online
What if a single database is active for less than an hour or uses a higher
service tier for less than an hour?
You are billed for each hour a database exists using the highest service tier + performance level that applied during
that hour, regardless of usage or whether the database was active for less than an hour. For example, if you create a
single database and delete it five minutes later your bill reflects a charge for one database hour.
Examples
If you create a Basic database and then immediately upgrade it to Standard S1, you are charged at the Standard
S1 rate for the first hour.
If you upgrade a database from Basic to Premium at 10:00 p.m. and upgrade completes at 1:35 a.m. on the
following day, you are charged at the Premium rate starting at 1:00 a.m.
If you downgrade a database from Premium to Basic at 11:00 a.m. and it completes at 2:15 p.m., then the
database is charged at the Premium rate until 3:00 p.m., after which it is charged at the Basic rates.
How does elastic pool usage show up on my bill and what happens
when I change eDTUs per pool?
Elastic pool charges show up on your bill as Elastic DTUs (eDTUs) in the increments shown under eDTUs per pool
on the pricing page. There is no per-database charge for elastic pools. You are billed for each hour a pool exists at
the highest eDTU, regardless of usage or whether the pool was active for less than an hour.
Examples
If you create a Standard elastic pool with 200 eDTUs at 11:18 a.m., adding five databases to the pool, you are
charged for 200 eDTUs for the whole hour, beginning at 11 a.m. through the remainder of the day.
On Day 2, at 5:05 a.m., Database 1 begins consuming 50 eDTUs and holds steady through the day. Databases 2-
5 fluctuate between 0 and 80 eDTUs. During the day, you add five other databases that consume varying eDTUs
throughout the day. Day 2 is a full day billed at 200 eDTU.
On Day 3, at 5 a.m. you add another 15 databases. Database usage increases throughout the day to the point
where you decide to increase eDTUs for the pool from 200 to 400 at 8:05 p.m. Charges at the 200 eDTU level
were in effect until 8 pm and increases to 400 eDTUs for the remaining four hours.
How do I find the right service tier and performance level for single
databases and elastic pools?
There are a few tools available to you.
For on-premises databases, use the DTU sizing advisor to recommend the databases and DTUs required, and
evaluate multiple databases for elastic pools.
If a single database would benefit from being in a pool, Azure's intelligent engine recommends an elastic pool if
it sees a historical usage pattern that warrants it. See Monitor and manage an elastic pool with the Azure portal.
For details about how to do the math yourself, see Price and performance considerations for an elastic pool
To see whether you need to dial a single database up or down, see performance guidance for single databases.
How often can I change the service tier or performance level of a single
database?
You can change the service tier (between Basic, Standard, Premium, and Premium RS) or the performance level
within a service tier (for example, S1 to S2) as often as you want. For earlier version databases, you can change the
service tier or performance level a total of four times in a 24-hour period.
How long does it take to change the service tier or performance level of
a single database or move a database in and out of an elastic pool?
Changing the service tier of a database and moving in and out of a pool requires the database to be copied on the
platform as a background operation. Changing the service tier can take from a few minutes to several hours
depending on the size of the databases. In both cases, the databases remain online and available during the move.
For details on changing single databases, see Change the service tier of a database.
I'm moving from Web/Business to the new service tiers, what do I need
to know?
Azure SQL Web and Business databases are now retired. The Basic, Standard, Premium, Premium RS, and Elastic
tiers replace the retiring Web and Business databases.
What is an expected replication lag when geo-replicating a database
between two regions within the same Azure geography?
We are currently supporting an RPO of five seconds and the replication lag has been less than that when the geo-
secondary is hosted in the Azure recommended paired region and at the same service tier.
If there is a network failure between two regions, how does the retry
logic work when Geo-Replication is set up?
If there is a disconnect, we retry every 10 seconds to re-establish connections.
What tools are available to monitor the replication lag between the
primary database and geo-secondary?
We expose the real-time replication lag between the primary database and geo-secondary through a DMV. For
details, see sys.dm_geo_replication_link_status.
Browse this list of public data sets for data that you can use to prototype and test storage and analytics services and
solutions.
US Government data Over 190,000 data sets covering Files of various sizes in various formats
agriculture, climate, consumer, including HTML, XML, CSV, JSON, Excel,
ecosystems, education, energy, finance, and many others. You can filter
health, local government, available data sets by file format.
manufacturing, maritime, ocean, public
safety, and science and research in the
U.S.
US Census data Statistical data about the population of Data sets are in various formats.
the U.S.
Earth science data from NASA Over 32,000 data collections covering Data sets are in various formats.
agriculture, atmosphere, biosphere,
climate, cryosphere, human dimensions,
hydrosphere, land surface, oceans, sun-
earth interactions, and more.
Airline flight delays and other "The U.S. Department of Files are in CSV format.
transportation data Transportation's (DOT) Bureau of
Transportation Statistics (BTS) tracks the
on-time performance of domestic flights
operated by large air carriers. Summary
information on the number of on-time,
delayed, canceled, and diverted flights
appears ... in summary tables posted on
this website."
Traffic fatalities - US Fatality Analysis "FARS is a nationwide census providing "Create your own fatality data run
Reporting System (FARS) NHTSA, Congress, and the American online by using the FARS Query System.
public yearly data regarding fatal Or download all FARS data from 1975
injuries suffered in motor vehicle traffic to present from the FTP Site."
crashes."
Toxic chemical data - EPA Toxicity "EPA's most updated, publicly available Data sets are available in various
ForeCaster (ToxCast™) data high-throughput toxicity data on formats including spreadsheets, R
thousands of chemicals. This data is packages, and MySQL database files.
generated through the EPA's ToxCast
research effort."
DATA SOURCE ABOUT THE DATA ABOUT THE FILES
Toxic chemical data - NIH Tox21 Data "The 2014 Tox21 data challenge is Data sets are available in SMILES and
Challenge 2014 designed to help scientists understand SDF formats. The data provides "assay
the potential of the chemicals and activity data and chemical structures on
compounds being tested through the the Tox21 collection of ~10,000
Toxicology in the 21st Century initiative compounds (Tox21 10K)."
to disrupt biological pathways in ways
that may result in toxic effects."
Biotechnology and genome data from Multiple data sets covering genes, Data sets are in text, XML, BLAST, and
the NCBI genomes, and proteins. other formats. A BLAST app is available.
New York City taxi data "Taxi trip records include fields capturing Data sets are in CSV files by month.
pick-up and drop-off dates/times, pick-
up and drop-off locations, trip
distances, itemized fares, rate types,
payment types, and driver-reported
passenger counts."
Microsoft Research data sets - "Data Multiple data sets covering human- Data sets are in various formats, zipped
Science for Research" computer interaction, audio/video, data for download.
mining/information retrieval,
geospatial/location, natural language
processing, and robotics/computer
vision.
Public genome data "A diverse data set of whole human Data sets, after extraction, are in UNIX
genomes are freely available for public text format. Analysis tools are also
use to enhance any genomic study..." available.
The provider, Complete Genomics, is a
private for-profit corporation.
Open Science Data Cloud data "The Open Science Data Cloud provides Data sets are in various formats.
the scientific community with resources
for storing, sharing, and analyzing
terabyte and petabyte-scale scientific
datasets."
Global climate data - WorldcLIM "WorldClim is a set of global climate These files contain geospatial data. For
layers (gridded climate data) with a more info, see Data format.
spatial resolution of about 1 km2. These
data can be used for mapping and
spatial modeling."
Data about human society - The GDELT "The GDELT Project is the largest, most The raw data files are in CSV format.
Project comprehensive, and highest resolution
open database of human society ever
created."
Advertising click prediction data for "The largest ever publicly released ML
machine learning from Criteo dataset." For more info, see Criteo's 1
TB Click Prediction Dataset.
DATA SOURCE ABOUT THE DATA ABOUT THE FILES
ClueWeb09 text mining data set from "The ClueWeb09 dataset was created to See Dataset Information.
The Lemur Project support research on information
retrieval and related human language
technologies. It consists of about 1
billion web pages in 10 languages that
were collected in January and February
2009."
GitHub activity data from The "The GHTorrent project [is] an effort to MySQL database dumps are in CSV
GHTorrent project create a scalable, queriable, offline format.
mirror of data offered through the
GitHub REST API. GHTorrent monitors
the GitHub public event time line. For
each event, it retrieves its contents and
their dependencies, exhaustively."
Stack Overflow data dump "This is an anonymized dump of all "Each site [such as Stack Overflow] is
user-contributed content on the Stack formatted as a separate archive
Exchange network [including Stack consisting of XML files zipped via 7-zip
Overflow]." using bzip2 compression. Each site
archive includes Posts, Users, Votes,
Comments, PostHistory, and PostLinks."
Azure SQL Database customer implementation
technical studies
3/10/2017 • 1 min to read • Edit Online
Daxko: Daxko/CSI Software faced a challenge: its customer base of fitness and recreation centers was
growing rapidly, thanks to the success of its comprehensive enterprise-software solution, but keeping up
with the IT-infrastructure needs for that growing customer base was testing the company’s IT staff. The
company was increasingly constrained by rising operations overhead, particularly for managing its growing
databases. Worse, that operations overhead was cutting into development resources for new initiatives, like
new mobility features for the company’s software.
GEP: GEP delivers software and services that enable procurement leaders around the world to maximize
their impact on their businesses’ operations, strategies, and financial performances. In addition to consulting
and managed services, the company offers SMART by GEP®, a cloud-based, comprehensive procurement-
software platform. However, GEP ran into limitations trying to support solutions like SMART by GEP with its
own on-premises datacenters: the investments needed were steep and regulatory requirements in other
countries would have made the necessary investments more daunting still. By moving to the cloud, GEP has
freed up IT resources, allowing it to worry less about IT operations and to focus more on developing new
sources of value for its customers across the globe.
SnelStart: SnelStart makes popular financial- and business-management software for small- and medium-
sized businesses (SMBs) in the Netherlands. Its 55,000 customers are serviced by a staff of 110 employees,
including an IT staff of 35. By moving from desktop software to a software-as-a-service (SaaS) offering built
on Azure, SnelStart made the most of built-in services, automating management using familiar environment
in C#, and optimizing performance and scalability by neither over- or under-provisioning businesses using
elastic pools. Using Azure provides SnelStart the fluidity of moving customers between on-premises and the
cloud.
Umbraco: To simplify customer deployments, Umbraco added Umbraco-as-a-Service (UaaS): a software-as-
a-service (SaaS) offering that eliminates the need for on-premises deployments, provides built-in scaling,
and removes management overhead by enabling developers to focus on product innovation rather than
solution management. Umbraco is able to provide all those benefits by relying on the flexible platform-as-a-
service (PaaS) model offered by Microsoft Azure.