好书分享,面向开发者的Azure SQL Database最佳实践,也适用SQL Server 2016以上的版本。应对不同场景使用的数据库功能,包括内存表,列存储表,非聚集列存储索引,JSON等等。

下载地址:

https://all-ebook.info/9978-practical-azure-sql-database-for-modern-developers.html

基础SQL

Subqueries

Common Table Expressions

Union

Merge

MERGE INTO

[Warehouse].[Colors] AS [target]

USING

(VALUES

(50, 'Deep Sea Blue'),

(51, 'Deep Sea Light Blue'),

(52, 'Deep Sea Dark Blue')

) [source](Id, [Name])

ON

[target].[ColorID] = [source].[Id]

WHEN MATCHED THEN

UPDATE SET [target].[ColorName] = [source].[Name]

WHEN NOT MATCHED THEN

INSERT ([ColorID], [ColorName], [LastEditedBy]) VALUES ([source].Id,

[source].[Name], 1)

WHEN NOT MATCHED BY SOURCE AND [target].[ColorID] BETWEEN 50 AND 100 THEN

DELETE

Windowing Functions

SELECT

[OrderID],

[OrderLineID],

[Description],

[Quantity],

SUM(Quantity) OVER ( PARTITION BY [OrderID] ORDER BY [OrderLineID] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS RunningTotal

FROM

[Sales].[OrderLines]

WHERE

[OrderID] in (37, 39)

进阶SQL

Variables

T-SQL doesn't support arrays, lists, or dictionaries, you can use a Table Variable

DECLARE @t AS TABLE (

[Id] INT NOT NULL,

[Name] NVARCHAR(50) NOT NULL

);

INSERT INTO @t VALUES (42, N'John');

SELECT * FROM @t;

Temporary Tables

Views

Functions

Stored Procedures

使用json传递多值参数

CREATE OR ALTER PROCEDURE dbo.GetOrderForCustomer

@CustomerInfo NVARCHAR(MAX)

AS

IF (ISJSON(@CustomerInfo) != 1) BEGIN

THROW 50000, '@CustomerInfo is not a valid JSON document', 16

END

SELECT [Value] INTO #T FROM OPENJSON(@CustomerInfo, '$.CustomerId') AS ci;

SELECT

[CustomerID],

COUNT(*) AS OrderCount,

MIN([OrderDate]) AS FirstOrder,

MAX([OrderDate]) AS LastOrder

FROM

Sales.[Orders]

WHERE

[CustomerID] IN (SELECT [Value] FROM #T)

GROUP BY

[CustomerID];

EXEC dbo.GetOrderForCustomer N'{"CustomerId": [106, 193, 832]}';

unless you have some specific use case that is perfectly suited for a Function, the recommendation is to use Stored Procedures

永远不要用触发器了

JSON

动态参数,拓展属性列,弹性域

CSV

STRING_SPLIT

CREATE PROCEDURE dbo.AddTagsToPost

@PostId INT,

@Tags NVARCHAR(MAX)

AS

INSERT INTO dbo.PostTags

SELECT @PostId, T.[value] FROM STRING_SPLIT(@Tags, '|') AS T

EXEC dbo.AddTagsToPost 1, 'azure-sql|string_split|csv'

Change Tracking

CDC

替代方案Debezium+ Kafka

Row-Level Security

CREATE FUNCTION rls.LoginSecurityPolicy(@PersonID AS INT)

RETURNS TABLE

WITH SCHEMABINDING

AS

RETURN

SELECT

1 As [Authorized]

FROM

[Application].[People]

WHERE

LoginName = SESSION_CONTEXT(N'Login')

AND

PersonID = @PersonId;

system function SESSION_CONTEXT to retrieve the value of the Logon key

Dynamic Data Masking

Always Encrypted

多模

JSON

SELECT

severity,

ip = JSON_VALUE(log, '$.ip'),

duration = AVG(CAST(JSON_VALUE(log,'$.duration') as int))

FROM

WebSite.Logs

WHERE

CAST(JSON_VALUE(log,'$.date') as datetime) > @datetime

GROUP BY

severity, JSON_VALUE(log, '$.ip')

HAVING

AVG(CAST(JSON_VALUE(log,'$.duration') as int) ) > 100

ORDER BY

AVG(CAST(JSON_VALUE(log,'$.duration') as int) );

ALTER TABLE Webite.Logs

ADD CONSTRAINT [Data should be formatted as JSON]

CHECK (ISJSON(log) = 1);

CREATE CLUSTERED COLUMNSTORE INDEX cci ON WebSite.Logs;

alter table WebSite.Logs

add [$severity] AS JSON_VALUE(log, '$.severity');

go

create index ix_severity on WebSite.Logs ([$severity]);

Graph

Spatial data

XML data

Key-value

Azure SQL doesn't have a specialized structure that holds key-value pairs.

With memory-optimized tables, you can index the key column using B-tree or Hash indexes-使用内存表代替

CREATE TABLE [Cache] (

[key] BIGINT IDENTITY,

value NVARCHAR(MAX),

INDEX IX_Hash_Key HASH ([key]) WITH (BUCKET_COUNT = 100000)

) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_ONLY);

More Than Tables

列存储表

聚集列存储表

非聚集列存储索引

内存表

using classic rowstore tables with NCCI indexes for HTAP scenarios is the general approach,

Memory-Optimized Clustered Columnstore Indexes are used only on very performance-intensive workloads.

--Columnstore memory-optimized tables

CREATE TABLE Accounts (

AccountKey int NOT NULL PRIMARY KEY NONCLUSTERED,

Description nvarchar (50),

Type nvarchar(50),

UnitSold int,

INDEX cci CLUSTERED COLUMNSTORE

) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA)

--memory-optimized tables and the NONCLUSTERED HASH index

CREATE TABLE [dbo].[Employees](

[EmpID] [int] NOT NULL

CONSTRAINT PK_Employees_EmpID PRIMARY KEY

NONCLUSTERED HASH (EmpID) WITH (BUCKET_COUNT = 100000),

[EmpName] [varchar](50) NOT NULL,

[EmpAddress] [varchar](50) NOT NULL,

[EmpDEPID] [int] NOT NULL,

[EmpBirthDay] [datetime] NULL

) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA)

Natively compiled code

CREATE FUNCTION PeopleData(@json nvarchar(max))

RETURNS TABLE

WITH NATIVE_COMPILATION, SCHEMABINDING

AS RETURN (

SELECT Title, HireDate, PrimarySalesTerritory,

CommissionRate, OtherLanguages

FROM OPENJSON(@json)

WITH(Title nvarchar(50),

HireDate datetime2,

PrimarySalesTerritory nvarchar(50),

CommissionRate float,

OtherLanguages nvarchar(max) AS JSON)

)

--调用函数

select p.FullName, p.EmailAddress, j.Title, j.CommissionRate

from Application.People p

cross apply PeopleData(p.CustomFields) j

Temporal tables

--当前表使用内存表

--历史表使用列存储表+非聚集行索引

CREATE CLUSTERED COLUMNSTORE INDEX cci_DepartmentHistory

ON DepartmentHistory;

CREATE NONCLUSTERED INDEX IX_DepartmentHistory_ID_PERIOD_COLUMNS

ON DepartmentHistory (SysEndTime, SysStartTime, DeptID);

HTAP

列存储索引+内存表做实时混合负载,HTAP场景

https://docs.microsoft.com/zh-cn/sql/relational-databases/indexes/get-started-with-columnstore-for-real-time-operational-analytics?view=sql-server-ver15

本书作者的博客

https://github.com/yorek

insert if not exists

insert into [dbo].[tags] ([post_id], [tag])

select * from (

values (10, 'tag123') -- sample value

) as s([post_id], [tag])

where not exists (

select * from [dbo].[tags] t with (updlock)

where s.[post_id] = t.[post_id] and s.[tag] = t.[tag]

)

https://devblogs.microsoft.com/azure-sql/the-insert-if-not-exists-challenge-a-solution/

多行插入使用JSON, Table Valued Parameters,与MERGE的比较

key-value store性能测试

https://devblogs.microsoft.com/azure-sql/azure-sql-database-as-a-key-value-store/

IoT场景性能测试

https://devblogs.microsoft.com/azure-sql/ingest-millions-of-events-per-second-on-azure-sql-leveraging-shock-absorber-pattern/

JSON性能测试

https://devblogs.microsoft.com/azure-sql/json-in-your-azure-sql-database-lets-benchmark-some-options/

开源web sql编辑器SQLPad

https://devblogs.microsoft.com/azure-sql/querying-and-visualizing-data-using-sqlpad/

DevOps for Azure SQL

https://devblogs.microsoft.com/azure-sql/devops-for-azure-sql/

SQL Database for Modern Developers的更多相关文章

  1. HTML5教程之html 5 本地数据库(Web Sql Database)

    HTML5的Web SQL Databases(html5 本地数据库)的确很诱惑人,当你发现可以用与mysql查询一样的查询语句来操作本地数据库时,你会发现这东西挺有趣的.今天,我们一起来了解HTM ...

  2. Azure SQL Database (19) Stretch Database 概览

    <Windows Azure Platform 系列文章目录>  Azure SQL Database (19) Stretch Database 概览      Azure SQL Da ...

  3. Azure SQL Database (20) 使用SQL Server 2016 Upgrade Advisor

    <Windows Azure Platform 系列文章目录>  Azure SQL Database (19) Stretch Database 概览      Azure SQL Da ...

  4. Azure SQL Database (21) 将整张表都迁移到Azure Stretch Database里

    <Windows Azure Platform 系列文章目录>  Azure SQL Database (19) Stretch Database 概览      Azure SQL Da ...

  5. Azure SQL Database (22) 迁移部分数据到Azure Stretch Database

    <Windows Azure Platform 系列文章目录>  Azure SQL Database (19) Stretch Database 概览      Azure SQL Da ...

  6. Azure SQL Database Active Geo-Replication简介

    笔者在<迁移SQL Server 数据库到 Azure SQL 实战>一文中,介绍了如何把一个本地版的 SQL Server 数据库迁移到 Azure SQL Database.迁移虽然顺 ...

  7. HTML5本地存储——Web SQL Database

    在HTML5 WebStorage介绍了html5本地存储的Local Storage和Session Storage,这两个是以键值对存储的解决方案,存储少量数据结构很有用,但是对于大量结构化数据就 ...

  8. HTML5 学习笔记(三)——本地存储(LocalStorage、SessionStorage、Web SQL Database)

    一.HTML4客户端存储 B/S架构的应用大量的信息存储在服务器端,客户端通过请求响应的方式从服务器获得数据,这样集中存储也会给服务器带来相应的压力,有些数据可以直接存储在客户端,传统的Web技术中会 ...

  9. web sql database数据存储位置

    Q1: 数据存储在哪儿? Web Storage / Web SQL Database / Indexed Database 的数据都存储在浏览器对应的用户配置文件目录(user profile di ...

随机推荐

  1. Java 窗口 绘制图形 #1

    写在前面: editplus换成eclipse了 Sketchpad要钱,买不起 自己搞(rua) by emeralddarkness 建立了一个平面直角坐标系 两个变元x,y,参数i 实现了以下功 ...

  2. hdu3669 Cross the Wall

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others) Total Submissi ...

  3. Codeforces Round #646 (Div. 2) C. Game On Leaves (贪心,博弈)

    题意:给你一棵树,每次可以去掉叶节点的一条边,Ayush先开始,每回合轮流来,问谁可以第一个把\(x\)点去掉. 题解:首先如果\(x\)的入度为\(1\),就可以直接拿掉,还需要特判一下入度为\(0 ...

  4. 最新版gradle安装使用简介

    目录 简介 安装gradle和解决gradle安装的问题 Gradle特性 标准task Build phases Gradle Wrapper wrapper的使用 wrapper的升级 一个简单的 ...

  5. 一篇文章搞懂G1收集器

    一.何为G1收集器 The Garbage-First (G1) garbage collector is a server-style garbage collector, targeted for ...

  6. XV6学习(15)Lab mmap: Mmap

    代码在Github上. 这一个实验是要实现最基础的mmap功能.mmap即内存映射文件,将一个文件直接映射到内存当中,之后对文件的读写就可以直接通过对内存进行读写来进行,而对文件的同步则由操作系统来负 ...

  7. word2vector代码实践

    引子 在上次的 <word2vector论文笔记>中大致介绍了两种词向量训练方法的原理及优劣,这篇咱们以skip-gram算法为例来代码实践一把. 当前教程参考:A Word2Vec Ke ...

  8. struct 和 class的区别

    struct和class如果按照在C的时代,还是有很大差别的. c中struct的定义如下: struct  结构名 {   成员表 }: 因为struct是一种数据类型,那么就肯定不能定义函数,所以 ...

  9. vue-router离开当前页面提示未保存,解决在使用beforeRouteLeave弹窗多次闪现问题

    在使用beforeRouteLeave时要注意两点: 1. next(false)阻止路由继续进行,若不先阻止,会多次执行守卫中的代码 2. 利用setTimeout延时触发弹窗,避免出现闪现情况

  10. 关于FFT的一些理解,以及如何手工计算FFT加深理解和验证正确性

    总结缺少逻辑性和系统性,主要便于自己理解和记忆 关于一维FFT的 于是复系数Cn是图像傅里叶变换的yn列向量 于是我们看到最后引入,Cn这个复系数的模来表征频率波的振幅记为Sn(即简谐波叠加的数量 然 ...