mirror of
https://github.com/Microsoft/sql-server-samples.git
synced 2025-12-08 14:58:54 +00:00
Merge remote-tracking branch 'refs/remotes/Microsoft/master'
This commit is contained in:
@@ -9,3 +9,7 @@ The new sample database for SQL Server 2016 and Azure SQL Database. It illustrat
|
||||
__[contoso-data-warehouse](contoso-data-warehouse/)__
|
||||
|
||||
Sample data warehouse that illustrates loading data into Azure SQL Data Warehouse.
|
||||
|
||||
__[AdventureWorks2014](https://github.com/Microsoft/sql-server-samples/releases/tag/adventureworks2014)__
|
||||
|
||||
Sample databases and Analysis Services models for use with SQL Server 2014 and later.
|
||||
@@ -0,0 +1,36 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp1.0</TargetFramework>
|
||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||
<AssemblyName>force-last-good-plan</AssemblyName>
|
||||
<OutputType>Exe</OutputType>
|
||||
<PackageId>force-last-good-plan</PackageId>
|
||||
<RuntimeFrameworkVersion>1.0.4</RuntimeFrameworkVersion>
|
||||
<PackageTargetFallback>$(PackageTargetFallback);dotnet5.6;portable-net45+win8</PackageTargetFallback>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="wwwroot\**\*">
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Routing" Version="1.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.0.2" />
|
||||
<PackageReference Include="System.Data.SqlClient" Version="4.3.0" />
|
||||
<PackageReference Include="Belgrade.Sql.Client" Version="0.7.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,60 +1,74 @@
|
||||
/********************************************************
|
||||
* SETUP - clear everything
|
||||
********************************************************/
|
||||
EXEC [dbo].[initialize]
|
||||
|
||||
ALTER DATABASE current SET AUTOMATIC_TUNING (FORCE_LAST_GOOD_PLAN = OFF);
|
||||
EXEC dbo.initialize;
|
||||
|
||||
/********************************************************
|
||||
* PART I
|
||||
* Plan regression identification.
|
||||
* Plan regression identification & manual tuning
|
||||
********************************************************/
|
||||
|
||||
-- 1. Start workload - execute procedure 30-300 times:
|
||||
begin
|
||||
declare @packagetypeid int = 7;
|
||||
exec dbo.report @packagetypeid
|
||||
end
|
||||
go 300
|
||||
-- Queries should be fast
|
||||
-- Optionally, include "Actual execution plan" in SSMS and show the plan (it should have Hash Aggregate)
|
||||
-- Execute the query and include "Actual execution plan" in SSMS and show the plan - it should have Hash Match (Aggregate) operator with Columnstore Index Scan
|
||||
EXEC sp_executesql N'select avg([UnitPrice]*[Quantity])
|
||||
from Sales.OrderLines
|
||||
where PackageTypeID = @packagetypeid', N'@packagetypeid int', @packagetypeid = 7;
|
||||
GO 60
|
||||
-- 1. Execute this query 45-300 times to setup the baseline.
|
||||
-- If you have QUERY_STORE CAPTURE_POLICY=AUTO increase number in GO <number> to at least 60
|
||||
|
||||
|
||||
-- 2. Execute procedure that causes plan regression
|
||||
-- Optionally, include "Actual execution plan" in SSMS and show the plan (it should have Stream Aggregate)
|
||||
exec dbo.regression
|
||||
-- 2. Execute the procedure that causes plan regression
|
||||
-- Optionally, include "Actual execution plan" in SSMS and show the plan - it should have Stream Aggregate, Index Seek & Nested Loops
|
||||
EXEC dbo.regression;
|
||||
|
||||
|
||||
-- 3. Start workload again - verify that is slower.
|
||||
begin
|
||||
declare @packagetypeid int = 7;
|
||||
exec dbo.report @packagetypeid
|
||||
end
|
||||
-- 3. Start the workload again - verify that is slower.
|
||||
EXEC sp_executesql N'select avg([UnitPrice]*[Quantity])
|
||||
from Sales.OrderLines
|
||||
where PackageTypeID = @packagetypeid', N'@packagetypeid int', @packagetypeid = 7;
|
||||
go 20
|
||||
-- Optionally, include "Actual execution plan" in SSMS and show the plan (it should have Stream Aggregate)
|
||||
-- Optionally, include "Actual execution plan" in SSMS and show the plan - it should have Stream Aggregate with Non-clustered index seek.
|
||||
|
||||
-- 4. Find recommendation recommended by database:
|
||||
SELECT planForceDetails.query_id, reason, score,
|
||||
JSON_VALUE(details, '$.implementationDetails.script') [correction script],
|
||||
planForceDetails.[new plan_id], planForceDetails.[recommended plan_id]
|
||||
FROM sys.dm_db_tuning_recommendations
|
||||
CROSS APPLY OPENJSON (Details, '$.planForceDetails')
|
||||
WITH ( [query_id] int '$.queryId',
|
||||
[new plan_id] int '$.regressedPlanId',
|
||||
[recommended plan_id] int '$.recommendedPlanId'
|
||||
) as planForceDetails;
|
||||
-- 4. Find a recommendation that can fix this issue:
|
||||
SELECT reason, score,
|
||||
script = JSON_VALUE(details, '$.implementationDetails.script')
|
||||
FROM sys.dm_db_tuning_recommendations;
|
||||
|
||||
-- 4.1. Optionally get more detailed information about the regression and recommendation.
|
||||
SELECT reason, score,
|
||||
script = JSON_VALUE(details, '$.implementationDetails.script'),
|
||||
planForceDetails.[query_id],
|
||||
planForceDetails.[new plan_id],
|
||||
planForceDetails.[recommended plan_id],
|
||||
estimated_gain = (regressedPlanExecutionCount+recommendedPlanExecutionCount)*(regressedPlanCpuTimeAverage-recommendedPlanCpuTimeAverage)/1000000,
|
||||
error_prone = IIF(regressedPlanErrorCount>recommendedPlanErrorCount, 'YES','NO')
|
||||
FROM sys.dm_db_tuning_recommendations
|
||||
CROSS APPLY OPENJSON (Details, '$.planForceDetails')
|
||||
WITH ( [query_id] int '$.queryId',
|
||||
[new plan_id] int '$.regressedPlanId',
|
||||
[recommended plan_id] int '$.recommendedPlanId',
|
||||
regressedPlanErrorCount int,
|
||||
recommendedPlanErrorCount int,
|
||||
regressedPlanExecutionCount int,
|
||||
regressedPlanCpuTimeAverage float,
|
||||
recommendedPlanExecutionCount int,
|
||||
recommendedPlanCpuTimeAverage float ) as planForceDetails;
|
||||
-- IMPORTANT NOTE: check is estimated_gain > 10.
|
||||
-- If estimated_gain < 10 THEN FLGP=ON will not automatically force the plan!!!
|
||||
-- In that case increase the number of executions in initial workload.
|
||||
-- Make sure that SQL Engine uses columnstore in original plan and nonclustered index in regressed plan.
|
||||
|
||||
-- Note: User can apply script and force the recommended plan to correct the error.
|
||||
<<Insert T-SQL from the script column here and execute the script>>
|
||||
-- e.g.: exec sp_query_store_force_plan @query_id = 3, @plan_id = 1
|
||||
|
||||
-- 5. Start workload again - verify that is faster.
|
||||
begin
|
||||
declare @packagetypeid int = 7;
|
||||
exec dbo.report @packagetypeid
|
||||
end
|
||||
go 20
|
||||
-- Optionally, include "Actual execution plan" in SSMS and show the plan (it should have Hash Aggregate again)
|
||||
-- 5. Execute the query again - verify that it is faster.
|
||||
EXEC sp_executesql N'select avg([UnitPrice]*[Quantity])
|
||||
from Sales.OrderLines
|
||||
where PackageTypeID = @packagetypeid', N'@packagetypeid int', @packagetypeid = 7;
|
||||
GO 20
|
||||
-- Optionally, include "Actual execution plan" in SSMS and show the plan - it should have Hash Aggregate & Columnstore again
|
||||
|
||||
|
||||
-- In part II will be shown better approach - automatic tuning.
|
||||
@@ -74,29 +88,26 @@ ALTER DATABASE current
|
||||
SET AUTOMATIC_TUNING ( FORCE_LAST_GOOD_PLAN = ON);
|
||||
|
||||
-- Verify that actual state on FLGP is ON:
|
||||
SELECT name, desired_state_desc, actual_state_desc, reason_desc
|
||||
FROM sys.database_automatic_tuning_options;
|
||||
|
||||
SELECT name, actual_state_desc, status = IIF(desired_state_desc <> actual_state_desc, reason_desc, 'Status:OK')
|
||||
FROM sys.database_automatic_tuning_options
|
||||
WHERE name = 'FORCE_LAST_GOOD_PLAN';
|
||||
|
||||
-- 1. Start workload - execute procedure 30-300 times like in the phase I
|
||||
begin
|
||||
declare @packagetypeid int = 7;
|
||||
exec dbo.report @packagetypeid
|
||||
end
|
||||
go 300
|
||||
EXEC sp_executesql N'select avg([UnitPrice]*[Quantity])
|
||||
from Sales.OrderLines
|
||||
where PackageTypeID = @packagetypeid', N'@packagetypeid int', @packagetypeid = 7;
|
||||
GO 60
|
||||
|
||||
-- 2. Execute the procedure that causes plan regression
|
||||
-- 2. Execute the procedure that causes the plan regression
|
||||
exec dbo.regression;
|
||||
|
||||
-- 3. Start workload again - verify that it is slower.
|
||||
begin
|
||||
declare @packagetypeid int = 7;
|
||||
exec dbo.report @packagetypeid;
|
||||
end
|
||||
go 20
|
||||
-- 3. Start the workload again - verify that it is slower.
|
||||
EXEC sp_executesql N'select avg([UnitPrice]*[Quantity])
|
||||
from Sales.OrderLines
|
||||
where PackageTypeID = @packagetypeid', N'@packagetypeid int', @packagetypeid = 7;
|
||||
go 30
|
||||
|
||||
-- 4. Find recommendation that returns query perf regression
|
||||
-- and check is it in Verifying state:
|
||||
-- 4. Find a recommendation and check is it in "Verifying" or "Success" state:
|
||||
SELECT reason, score,
|
||||
JSON_VALUE(state, '$.currentValue') state,
|
||||
JSON_VALUE(state, '$.reason') state_transition_reason,
|
||||
@@ -110,11 +121,11 @@ FROM sys.dm_db_tuning_recommendations
|
||||
) as planForceDetails;
|
||||
|
||||
|
||||
-- 5. Wait until recommendation is applied and start workload again - verify that it is faster.
|
||||
begin
|
||||
declare @packagetypeid int = 7;
|
||||
exec dbo.report @packagetypeid
|
||||
end
|
||||
go 30
|
||||
-- 5. Recommendation is in "Verifying" state, but the last good plan is forced, so the query will be faster:
|
||||
EXEC sp_executesql N'select avg([UnitPrice]*[Quantity])
|
||||
from Sales.OrderLines
|
||||
where PackageTypeID = @packagetypeid', N'@packagetypeid int', @packagetypeid = 7;
|
||||
|
||||
|
||||
-- Open Query Store/"Top Resource Consuming Queries" dialog in SSMS and show that the better plan is forced.
|
||||
|
||||
-- Open Query Store/"Top Resource Consuming Queries" dialog in SSMS and show that better plan is forced.
|
||||
@@ -0,0 +1,64 @@
|
||||
/***************************************************************************
|
||||
* Run this script on a empty database if you don't have WWI database and
|
||||
* you want to use new database instead of full WWI
|
||||
* If you are using SSMS, use Ctrl+Shift+M to populate parameters.
|
||||
***************************************************************************/
|
||||
ALTER DATABASE <database_name, sysname, flgp> MODIFY (EDITION = 'Premium', SERVICE_OBJECTIVE = '<azuredb_service_objective, varchar(6), P4>');
|
||||
SELECT DATABASEPROPERTYEX('<database_name, sysname, flgp>', 'ServiceObjective');
|
||||
-- Create minimal WWI schema required to run the sample:
|
||||
DROP TABLE IF EXISTS [Sales].[OrderLines];
|
||||
GO
|
||||
DROP SEQUENCE IF EXISTS [Sequences].[OrderLineID];
|
||||
GO
|
||||
DROP SCHEMA IF EXISTS [Sequences];
|
||||
GO
|
||||
DROP SCHEMA IF EXISTS [Sequences];
|
||||
GO
|
||||
|
||||
CREATE SCHEMA [Sequences];
|
||||
GO
|
||||
CREATE SEQUENCE [Sequences].[OrderLineID]
|
||||
AS [int]
|
||||
START WITH 231413
|
||||
INCREMENT BY 1
|
||||
MINVALUE -2147483648
|
||||
MAXVALUE 2147483647
|
||||
CACHE
|
||||
GO
|
||||
|
||||
CREATE TABLE [Sales].[OrderLines](
|
||||
[OrderLineID] [int] PRIMARY KEY,
|
||||
[OrderID] [int] NOT NULL,
|
||||
[StockItemID] [int] NOT NULL,
|
||||
[Description] [nvarchar](100) NOT NULL,
|
||||
[PackageTypeID] [int] NOT NULL,
|
||||
[Quantity] [int] NOT NULL,
|
||||
[UnitPrice] [decimal](18, 2) NULL,
|
||||
[TaxRate] [decimal](18, 3) NOT NULL,
|
||||
[PickedQuantity] [int] NOT NULL,
|
||||
[PickingCompletedWhen] [datetime2](7) NULL,
|
||||
[LastEditedBy] [int] NOT NULL,
|
||||
[LastEditedWhen] [datetime2](7) NOT NULL
|
||||
)
|
||||
GO
|
||||
ALTER TABLE [Sales].[OrderLines]
|
||||
ADD CONSTRAINT [DF_Sales_OrderLines_OrderLineID]
|
||||
DEFAULT (NEXT VALUE FOR [Sequences].[OrderLineID]) FOR [OrderLineID]
|
||||
GO
|
||||
ALTER TABLE [Sales].[OrderLines]
|
||||
ADD CONSTRAINT [DF_Sales_OrderLines_LastEditedWhen]
|
||||
DEFAULT (sysdatetime()) FOR [LastEditedWhen]
|
||||
GO
|
||||
DROP INDEX IF EXISTS [FK_Sales_OrderLines_PackageTypeID]
|
||||
ON [Sales].[OrderLines]
|
||||
|
||||
CREATE NONCLUSTERED INDEX [FK_Sales_OrderLines_PackageTypeID]
|
||||
ON [Sales].[OrderLines]([PackageTypeID] ASC)
|
||||
GO
|
||||
|
||||
|
||||
-- Export Sales.OrderLines from WWI database using bcp:
|
||||
-- bcp WideWorldImporters.Sales.OrderLines out OrderLines.dat -T -c -U <wwi_user_name, nvarchar(50), WWIUSERNAME> -P <wwi_password, nvarchar(50), WWIPASSWORD> -S <wwi server/instance, nvarchar(50), .//SQLEXPRESS>
|
||||
|
||||
-- Import data in new database using bcp:
|
||||
-- bcp <database_name, sysname, flgp>.Sales.OrderLines in OrderLines.dat -c -U <demo_user_name, nvarchar(50), DEMOUSERNAME> -P <demo_password, nvarchar(50), DEMOPASSWORD> -S <demo server/instance, nvarchar(50), .//SQLEXPRESS>
|
||||
@@ -1,6 +1,10 @@
|
||||
DROP INDEX IF EXISTS [NCCX_Sales_OrderLines] ON [Sales].[OrderLines]
|
||||
-- Insert one OrderLine that with PackageTypeID=(0) will cause regression
|
||||
INSERT INTO Sales.OrderLines(OrderId, StockItemID, Description, PAckageTypeID, quantity, unitprice, taxrate, PickedQuantity,LastEditedBy)
|
||||
SELECT TOP 1 OrderID, StockItemID, Description, PackageTypeID = 0, Quantity, UnitPrice, taxrate , PickedQuantity,LastEditedBy
|
||||
FROM Sales.OrderLines;
|
||||
|
||||
DROP INDEX IF EXISTS [NCCX_Sales_OrderLines] ON [Sales].[OrderLines]
|
||||
|
||||
/****** Object: Index [NCCX_Sales_OrderLines] Script Date: 4/20/2017 11:27:27 AM ******/
|
||||
CREATE NONCLUSTERED COLUMNSTORE INDEX [NCCX_Sales_OrderLines] ON [Sales].[OrderLines]
|
||||
(
|
||||
[OrderID],
|
||||
@@ -10,72 +14,74 @@ CREATE NONCLUSTERED COLUMNSTORE INDEX [NCCX_Sales_OrderLines] ON [Sales].[OrderL
|
||||
[UnitPrice],
|
||||
[PickedQuantity],
|
||||
[PackageTypeID] -- adding package type id for demo purpose
|
||||
)WITH (DROP_EXISTING = OFF, COMPRESSION_DELAY = 0) ON [USERDATA]
|
||||
)WITH (DROP_EXISTING = OFF, COMPRESSION_DELAY = 0)
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[initialize]
|
||||
as begin
|
||||
AS BEGIN
|
||||
|
||||
ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;
|
||||
ALTER DATABASE current SET QUERY_STORE CLEAR ALL;
|
||||
ALTER DATABASE current SET AUTOMATIC_TUNING ( FORCE_LAST_GOOD_PLAN = OFF);
|
||||
ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;
|
||||
ALTER DATABASE current SET QUERY_STORE CLEAR ALL;
|
||||
|
||||
end
|
||||
END
|
||||
GO
|
||||
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[report] (@packagetypeid int)
|
||||
as begin
|
||||
AS BEGIN
|
||||
|
||||
select avg([UnitPrice]*[Quantity])
|
||||
from Sales.OrderLines
|
||||
where PackageTypeID = @packagetypeid
|
||||
EXEC sp_executesql N'select avg([UnitPrice]*[Quantity])
|
||||
from Sales.OrderLines
|
||||
where PackageTypeID = @packagetypeid', N'@packagetypeid int', @packagetypeid;
|
||||
|
||||
end
|
||||
END
|
||||
GO
|
||||
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[regression]
|
||||
as begin
|
||||
AS BEGIN
|
||||
|
||||
ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;
|
||||
begin
|
||||
declare @packagetypeid int = 1;
|
||||
BEGIN
|
||||
declare @packagetypeid int = 0;
|
||||
exec report @packagetypeid;
|
||||
end
|
||||
END
|
||||
|
||||
end
|
||||
END
|
||||
GO
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[auto_tuning_on]
|
||||
as begin
|
||||
AS BEGIN
|
||||
|
||||
ALTER DATABASE current SET AUTOMATIC_TUNING ( FORCE_LAST_GOOD_PLAN = ON);
|
||||
ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;
|
||||
ALTER DATABASE current SET QUERY_STORE CLEAR ALL;
|
||||
ALTER DATABASE current SET AUTOMATIC_TUNING ( FORCE_LAST_GOOD_PLAN = ON);
|
||||
ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;
|
||||
ALTER DATABASE current SET QUERY_STORE CLEAR ALL;
|
||||
|
||||
end
|
||||
END
|
||||
GO
|
||||
|
||||
|
||||
CREATE OR ALTER PROCEDURE [dbo].[auto_tuning_off]
|
||||
as begin
|
||||
AS BEGIN
|
||||
|
||||
ALTER DATABASE current SET AUTOMATIC_TUNING ( FORCE_LAST_GOOD_PLAN = OFF);
|
||||
ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;
|
||||
ALTER DATABASE current SET QUERY_STORE CLEAR ALL;
|
||||
ALTER DATABASE current SET AUTOMATIC_TUNING ( FORCE_LAST_GOOD_PLAN = OFF);
|
||||
ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;
|
||||
ALTER DATABASE current SET QUERY_STORE CLEAR ALL;
|
||||
|
||||
end
|
||||
END
|
||||
GO
|
||||
/*
|
||||
|
||||
CREATE EVENT SESSION [APC - plans that are not corrected] ON SERVER
|
||||
|
||||
CREATE EVENT SESSION [APC - plans that are not corrected] ON DATABASE
|
||||
ADD EVENT qds.automatic_tuning_plan_regression_detection_check_completed(
|
||||
WHERE ((([is_regression_detected]=(1))
|
||||
AND ([is_regression_corrected]=(0)))
|
||||
AND ([option_id]=(1))))
|
||||
ADD TARGET package0.event_file(SET filename=N'plans_that_are_not_corrected')
|
||||
-- Use file target only on SQL Server 2017:
|
||||
-- ADD TARGET package0.event_file(SET filename=N'plans_that_are_not_corrected')
|
||||
ADD TARGET package0.ring_buffer (SET max_memory = 1000)
|
||||
WITH (STARTUP_STATE=ON);
|
||||
GO
|
||||
|
||||
ALTER EVENT SESSION [APC - plans that are not corrected] ON SERVER STATE = start;
|
||||
ALTER EVENT SESSION [APC - plans that are not corrected] ON SERVER STATE = start;
|
||||
*/
|
||||
@@ -37,27 +37,37 @@
|
||||
<div class="col-md-4">
|
||||
<h1>Automatic tuning</h1>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="col-md-3 hidden">
|
||||
<div class="btn-group pull-right align-bottom" data-toggle="buttons">
|
||||
<label class="btn btn-default active">
|
||||
<input type="radio" name="options" id="off" autocomplete="off" checked> OFF
|
||||
</label>
|
||||
<label class="btn btn-default">
|
||||
<input type="radio" name="options" id="on" autocomplete="off"> ON
|
||||
<input type="radio" name="options" id="off" autocomplete="off"> OFF
|
||||
</label>
|
||||
<label class="btn btn-default active">
|
||||
<input type="radio" name="options" id="on" autocomplete="off" checked> ON
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<span id="speed">0</span> requests per second.
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<button id="regression" type="button" class="btn btn-danger pull-right">Regression</button>
|
||||
<div class="col-md-12">
|
||||
<span id="speed">0</span> requests per second. <button id="regression" type="button" class="btn btn-danger pull-right">Regression</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<svg width="500" height="500"></svg>
|
||||
<div class="col-md-6">
|
||||
<svg width="500" height="500"></svg>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h3>T-SQL query:</h3>
|
||||
<pre>
|
||||
SELECT AVG( UnitPrice * Quantity )
|
||||
FROM Sales.OrderLines
|
||||
WHERE PackageTypeID = @packagetypeid;</pre>
|
||||
<h3>Enable FORCE LAST GOOD PLAN:</h3>
|
||||
<pre>
|
||||
ALTER DATABASE current
|
||||
SET AUTOMATIC_TUNING ( FORCE_LAST_GOOD_PLAN = ON);</pre>
|
||||
</div>
|
||||
</div>
|
||||
<script src="media/d3.v3.min.js"></script>
|
||||
<script src="media/viz.v1.0.0.min.js"></script>
|
||||
@@ -66,7 +76,7 @@
|
||||
<script src="media/GraphVizGauge.js"></script>
|
||||
<script src="/api/demo/init"></script>
|
||||
<script>
|
||||
var gauge = new GraphVizGauge("svg", { to: 150 });
|
||||
var gauge = new GraphVizGauge("svg", { to: 250 });
|
||||
var perfData = [];
|
||||
setInterval(function () {
|
||||
$.ajax({
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,66 @@
|
||||
# Power BI Reports for Consolidated Migration Assessments
|
||||
|
||||
This contains examples of Power BI reports for consolidated migration assessements. The assessments are generated using Data Migration Assistant, to evaluate moving data to SQL Server or to Azure SQL Database.
|
||||
|
||||
|
||||
### Contents
|
||||
|
||||
[About this sample](#about-this-sample)<br/>
|
||||
[Before you begin](#before-you-begin)<br/>
|
||||
[Run this sample](#run-this-sample)<br/>
|
||||
[Sample details](#sample-details)<br/>
|
||||
[Related links](#related-links)<br/>
|
||||
|
||||
|
||||
<a name=about-this-sample></a>
|
||||
|
||||
## About this sample
|
||||
|
||||
|
||||
- **Applies to:** SQL Server 2016 (or higher), Azure SQL Database
|
||||
- **Key features:** Migration assessments
|
||||
|
||||
|
||||
<a name=before-you-begin></a>
|
||||
|
||||
## Before you begin
|
||||
|
||||
To run this sample, you need the following prerequisites.
|
||||
|
||||
**Software prerequisites:**
|
||||
|
||||
1. Power BI
|
||||
2. SQL Server 2016 (or higher) or an Azure SQL Database
|
||||
3. Data Migration Assistant
|
||||
|
||||
**Azure prerequisites:**
|
||||
|
||||
1. Permission to create an Azure SQL Database
|
||||
|
||||
<a name=run-this-sample></a>
|
||||
|
||||
## Run this sample
|
||||
|
||||
<!-- Step by step instructions. Here's a few examples -->
|
||||
|
||||
1. Copy the DMA Reports V3.1.pbix file locally.
|
||||
2. Open the file using Power BI.
|
||||
|
||||
<a name=sample-details></a>
|
||||
|
||||
## Sample details
|
||||
|
||||
This includes the following Power BI reports, for consolidated migration assessments.
|
||||
- **Dashboard:** Provides snapshot stats and a drill down report.
|
||||
- **On Premise Upgrade Readiness:** Shows the percentage upgrade success for you assessed databases.
|
||||
- **On Premise Feature Parity Report -- Details:** Highlights new features that can be used for database in the target SQL Server version.
|
||||
- **Azure SQL DB Upgrade Readiness:** Shows the percentage upgrade success for databases assessed for Azure SQL DB migrations.
|
||||
- **Azure SQL DB Unsuppported Features:** Shows features that in your existing databases are not supported in Azure SQL DB (v12).
|
||||
|
||||
<a name=related-links></a>
|
||||
|
||||
## Related Links
|
||||
|
||||
For more information, see these articles:
|
||||
|
||||
[Report on your Consolidated Assessments using Power BI (Data Migration Assistant)](https://docs.microsoft.com/sql/dma/dma-powerbiassesreport)
|
||||
@@ -0,0 +1,926 @@
|
||||
#This Sample Code is provided for the purpose of illustration only and is not intended to be used in a production environment.
|
||||
#THIS SAMPLE CODE AND ANY RELATED INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
|
||||
#INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
#We grant you a nonexclusive, royalty-free right to use and modify the Sample Code and to reproduce and distribute
|
||||
#the object code form of the Sample Code, provided that you agree:
|
||||
#(i) to not use Our name, logo, or trademarks to market Your software product in which the Sample Code is embedded;
|
||||
#(ii) to include a valid copyright notice on Your software product in which the Sample Code is embedded; and
|
||||
#(iii) to indemnify, hold harmless, and defend Us and our suppliers from and against any claims or lawsuits, including attorneys' fees, that arise or result from the use or distribution of the Sample Code.
|
||||
# -----------------------------------------------------------------------------
|
||||
#
|
||||
# Script: DMA_Processor.ps1
|
||||
# Author: Chris Lound - Senior Premier Field Engineer - Data Platform.
|
||||
# Date: 08/02/2017
|
||||
# Version: 5.0
|
||||
# Synopsis: Create reporting objects and loads JSON files from DMA output folder into SQL server
|
||||
# Keywords:
|
||||
# Notes: A processed folder is created in the root folder of the folder containing the DMA JSON output (user specified). Script currently only supports windows authentication to SQL Server.
|
||||
# Comments:
|
||||
# 1.0 Initial Release - 22/11/2016
|
||||
# 2.0 Refactored JSON shredder for SQL2014 and below. Made this the only shredding function by removing the SQL2016 dependency
|
||||
# 3.0 Built in weighted breaking changes. Added table to support breaking change weighting and updated view to use it for reporting. Also removed Azure Artifacts
|
||||
# 3.1 Change importdate type to datetime. Added DBOwner column for reportdata table. - 16/02/2017
|
||||
# 4.0 Added DMAWarehouse objects. Cleaned up output into console
|
||||
# 4.1 Added Warehouse views, AssessmentTarget and AssessmentName properties and dependants
|
||||
# 5.0 Added support for feature parity for azure targets (new table, table type, stored procedure, datatable (ps), shredding loop (ps).
|
||||
# Added error handling for failed dataset fills. Added support for only moving files when they are actually processed. if they fail they dont get moved.
|
||||
# Added option to create data warehouse
|
||||
# Altered UpgradeSuccessRanking view to exclude TargetCompatibilityMode of 'NA' (Azure migrations)
|
||||
# REMOVED data warehouse scripts from this specific script version
|
||||
# Split UpgradeSuccessRanking views into 2, 1 for onprem and 1 for azure to fix assessment counts in powerbi
|
||||
|
||||
#------------------------------------------------------------------------------------ CREATE FUNCTIONS -------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#Import JSON to SQL on prem or azure
|
||||
function dmaProcessor
|
||||
{
|
||||
param(
|
||||
[parameter(Mandatory)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string] $serverName,
|
||||
|
||||
[parameter(Mandatory)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string] $databaseName,
|
||||
|
||||
[parameter(Mandatory)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string] $jsonDirectory,
|
||||
|
||||
[parameter(Mandatory)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[ValidateSet("SQLServer")]
|
||||
[string] $processTo
|
||||
)
|
||||
|
||||
#Create database objects
|
||||
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null
|
||||
$srv = New-Object Microsoft.SqlServer.Management.SMO.Server($serverName)
|
||||
|
||||
#create reporting database
|
||||
$dbCheck = $srv.Databases | Where {$_.Name -eq "$databaseName"} | Select Name
|
||||
if(!$dbCheck)
|
||||
{
|
||||
$db = New-Object Microsoft.SqlServer.Management.Smo.Database ($srv, $databaseName)
|
||||
|
||||
$db.Create()
|
||||
|
||||
Write-Host("Database $databaseName created successfully") -ForegroundColor Green
|
||||
}
|
||||
else
|
||||
{
|
||||
$db=$srv.Databases.Item($databaseName)
|
||||
Write-Host ("Database $databaseName already exists") -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
#create ReportData table
|
||||
$tableCheck = $db.Tables | Where {$_.Name -eq "ReportData"}
|
||||
if(!$tableCheck)
|
||||
{
|
||||
$ReportDatatbl = New-Object Microsoft.SqlServer.Management.Smo.Table($db, "ReportData")
|
||||
|
||||
$col1 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "ImportDate", [Microsoft.SqlServer.Management.Smo.DataType]::DateTime)
|
||||
$col2 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "InstanceName", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(50))
|
||||
$col3 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "Status", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(30))
|
||||
$col4 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "Name", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(255))
|
||||
$col5 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "SizeMB", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(30))
|
||||
$col6 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "SourceCompatibilityLevel", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(15))
|
||||
$col7 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "TargetCompatibilityLevel", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(15))
|
||||
$col8 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "Category", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(30))
|
||||
$col9 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "Severity", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(15))
|
||||
$col10 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "ChangeCategory", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(20))
|
||||
$col11 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "RuleId", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(100))
|
||||
$col12 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "Title", [Microsoft.SqlServer.Management.Smo.DataType]::VarCharMax)
|
||||
$col13 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "Impact", [Microsoft.SqlServer.Management.Smo.DataType]::VarCharMax)
|
||||
$col14 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "Recommendation", [Microsoft.SqlServer.Management.Smo.DataType]::VarCharMax)
|
||||
$col15 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "MoreInfo", [Microsoft.SqlServer.Management.Smo.DataType]::VarCharMax)
|
||||
$col16 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "ImpactedObjectName", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(255))
|
||||
$col17 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "ImpactedObjectType", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(50))
|
||||
$col18 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "ImpactDetail", [Microsoft.SqlServer.Management.Smo.DataType]::VarCharMax)
|
||||
$col19 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "DBOwner", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(128))
|
||||
$col20 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "AssessmentTarget", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(50))
|
||||
$col21 = New-Object Microsoft.SqlServer.Management.Smo.Column($ReportDatatbl, "AssessmentName", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(128))
|
||||
|
||||
$ReportDatatbl.Columns.Add($col1)
|
||||
$ReportDatatbl.Columns.Add($col2)
|
||||
$ReportDatatbl.Columns.Add($col3)
|
||||
$ReportDatatbl.Columns.Add($col4)
|
||||
$ReportDatatbl.Columns.Add($col5)
|
||||
$ReportDatatbl.Columns.Add($col6)
|
||||
$ReportDatatbl.Columns.Add($col7)
|
||||
$ReportDatatbl.Columns.Add($col8)
|
||||
$ReportDatatbl.Columns.Add($col9)
|
||||
$ReportDatatbl.Columns.Add($col10)
|
||||
$ReportDatatbl.Columns.Add($col11)
|
||||
$ReportDatatbl.Columns.Add($col12)
|
||||
$ReportDatatbl.Columns.Add($col13)
|
||||
$ReportDatatbl.Columns.Add($col14)
|
||||
$ReportDatatbl.Columns.Add($col15)
|
||||
$ReportDatatbl.Columns.Add($col16)
|
||||
$ReportDatatbl.Columns.Add($col17)
|
||||
$ReportDatatbl.Columns.Add($col18)
|
||||
$ReportDatatbl.Columns.Add($col19)
|
||||
$ReportDatatbl.Columns.Add($col20)
|
||||
$ReportDatatbl.Columns.Add($col21)
|
||||
|
||||
$ReportDatatbl.Create()
|
||||
Write-Host ("Table ReportData created successfully") -ForegroundColor Green
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host ("Table ReportData already exists") -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
#create AzureFeatureParity table
|
||||
$tableCheck2 = $db.Tables | Where {$_.Name -eq "AzureFeatureParity"}
|
||||
if(!$tableCheck2)
|
||||
{
|
||||
$AzureReportDatatbl = New-Object Microsoft.SqlServer.Management.Smo.Table($db, "AzureFeatureParity")
|
||||
|
||||
$col1 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureReportDatatbl, "ImportDate", [Microsoft.SqlServer.Management.Smo.DataType]::DateTime)
|
||||
$col2 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureReportDatatbl, "ServerName", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(128))
|
||||
$col3 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureReportDatatbl, "Version", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(15))
|
||||
$col4 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureReportDatatbl, "Status", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(10))
|
||||
$col5 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureReportDatatbl, "Category", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(50))
|
||||
$col6 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureReportDatatbl, "Severity", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(50))
|
||||
$col7 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureReportDatatbl, "FeatureParityCategory", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(50))
|
||||
$col8 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureReportDatatbl, "RuleID", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(100))
|
||||
$col9 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureReportDatatbl, "Title", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(1000))
|
||||
$col10 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureReportDatatbl, "Impact", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(1000))
|
||||
$col11 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureReportDatatbl, "Recommendation", [Microsoft.SqlServer.Management.Smo.DataType]::VarCharMax)
|
||||
$col12 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureReportDatatbl, "MoreInfo", [Microsoft.SqlServer.Management.Smo.DataType]::VarCharMax)
|
||||
$col13 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureReportDatatbl, "ImpactedDatabasename", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(128))
|
||||
$col14 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureReportDatatbl, "ImpactedObjectType", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(30))
|
||||
$col15 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureReportDatatbl, "ImpactDetail", [Microsoft.SqlServer.Management.Smo.DataType]::VarCharMax)
|
||||
|
||||
$AzureReportDatatbl.Columns.Add($col1)
|
||||
$AzureReportDatatbl.Columns.Add($col2)
|
||||
$AzureReportDatatbl.Columns.Add($col3)
|
||||
$AzureReportDatatbl.Columns.Add($col4)
|
||||
$AzureReportDatatbl.Columns.Add($col5)
|
||||
$AzureReportDatatbl.Columns.Add($col6)
|
||||
$AzureReportDatatbl.Columns.Add($col7)
|
||||
$AzureReportDatatbl.Columns.Add($col8)
|
||||
$AzureReportDatatbl.Columns.Add($col9)
|
||||
$AzureReportDatatbl.Columns.Add($col10)
|
||||
$AzureReportDatatbl.Columns.Add($col11)
|
||||
$AzureReportDatatbl.Columns.Add($col12)
|
||||
$AzureReportDatatbl.Columns.Add($col13)
|
||||
$AzureReportDatatbl.Columns.Add($col14)
|
||||
$AzureReportDatatbl.Columns.Add($col15)
|
||||
|
||||
$AzureReportDatatbl.Create()
|
||||
Write-Host ("Table AzureFeatureParity created successfully") -ForegroundColor Green
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host ("Table AzureFeatureParity already exists") -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
#create BreakingChangeWeighting table
|
||||
$tableCheck3 = $db.Tables | Where {$_.Name -eq "BreakingChangeWeighting"}
|
||||
if(!$tableCheck3)
|
||||
{
|
||||
$BreakingChangetbl = New-Object Microsoft.SqlServer.Management.Smo.Table($db, "BreakingChangeWeighting")
|
||||
|
||||
$col1 = New-Object Microsoft.SqlServer.Management.Smo.Column($BreakingChangetbl, "RuleId", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(36))
|
||||
$col1.Nullable = $false
|
||||
$col2 = New-Object Microsoft.SqlServer.Management.Smo.Column($BreakingChangetbl, "Title", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(150))
|
||||
$col3 = New-Object Microsoft.SqlServer.Management.Smo.Column($BreakingChangetbl, "Effort", [Microsoft.SqlServer.Management.Smo.DataType]::TinyInt)
|
||||
$col4 = New-Object Microsoft.SqlServer.Management.Smo.Column($BreakingChangetbl, "FixTime", [Microsoft.SqlServer.Management.Smo.DataType]::TinyInt)
|
||||
$col5 = New-Object Microsoft.SqlServer.Management.Smo.Column($BreakingChangetbl, "Cost", [Microsoft.SqlServer.Management.Smo.DataType]::TinyInt)
|
||||
$col6 = New-Object Microsoft.SqlServer.Management.Smo.Column($BreakingChangetbl, "ChangeRank", [Microsoft.SqlServer.Management.Smo.DataType]::TinyInt)
|
||||
$Col6.Computed = $True
|
||||
$Col6.ComputedText = "(Effort + FixTime + Cost) / 3"
|
||||
|
||||
$BreakingChangetbl.Columns.Add($col1)
|
||||
$BreakingChangetbl.Columns.Add($col2)
|
||||
$BreakingChangetbl.Columns.Add($col3)
|
||||
$BreakingChangetbl.Columns.Add($col4)
|
||||
$BreakingChangetbl.Columns.Add($col5)
|
||||
$BreakingChangetbl.Columns.Add($col6)
|
||||
|
||||
$BreakingChangetbl.Create()
|
||||
|
||||
$PK = New-Object Microsoft.SqlServer.Management.Smo.Index($BreakingChangetbl,"PK_BreakingChangeWeighting_RuleId")
|
||||
$PK.IndexKeyType = "DriPrimaryKey"
|
||||
|
||||
$IdxCol = New-Object Microsoft.SqlServer.Management.Smo.IndexedColumn($PK, $col1.Name)
|
||||
$PK.IndexedColumns.Add($IdxCol)
|
||||
$PK.Create()
|
||||
|
||||
Write-Host ("Table BreakingChangeWeighting created successfully") -ForegroundColor Green
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host ("Table BreakingChangeWeighting already exists") -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
#Create views
|
||||
$vwCheck1 = $db.Views | Where {$_.Name -eq "DatabaseCategoryRanking"}
|
||||
if(!$vwCheck1)
|
||||
{
|
||||
$vwDatabaseCategoryRanking = New-Object -TypeName Microsoft.SqlServer.Management.SMO.View -argumentlist $db, "DatabaseCategoryRanking", "dbo"
|
||||
|
||||
$vwDatabaseCategoryRanking.TextHeader = "CREATE VIEW [dbo].[DatabaseCategoryRanking] AS"
|
||||
$vwDatabaseCategoryRanking.TextBody=@"
|
||||
WITH DatabaseRanking
|
||||
AS
|
||||
(
|
||||
SELECT [Name]
|
||||
,ChangeCategory
|
||||
,COUNT(*) AS "NumberOfIssues"
|
||||
,(CONVERT(NUMERIC(5,2),COUNT(*))/(SELECT CONVERT(NUMERIC(5,2),COUNT(*)) FROM reportdata r2 Where r1.[name] = r2.[name])) * 100 AS "ChangeCategoryPercentage"
|
||||
FROM reportdata r1
|
||||
GROUP BY [Name], ChangeCategory
|
||||
)
|
||||
SELECT [Name] AS "DatabaseName"
|
||||
,ChangeCategory
|
||||
,ChangeCategoryPercentage
|
||||
FROM DatabaseRanking;
|
||||
"@
|
||||
|
||||
$vwDatabaseCategoryRanking.Create()
|
||||
Write-Host ("View DatabaseCategoryRanking created successfully") -ForegroundColor Green
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host ("View DatabaseCategoryRanking already exists") -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
$vwCheck2 = $db.Views | Where {$_.Name -eq "UpgradeSuccessRanking"}
|
||||
if(!$vwCheck2)
|
||||
{
|
||||
$vwUpgradeSuccessRanking = New-Object -TypeName Microsoft.SqlServer.Management.SMO.View -argumentlist $db, "UpgradeSuccessRanking", "dbo"
|
||||
|
||||
$vwUpgradeSuccessRanking.TextHeader = "CREATE VIEW [dbo].[UpgradeSuccessRanking] AS"
|
||||
$vwUpgradeSuccessRanking.TextBody=@"
|
||||
WITH issuecount
|
||||
AS
|
||||
(
|
||||
-- currently doesn't take into account diminishing returns for repeating issues
|
||||
-- removed NotDefined as these are for feature parity, not migration blockers and should therefore be excluded in calculations
|
||||
SELECT InstanceName
|
||||
,NAME
|
||||
,TargetCompatibilityLevel
|
||||
,COALESCE(CASE changecategory WHEN 'BehaviorChange' THEN COUNT(*) END,0) AS 'BehaviorChange'
|
||||
,COALESCE(CASE changecategory WHEN 'Deprecated' THEN COUNT(*) END,0) AS 'DeprecatedCount'
|
||||
,COALESCE(CASE changecategory WHEN 'BreakingChange' THEN SUM(ChangeRank) END ,0) AS 'BreakingChange'
|
||||
--,COALESCE(CASE changecategory WHEN 'NotDefined' THEN COUNT(*) END,0) AS 'NotDefined'
|
||||
,COALESCE(CASE changecategory WHEN 'MigrationBlocker' THEN COUNT(*) END,0) AS 'MigrationBlocker'
|
||||
FROM reportdata rd
|
||||
LEFT JOIN BreakingChangeWeighting bcw
|
||||
ON rd.RuleId = bcw.ruleid
|
||||
WHERE changecategory != 'NotDefined'
|
||||
and TargetCompatibilityLevel != 'NA'
|
||||
GROUP BY InstanceName,name, changecategory, TargetCompatibilityLevel
|
||||
),
|
||||
distinctissues
|
||||
AS
|
||||
(
|
||||
SELECT InstanceName
|
||||
,NAME
|
||||
,TargetCompatibilityLevel
|
||||
,MAX(BehaviorChange) AS 'BehaviorChange'
|
||||
,MAX(DeprecatedCount) AS 'DeprecatedCount'
|
||||
,MAX(BreakingChange) AS 'BreakingChange'
|
||||
--,MAX(NotDefined) AS 'NotDefined'
|
||||
,MAX(MigrationBlocker) AS 'MigrationBlocker'
|
||||
FROM issuecount
|
||||
GROUP BY InstanceName,name, TargetCompatibilityLevel
|
||||
),
|
||||
IssueTotaled
|
||||
AS
|
||||
(
|
||||
SELECT *, behaviorchange + deprecatedcount + breakingchange + MigrationBlocker AS 'Total'
|
||||
FROM distinctissues
|
||||
),
|
||||
RankedDatabases
|
||||
AS
|
||||
(
|
||||
SELECT InstanceName
|
||||
,Name
|
||||
,TargetCompatibilityLevel
|
||||
,CAST(100-((BehaviorChange + 0.00) / (total + 0.00)) * 100 AS DECIMAL(5,2)) AS 'BehaviorChange'
|
||||
,CAST(100-((DeprecatedCount + 0.00) / (total + 0.00)) * 100 AS DECIMAL(5,2)) AS 'DeprecatedCount'
|
||||
,CAST(100-((BreakingChange + 0.00) / (total + 0.00)) * 100 AS DECIMAL(5,2)) AS 'BreakingChange'
|
||||
--,CAST(100-((NotDefined + 0.00) / (total + 0.00)) * 100 AS DECIMAL(5,2)) AS 'NotDefined'
|
||||
,CAST(100-((MigrationBlocker + 0.00) / (total + 0.00)) * 100 AS DECIMAL(5,2)) AS 'MigrationBlocker'
|
||||
FROM IssueTotaled
|
||||
)
|
||||
-- This section will ensure that if there are 0 issues in a category we return 1. This ensures the reports show data
|
||||
SELECT InstanceName
|
||||
,[Name]
|
||||
,TargetCompatibilityLevel
|
||||
,CASE WHEN BehaviorChange > 0 THEN BehaviorChange ELSE 1 END AS "BehaviorChange"
|
||||
,CASE WHEN DeprecatedCount > 0 THEN DeprecatedCount ELSE 1 END AS "DeprecatedCount"
|
||||
,CASE WHEN BreakingChange > 0 THEN BreakingChange ELSE 1 END AS "BreakingChange"
|
||||
--,CASE WHEN NotDefined > 0 THEN NotDefined ELSE 1 END AS "NotDefined"
|
||||
,CASE WHEN MigrationBlocker > 0 THEN MigrationBlocker ELSE 1 END AS "MigrationBlocker"
|
||||
FROM RankedDatabases
|
||||
"@
|
||||
|
||||
$vwUpgradeSuccessRanking.Create()
|
||||
Write-Host ("View UpgradeSuccessRanking created successfully") -ForegroundColor Green
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host ("View UpgradeSuccessRanking already exists") -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
$vwCheck3 = $db.Views | Where {$_.Name -eq "UpgradeSuccessRanking_OnPrem"}
|
||||
if(!$vwCheck3)
|
||||
{
|
||||
$vwUpgradeSuccessRankingop = New-Object -TypeName Microsoft.SqlServer.Management.SMO.View -argumentlist $db, "UpgradeSuccessRanking_OnPrem", "dbo"
|
||||
|
||||
$vwUpgradeSuccessRankingop.TextHeader = "CREATE VIEW [dbo].[UpgradeSuccessRanking_OnPrem] AS"
|
||||
$vwUpgradeSuccessRankingop.TextBody=@"
|
||||
WITH issuecount
|
||||
AS
|
||||
(
|
||||
-- currently doesn't take into account diminishing returns for repeating issues
|
||||
-- removed NotDefined as these are for feature parity, not migration blockers and should therefore be excluded in calculations
|
||||
SELECT InstanceName
|
||||
,NAME
|
||||
,TargetCompatibilityLevel
|
||||
,COALESCE(CASE changecategory WHEN 'BehaviorChange' THEN COUNT(*) END,0) AS 'BehaviorChange'
|
||||
,COALESCE(CASE changecategory WHEN 'Deprecated' THEN COUNT(*) END,0) AS 'DeprecatedCount'
|
||||
,COALESCE(CASE changecategory WHEN 'BreakingChange' THEN SUM(ChangeRank) END ,0) AS 'BreakingChange'
|
||||
FROM ReportData rd
|
||||
LEFT JOIN BreakingChangeWeighting bcw
|
||||
ON rd.RuleId = bcw.ruleid
|
||||
WHERE ChangeCategory != 'NotDefined'
|
||||
AND TargetCompatibilityLevel != 'NA'
|
||||
AND AssessmentTarget IN ('SqlServer2012', 'SqlServer2014', 'SqlServer2016')
|
||||
GROUP BY InstanceName,name, changecategory, TargetCompatibilityLevel
|
||||
),
|
||||
distinctissues
|
||||
AS
|
||||
(
|
||||
SELECT InstanceName
|
||||
,NAME
|
||||
,TargetCompatibilityLevel
|
||||
,MAX(BehaviorChange) AS 'BehaviorChange'
|
||||
,MAX(DeprecatedCount) AS 'DeprecatedCount'
|
||||
,MAX(BreakingChange) AS 'BreakingChange'
|
||||
FROM issuecount
|
||||
GROUP BY InstanceName,name, TargetCompatibilityLevel
|
||||
),
|
||||
IssueTotaled
|
||||
AS
|
||||
(
|
||||
SELECT *, behaviorchange + deprecatedcount + breakingchange AS 'Total'
|
||||
FROM distinctissues
|
||||
),
|
||||
RankedDatabases
|
||||
AS
|
||||
(
|
||||
SELECT InstanceName
|
||||
,Name
|
||||
,TargetCompatibilityLevel
|
||||
,CAST(100-((BehaviorChange + 0.00) / (total + 0.00)) * 100 AS DECIMAL(5,2)) AS 'BehaviorChange'
|
||||
,CAST(100-((DeprecatedCount + 0.00) / (total + 0.00)) * 100 AS DECIMAL(5,2)) AS 'DeprecatedCount'
|
||||
,CAST(100-((BreakingChange + 0.00) / (total + 0.00)) * 100 AS DECIMAL(5,2)) AS 'BreakingChange'
|
||||
FROM IssueTotaled
|
||||
)
|
||||
-- This section will ensure that if there are 0 issues in a category we return 1. This ensures the reports show data
|
||||
SELECT InstanceName
|
||||
,[Name]
|
||||
,TargetCompatibilityLevel
|
||||
,CASE WHEN BehaviorChange > 0 THEN BehaviorChange ELSE 1 END AS "BehaviorChange"
|
||||
,CASE WHEN DeprecatedCount > 0 THEN DeprecatedCount ELSE 1 END AS "DeprecatedCount"
|
||||
,CASE WHEN BreakingChange > 0 THEN BreakingChange ELSE 1 END AS "BreakingChange"
|
||||
FROM RankedDatabases
|
||||
|
||||
"@
|
||||
|
||||
$vwUpgradeSuccessRankingop.Create()
|
||||
Write-Host ("View UpgradeSuccessRanking_OnPrem created successfully") -ForegroundColor Green
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host ("View UpgradeSuccessRanking_OnPrem already exists") -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
|
||||
$vwCheck4 = $db.Views | Where {$_.Name -eq "UpgradeSuccessRanking_Azure"}
|
||||
if(!$vwCheck4)
|
||||
{
|
||||
$vwUpgradeSuccessRankingaz = New-Object -TypeName Microsoft.SqlServer.Management.SMO.View -argumentlist $db, "UpgradeSuccessRanking_Azure", "dbo"
|
||||
|
||||
$vwUpgradeSuccessRankingaz.TextHeader = "CREATE VIEW [dbo].[UpgradeSuccessRanking_Azure] AS"
|
||||
$vwUpgradeSuccessRankingaz.TextBody=@"
|
||||
WITH issuecount
|
||||
AS
|
||||
(
|
||||
-- currently doesn't take into account diminishing returns for repeating issues
|
||||
-- removed NotDefined as these are for feature parity, not migration blockers and should therefore be excluded in calculations
|
||||
SELECT InstanceName
|
||||
,NAME
|
||||
,TargetCompatibilityLevel
|
||||
,COALESCE(CASE changecategory WHEN 'BehaviorChange' THEN COUNT(*) END,0) AS 'BehaviorChange'
|
||||
,COALESCE(CASE changecategory WHEN 'Deprecated' THEN COUNT(*) END,0) AS 'DeprecatedCount'
|
||||
,COALESCE(CASE changecategory WHEN 'BreakingChange' THEN SUM(ChangeRank) END ,0) AS 'BreakingChange'
|
||||
,COALESCE(CASE changecategory WHEN 'MigrationBlocker' THEN COUNT(*) END,0) AS 'MigrationBlocker'
|
||||
FROM ReportData rd
|
||||
LEFT JOIN BreakingChangeWeighting bcw
|
||||
ON rd.RuleId = bcw.ruleid
|
||||
WHERE changecategory != 'NotDefined'
|
||||
AND TargetCompatibilityLevel != 'NA'
|
||||
AND AssessmentTarget = 'AzureSQLDatabaseV12'
|
||||
GROUP BY InstanceName, [Name], changecategory, TargetCompatibilityLevel
|
||||
),
|
||||
distinctissues
|
||||
AS
|
||||
(
|
||||
SELECT InstanceName
|
||||
,[Name]
|
||||
,TargetCompatibilityLevel
|
||||
,MAX(BehaviorChange) AS 'BehaviorChange'
|
||||
,MAX(DeprecatedCount) AS 'DeprecatedCount'
|
||||
,MAX(BreakingChange) AS 'BreakingChange'
|
||||
,MAX(MigrationBlocker) AS 'MigrationBlocker'
|
||||
FROM issuecount
|
||||
GROUP BY InstanceName, [Name], TargetCompatibilityLevel
|
||||
),
|
||||
IssueTotaled
|
||||
AS
|
||||
(
|
||||
SELECT *, behaviorchange + deprecatedcount + breakingchange + MigrationBlocker AS 'Total'
|
||||
FROM distinctissues
|
||||
),
|
||||
RankedDatabases
|
||||
AS
|
||||
(
|
||||
SELECT InstanceName
|
||||
,[Name]
|
||||
,TargetCompatibilityLevel
|
||||
,CAST(100-((BehaviorChange + 0.00) / (total + 0.00)) * 100 AS DECIMAL(5,2)) AS 'BehaviorChange'
|
||||
,CAST(100-((DeprecatedCount + 0.00) / (total + 0.00)) * 100 AS DECIMAL(5,2)) AS 'DeprecatedCount'
|
||||
,CAST(100-((BreakingChange + 0.00) / (total + 0.00)) * 100 AS DECIMAL(5,2)) AS 'BreakingChange'
|
||||
,CAST(100-((MigrationBlocker + 0.00) / (total + 0.00)) * 100 AS DECIMAL(5,2)) AS 'MigrationBlocker'
|
||||
FROM IssueTotaled
|
||||
)
|
||||
-- This section will ensure that if there are 0 issues in a category we return 1. This ensures the reports show data
|
||||
SELECT InstanceName
|
||||
,[Name]
|
||||
,TargetCompatibilityLevel
|
||||
,CASE WHEN BehaviorChange > 0 THEN BehaviorChange ELSE 1 END AS "BehaviorChange"
|
||||
,CASE WHEN DeprecatedCount > 0 THEN DeprecatedCount ELSE 1 END AS "DeprecatedCount"
|
||||
,CASE WHEN BreakingChange > 0 THEN BreakingChange ELSE 1 END AS "BreakingChange"
|
||||
,CASE WHEN MigrationBlocker > 0 THEN MigrationBlocker ELSE 1 END AS "MigrationBlocker"
|
||||
FROM RankedDatabases
|
||||
"@
|
||||
|
||||
$vwUpgradeSuccessRankingaz.Create()
|
||||
Write-Host ("View UpgradeSuccessRanking_Azure created successfully") -ForegroundColor Green
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host ("View UpgradeSuccessRanking_Azure already exists") -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
#Create Table Types
|
||||
$ttCheck = $db.UserDefinedTableTypes | Where {$_.Name -eq "JSONResults"}
|
||||
if(!$ttCheck)
|
||||
{
|
||||
$JSONResultstt = New-Object -TypeName Microsoft.SqlServer.Management.Smo.UserDefinedTableType -ArgumentList $db, "JSONResults"
|
||||
|
||||
$col1 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "ImportDate", [Microsoft.SqlServer.Management.Smo.DataType]::DateTime)
|
||||
$col2 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "InstanceName", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(50))
|
||||
$col3 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "Status", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(30))
|
||||
$col4 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "Name", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(255))
|
||||
$col5 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "SizeMB", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(30))
|
||||
$col6 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "SourceCompatibilityLevel", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(15))
|
||||
$col7 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "TargetCompatibilityLevel", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(15))
|
||||
$col8 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "Category", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(30))
|
||||
$col9 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "Severity", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(15))
|
||||
$col10 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "ChangeCategory", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(20))
|
||||
$col11 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "RuleId", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(100))
|
||||
$col12 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "Title", [Microsoft.SqlServer.Management.Smo.DataType]::VarCharMax)
|
||||
$col13 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "Impact", [Microsoft.SqlServer.Management.Smo.DataType]::VarCharMax)
|
||||
$col14 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "Recommendation", [Microsoft.SqlServer.Management.Smo.DataType]::VarCharMax)
|
||||
$col15 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "MoreInfo", [Microsoft.SqlServer.Management.Smo.DataType]::VarCharMax)
|
||||
$col16 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "ImpactedObjectName", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(255))
|
||||
$col17 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "ImpactedObjectType", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(50))
|
||||
$col18 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "ImpactDetail", [Microsoft.SqlServer.Management.Smo.DataType]::VarCharMax)
|
||||
$col19 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "DBOwner", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(128))
|
||||
$col20 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "AssessmentTarget", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(50))
|
||||
$col21 = New-Object Microsoft.SqlServer.Management.Smo.Column($JSONResultstt, "AssessmentName", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(128))
|
||||
|
||||
$JSONResultstt.Columns.Add($col1)
|
||||
$JSONResultstt.Columns.Add($col2)
|
||||
$JSONResultstt.Columns.Add($col3)
|
||||
$JSONResultstt.Columns.Add($col4)
|
||||
$JSONResultstt.Columns.Add($col5)
|
||||
$JSONResultstt.Columns.Add($col6)
|
||||
$JSONResultstt.Columns.Add($col7)
|
||||
$JSONResultstt.Columns.Add($col8)
|
||||
$JSONResultstt.Columns.Add($col9)
|
||||
$JSONResultstt.Columns.Add($col10)
|
||||
$JSONResultstt.Columns.Add($col11)
|
||||
$JSONResultstt.Columns.Add($col12)
|
||||
$JSONResultstt.Columns.Add($col13)
|
||||
$JSONResultstt.Columns.Add($col14)
|
||||
$JSONResultstt.Columns.Add($col15)
|
||||
$JSONResultstt.Columns.Add($col16)
|
||||
$JSONResultstt.Columns.Add($col17)
|
||||
$JSONResultstt.Columns.Add($col18)
|
||||
$JSONResultstt.Columns.Add($col19)
|
||||
$JSONResultstt.Columns.Add($col20)
|
||||
$JSONResultstt.Columns.Add($col21)
|
||||
|
||||
$JSONResultstt.Create()
|
||||
Write-Host ("Table Type JSONResults created successfully") -ForegroundColor Green
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host ("Table Type JSONResults already exists") -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
$ttCheck2 = $db.UserDefinedTableTypes | Where {$_.Name -eq "AzureFeatureParityResults"}
|
||||
if(!$ttCheck2)
|
||||
{
|
||||
$AzureParityResultstt = New-Object -TypeName Microsoft.SqlServer.Management.Smo.UserDefinedTableType -ArgumentList $db, "AzureFeatureParityResults"
|
||||
|
||||
$col1 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureParityResultstt, "ImportDate", [Microsoft.SqlServer.Management.Smo.DataType]::DateTime)
|
||||
$col2 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureParityResultstt, "ServerName", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(128))
|
||||
$col3 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureParityResultstt, "Version", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(15))
|
||||
$col4 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureParityResultstt, "Status", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(10))
|
||||
$col5 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureParityResultstt, "Category", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(50))
|
||||
$col6 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureParityResultstt, "Severity", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(50))
|
||||
$col7 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureParityResultstt, "FeatureParityCategory", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(50))
|
||||
$col8 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureParityResultstt, "RuleID", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(100))
|
||||
$col9 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureParityResultstt, "Title", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(1000))
|
||||
$col10 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureParityResultstt, "Impact", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(1000))
|
||||
$col11 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureParityResultstt, "Recommendation", [Microsoft.SqlServer.Management.Smo.DataType]::VarCharMax)
|
||||
$col12 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureParityResultstt, "MoreInfo", [Microsoft.SqlServer.Management.Smo.DataType]::VarCharMax)
|
||||
$col13 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureParityResultstt, "ImpactedDatabasename", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(128))
|
||||
$col14 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureParityResultstt, "ImpactedObjectType", [Microsoft.SqlServer.Management.Smo.DataType]::VarChar(30))
|
||||
$col15 = New-Object Microsoft.SqlServer.Management.Smo.Column($AzureParityResultstt, "ImpactDetail", [Microsoft.SqlServer.Management.Smo.DataType]::VarCharMax)
|
||||
|
||||
|
||||
$AzureParityResultstt.Columns.Add($col1)
|
||||
$AzureParityResultstt.Columns.Add($col2)
|
||||
$AzureParityResultstt.Columns.Add($col3)
|
||||
$AzureParityResultstt.Columns.Add($col4)
|
||||
$AzureParityResultstt.Columns.Add($col5)
|
||||
$AzureParityResultstt.Columns.Add($col6)
|
||||
$AzureParityResultstt.Columns.Add($col7)
|
||||
$AzureParityResultstt.Columns.Add($col8)
|
||||
$AzureParityResultstt.Columns.Add($col9)
|
||||
$AzureParityResultstt.Columns.Add($col10)
|
||||
$AzureParityResultstt.Columns.Add($col11)
|
||||
$AzureParityResultstt.Columns.Add($col12)
|
||||
$AzureParityResultstt.Columns.Add($col13)
|
||||
$AzureParityResultstt.Columns.Add($col14)
|
||||
$AzureParityResultstt.Columns.Add($col15)
|
||||
|
||||
$AzureParityResultstt.Create()
|
||||
Write-Host ("Table Type AzureFeatureParityResults created successfully") -ForegroundColor Green
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host ("Table Type AzureFeatureParityResults already exists") -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
#Create Stored Procedures
|
||||
$procCheck = $db.StoredProcedures | Where {$_.Name -eq "JSONResults_Insert"}
|
||||
if(!$procCheck)
|
||||
{
|
||||
$JSONResults_Insert = New-Object -TypeName Microsoft.SqlServer.Management.Smo.StoredProcedure -ArgumentList $db, "JSONResults_Insert", "dbo"
|
||||
|
||||
$JSONResults_Insert.TextHeader = "CREATE PROCEDURE dbo.JSONResults_Insert @JSONResults JSONResults READONLY AS"
|
||||
$JSONResults_Insert.TextBody = @"
|
||||
BEGIN
|
||||
|
||||
INSERT INTO dbo.ReportData (ImportDate, InstanceName, [Status], [Name], SizeMB, SourceCompatibilityLevel, TargetCompatibilityLevel, Category, Severity, ChangeCategory, RuleId, Title, Impact, Recommendation, MoreInfo, ImpactedObjectName, ImpactedObjectType, ImpactDetail, DBOwner, AssessmentTarget, AssessmentName)
|
||||
SELECT ImportDate, InstanceName, [Status], [Name], SizeMB, SourceCompatibilityLevel, TargetCompatibilityLevel, Category, Severity, ChangeCategory, RuleId, Title, Impact, Recommendation, MoreInfo, ImpactedObjectName, ImpactedObjectType, ImpactDetail, DBOwner, AssessmentTarget, AssessmentName
|
||||
FROM @JSONResults
|
||||
|
||||
END
|
||||
"@
|
||||
|
||||
$JSONResults_Insert.Create()
|
||||
Write-Host ("Stored Procedure JSONNResults_Insert created successfully") -ForegroundColor Green
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host ("Stored Procedure JSONNResults_Insert already exists") -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
$procCheck2 = $db.StoredProcedures | Where {$_.Name -eq "AzureFeatureParityResults_Insert"}
|
||||
if(!$procCheck2)
|
||||
{
|
||||
$AzureFeatureParityResults_Insert = New-Object -TypeName Microsoft.SqlServer.Management.Smo.StoredProcedure -ArgumentList $db, "AzureFeatureParityResults_Insert", "dbo"
|
||||
|
||||
$AzureFeatureParityResults_Insert.TextHeader = "CREATE PROCEDURE dbo.AzureFeatureParityResults_Insert @AzureFeatureParityResults AzureFeatureParityResults READONLY AS"
|
||||
$AzureFeatureParityResults_Insert.TextBody = @"
|
||||
BEGIN
|
||||
|
||||
INSERT INTO dbo.AzureFeatureParity (ImportDate, ServerName, Version, Status, Category, Severity, FeatureParityCategory, RuleID, Title, Impact, Recommendation, MoreInfo, ImpactedDatabasename, ImpactedObjectType, ImpactDetail)
|
||||
SELECT ImportDate, ServerName, Version, Status, Category, Severity, FeatureParityCategory, RuleID, Title, Impact, Recommendation, MoreInfo, ImpactedDatabasename, ImpactedObjectType, ImpactDetail
|
||||
FROM @AzureFeatureParityResults
|
||||
|
||||
END
|
||||
"@
|
||||
|
||||
$AzureFeatureParityResults_Insert.Create()
|
||||
Write-Host ("Stored Procedure AzureFeatureParityResults_Insert created successfully") -ForegroundColor Green
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host ("Stored Procedure AzureFeatureParityResults_Insert already exists") -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
# END CREATE DATABASE OBJECTS #
|
||||
|
||||
|
||||
#Make processed directory inside the folder that contains the json files
|
||||
if(!$jsonDirectory.EndsWith("\"))
|
||||
{
|
||||
$jsonDirectory = "$jsonDirectory\"
|
||||
}
|
||||
$processedDir = "$jsonDirectory`Processed"
|
||||
|
||||
if((Test-Path $processedDir) -eq $false)
|
||||
{
|
||||
new-item $processedDir -ItemType directory
|
||||
Write-Host ("Processed directory created successfully at [$processDir]") -ForegroundColor Green
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host ("Processed directory already exists") -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
# if there are no files to process stop importer
|
||||
$FileCheck = Get-ChildItem $jsonDirectory -Filter *.JSON
|
||||
if($FileCheck.Count -eq 0)
|
||||
{
|
||||
Write-Host ("There are no JSON assessment files to process") -ForegroundColor Yellow
|
||||
Break
|
||||
}
|
||||
|
||||
|
||||
$connectionString = "Server=$serverName;Database=$databaseName;Trusted_Connection=True;"
|
||||
|
||||
#Populate the breaking change reference data
|
||||
$RefDataCheck = $db.Tables | Where {$_.Name -eq "BreakingChangeWeighting"} | Select RowCount
|
||||
if($RefDataCheck.RowCount -eq 0)
|
||||
{
|
||||
|
||||
#populate static data into BreakingChangeWeighting
|
||||
|
||||
$CommandText = @'
|
||||
INSERT INTO BreakingChangeWeighting VALUES ('Microsoft.Rules.Data.Upgrade.UR00001','Syntax issue on the source server',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00006','BACKUP LOG WITH NO_LOG|TRUNCATE_ONLY statements are not supported',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00007','BACKUP/RESTORE TRANSACTION statements are deprecated or discontinued',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00013','COMPUTE clause is not allowed in database compatibility 110',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00020','Read-only databases cannot be upgraded',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00021','Verify all filegroups are writeable during the upgrade process',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00023','SQL Server native SOAP support is discontinued in SQL Server 2014 and above',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00044','Remove user-defined type (UDT)s named after the reserved GEOMETRY and GEOGRAPHY data types',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00050','Table hints in indexed view definitions are ignored in compatibility mode 80 and are not allowed in compatibility mode 90 or above',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00058','After upgrade, new reserved keywords cannot be used as identifiers',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00062','Tables and Columns named NEXT may lead to an error using compatibility Level 110 and above',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00086','XML is a reserved system type name',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00110','New column in output of sp_helptrigger may impact applications',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00113','SQL Mail has been discontinued',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00300','Remove the use of PASSWORD in BACKUP command',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00301','WITH CHECK OPTION is not supported in views that contain TOP in compatibility mode 90 and above',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00302','Discontinued DBCC commands referenced in your T-SQL objects',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00308','Legacy style RAISERROR calls should be replaced with modern equivalents',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00311','Detected statements that reference removed system stored procedures that are not available in database compatibility level 100 and higher',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00318','FOR BROWSE is not allowed in views in 90 or later compatibility modes',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00321','Non ANSI style left outer join usage',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00322','Non ANSI style right outer join usage',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00326','Constant expressions are not allowed in the ORDER BY clause in 90 or later compatibility modes',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00332','FASTFIRSTROW table hint usage',1,1,1),
|
||||
('Microsoft.Rules.Data.Upgrade.UR00336','Certain XPath functions are not allowed in OPENXML queries',1,1,1)
|
||||
'@
|
||||
|
||||
$conn = New-Object System.Data.SqlClient.SqlConnection $connectionString
|
||||
$conn.Open() | Out-Null
|
||||
|
||||
$cmd = New-Object System.Data.SqlClient.SqlCommand
|
||||
$cmd.Connection = $conn
|
||||
$cmd.CommandType = [System.Data.CommandType]"Text"
|
||||
$cmd.CommandText= $CommandText
|
||||
|
||||
$ds=New-Object system.Data.DataSet
|
||||
$da=New-Object system.Data.SqlClient.SqlDataAdapter($cmd)
|
||||
$da.fill($ds)
|
||||
$conn.Close()
|
||||
}
|
||||
|
||||
# importer for SQL2014 and previous versions. Done via PowerShell
|
||||
Get-ChildItem $jsonDirectory -Filter *.JSON |
|
||||
Foreach-Object {
|
||||
|
||||
$filename = $_.FullName
|
||||
|
||||
#ReportData datatable {
|
||||
$datatable = New-Object -type system.data.datatable
|
||||
$datatable.columns.add("ImportDate",[DateTime]) | Out-Null
|
||||
$datatable.columns.add("InstanceName",[String]) | Out-Null
|
||||
$datatable.columns.add("Status",[String]) | Out-Null
|
||||
$datatable.columns.add("Name",[String]) | Out-Null
|
||||
$datatable.columns.add("SizeMB",[String]) | Out-Null
|
||||
$datatable.columns.add("SourceCompatibilityLevel",[String]) | Out-Null
|
||||
$datatable.columns.add("TargetCompatibilityLevel",[String]) | Out-Null
|
||||
$datatable.columns.add("Category",[String]) | Out-Null
|
||||
$datatable.columns.add("Severity",[String]) | Out-Null
|
||||
$datatable.columns.add("ChangeCategory",[String]) | Out-Null
|
||||
$datatable.columns.add("RuleId",[String]) | Out-Null
|
||||
$datatable.columns.add("Title",[String]) | Out-Null
|
||||
$datatable.columns.add("Impact",[String]) | Out-Null
|
||||
$datatable.columns.add("Recommendation",[String]) | Out-Null
|
||||
$datatable.columns.add("MoreInfo",[String]) | Out-Null
|
||||
$datatable.columns.add("ImpactedObjectName",[String]) | Out-Null
|
||||
$datatable.columns.add("ImpactedObjectType",[String]) | Out-Null
|
||||
$datatable.columns.add("ImpactDetail",[string]) | Out-Null
|
||||
$datatable.columns.add("DBOwner",[string]) | Out-Null
|
||||
$datatable.columns.add("AssessmentTarget",[string]) | Out-Null
|
||||
$datatable.columns.add("AssessmentName",[string]) | Out-Null
|
||||
|
||||
#AzureFeatureParity datatable
|
||||
$azuredatatable = New-Object -type system.data.datatable
|
||||
$azuredatatable.columns.add("ImportDate",[DateTime]) | Out-Null
|
||||
$azuredatatable.columns.add("ServerName",[String]) | Out-Null
|
||||
$azuredatatable.columns.add("Version",[String]) | Out-Null
|
||||
$azuredatatable.columns.add("Status",[String]) | Out-Null
|
||||
$azuredatatable.columns.add("Category",[String]) | Out-Null
|
||||
$azuredatatable.columns.add("Severity",[String]) | Out-Null
|
||||
$azuredatatable.columns.add("FeatureParityCategory",[String]) | Out-Null
|
||||
$azuredatatable.columns.add("RuleID",[String]) | Out-Null
|
||||
$azuredatatable.columns.add("Title",[String]) | Out-Null
|
||||
$azuredatatable.columns.add("Impact",[String]) | Out-Null
|
||||
$azuredatatable.columns.add("Recommendation",[String]) | Out-Null
|
||||
$azuredatatable.columns.add("MoreInfo",[String]) | Out-Null
|
||||
$azuredatatable.columns.add("ImpactedDatabasename",[String]) | Out-Null
|
||||
$azuredatatable.columns.add("ImpactedObjectType",[String]) | Out-Null
|
||||
$azuredatatable.columns.add("ImpactDetail",[String]) | Out-Null
|
||||
|
||||
|
||||
$processStartTime = Get-Date
|
||||
$datetime = Get-Date
|
||||
$content = Get-Content $_.FullName -Raw
|
||||
|
||||
# when a database assessment fails the assessment recommendations and impacted objects arrays
|
||||
# will be blank. Setting them to default values allows for the errors to be captured
|
||||
$blankAssessmentRecommendations = (New-Object PSObject |
|
||||
Add-Member -PassThru NoteProperty CompatibilityLevel NA |
|
||||
Add-Member -PassThru NoteProperty Category NA |
|
||||
Add-Member -PassThru NoteProperty Severity NA |
|
||||
Add-Member -PassThru NoteProperty ChangeCategory NA |
|
||||
Add-Member -PassThru NoteProperty RuleId NA |
|
||||
Add-Member -PassThru NoteProperty Title NA |
|
||||
Add-Member -PassThru NoteProperty Impact NA |
|
||||
Add-Member -PassThru NoteProperty Recommendation NA |
|
||||
Add-Member -PassThru NoteProperty MoreInfo NA |
|
||||
Add-Member -PassThru NoteProperty ImpactedObjects NA
|
||||
)
|
||||
|
||||
$blankImpactedObjects = (New-Object PSObject |
|
||||
Add-Member -PassThru NoteProperty Name NA |
|
||||
Add-Member -PassThru NoteProperty ObjectType NA |
|
||||
Add-Member -PassThru NoteProperty ImpactDetail NA
|
||||
)
|
||||
|
||||
$blankImpactedDatabases = (New-Object PSObject |
|
||||
Add-Member -PassThru NoteProperty Name NA |
|
||||
Add-Member -PassThru NoteProperty ObjectType NA |
|
||||
Add-Member -PassThru NoteProperty ImpactDetail NA
|
||||
)
|
||||
|
||||
|
||||
# Start looping through each JSON array
|
||||
|
||||
#fill dataset for ReportData table
|
||||
foreach($obj in (ConvertFrom-Json $content)) #level 1, the actual file
|
||||
{
|
||||
foreach($database in $obj.Databases) #level 2, the sources
|
||||
{
|
||||
$database.AssessmentRecommendations = if($database.AssessmentRecommendations.Length -eq 0) {$blankAssessmentRecommendations } else {$database.AssessmentRecommendations}
|
||||
|
||||
foreach($assessment in $database.AssessmentRecommendations) #level 3, the assessment
|
||||
{
|
||||
|
||||
$assessment.ImpactedObjects = if ($assessment.ImpactedObjects.Length -eq 0) {$blankImpactedObjects} else {$assessment.ImpactedObjects}
|
||||
|
||||
foreach($impactedobj in $assessment.ImpactedObjects) #level 4, the impacted objects
|
||||
{
|
||||
|
||||
#TODO Get date here will eventually be replace with timestamp from JSON file
|
||||
$datatable.rows.add((Get-Date).toString(), $database.ServerName, $database.Status, $database.Name, $database.SizeMB, $database.CompatibilityLevel, $assessment.CompatibilityLevel, $assessment.Category, $assessment.severity, $assessment.ChangeCategory, $assessment.RuleId, $assessment.Title, $assessment.Impact, $assessment.Recommendation, $assessment.MoreInfo, $impactedobj.Name, $impactedobj.ObjectType, $impactedobj.ImpactDetail, $null, $obj.TargetPlatform, $obj.Name) | Out-Null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#fill data set for AzureFeatureParity table
|
||||
foreach($obj in (ConvertFrom-Json $content)) #level 1, the actual file
|
||||
{
|
||||
foreach($serverInstances in $obj.ServerInstances) #level 2, the ServerInstances
|
||||
{
|
||||
foreach($assessment in $serverInstances.AssessmentRecommendations) #level 3, the assessment
|
||||
{
|
||||
$assessment.ImpactedDatabases = if ($assessment.ImpactedDatabases.Length -eq 0) {$blankImpactedDatabases} else {$assessment.ImpactedDatabases}
|
||||
|
||||
foreach($impacteddbs in $assessment.ImpactedDatabases) #level 4, the impacted objects
|
||||
{
|
||||
#TODO Get date here will eventually be replace with timestamp from JSON file
|
||||
$azuredatatable.rows.add((Get-Date).toString(), $serverInstances.ServerName, $serverInstances.Version, $serverInstances.Status, $assessment.Category, $assessment.Severity, $assessment.FeatureParityCategory, $assessment.RuleId, $assessment.Title, $assessment.Impact, $assessment.Recommendation, $assessment.MoreInfo, $impacteddbs.Name, $impacteddbs.ObjectType, $impacteddbs.ImpactDetail) | Out-Null
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$rowcount_rd = $datatable.rows.Count
|
||||
$rowcount_afp = $azuredatatable.rows.Count
|
||||
|
||||
$query1='dbo.JSONResults_Insert'
|
||||
$query2='dbo.AzureFeatureParityResults_Insert'
|
||||
|
||||
#Connect
|
||||
$conn = New-Object System.Data.SqlClient.SqlConnection $connectionString
|
||||
$conn.Open() | Out-Null
|
||||
|
||||
$cmd1 = New-Object System.Data.SqlClient.SqlCommand
|
||||
$cmd1.Connection = $conn
|
||||
$cmd1.CommandType = [System.Data.CommandType]"StoredProcedure"
|
||||
$cmd1.CommandText= $query1
|
||||
$cmd1.Parameters.Add("@JSONResults" , [System.Data.SqlDbType]::Structured) | Out-Null
|
||||
$cmd1.Parameters["@JSONResults"].Value =$datatable
|
||||
|
||||
$cmd2 = New-Object System.Data.SqlClient.SqlCommand
|
||||
$cmd2.Connection = $conn
|
||||
$cmd2.CommandType = [System.Data.CommandType]"StoredProcedure"
|
||||
$cmd2.CommandText= $query2
|
||||
$cmd2.Parameters.Add("@AzureFeatureParityResults" , [System.Data.SqlDbType]::Structured) | Out-Null
|
||||
$cmd2.Parameters["@AzureFeatureParityResults"].Value = $azuredatatable
|
||||
|
||||
$ds1=New-Object system.Data.DataSet
|
||||
$da1=New-Object system.Data.SqlClient.SqlDataAdapter($cmd1)
|
||||
|
||||
$ds2=New-Object system.Data.DataSet
|
||||
$da2=New-Object system.Data.SqlClient.SqlDataAdapter($cmd2)
|
||||
|
||||
# ensure that the dataset can write to the database, if not the dont move the file to processed directory
|
||||
try
|
||||
{
|
||||
$da1.fill($ds1) | Out-Null
|
||||
$da2.fill($ds2) | out-null
|
||||
|
||||
try
|
||||
{
|
||||
Move-Item $filename $processedDir -Force
|
||||
}
|
||||
catch
|
||||
{
|
||||
write-host("Error moving file $filename to directory") -ForegroundColor Red
|
||||
$error[0]|format-list -force
|
||||
}
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
$rowcount_rd = 0
|
||||
$rowcount_afp = 0
|
||||
write-host("Error writing results for file $filename to database") -ForegroundColor Red
|
||||
$error[0]|format-list -force
|
||||
}
|
||||
|
||||
$conn.Close()
|
||||
|
||||
$processEndTime = Get-Date
|
||||
$processTime = NEW-TIMESPAN -Start $processStartTime -End $processEndTime
|
||||
Write-Host("Rows Processed for ReportData Table = $rowcount_rd Rows processed for AzureFeatureParityTable = $rowcount_afp for file $filename Total Processing Time = $processTime")
|
||||
|
||||
$datatable.Clear()
|
||||
$azuredatatable.Clear()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------------ END FUNCTIONS ------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------------- EXECUTE FUNCTIONS --------------------------------------------------------------------------------------
|
||||
|
||||
dmaProcessor -serverName localhost `
|
||||
-databaseName DMAReporting `
|
||||
-jsonDirectory "C:\DMAResults\" `
|
||||
-processTo SQLServer
|
||||
|
||||
|
||||
|
||||
# To process on a named instance use SERVERNAME\INSTANCENAME as the -serverName
|
||||
|
||||
#------------------------------------------------------------------------------------ END EXECUTE FUNCTIONS ------------------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
# PowerShell Script for Importing Assessment Results
|
||||
|
||||
This contains a PowerShell script for importing assessment results from JSON files into a SQL Server database. Assessments are generated using Data Migration Assistant, to evaluate moving data to SQL Server or to Azure SQL Database.
|
||||
|
||||
|
||||
### Contents
|
||||
|
||||
[About this sample](#about-this-sample)<br/>
|
||||
[Before you begin](#before-you-begin)<br/>
|
||||
[Run this sample](#run-this-sample)<br/>
|
||||
[Sample details](#sample-details)<br/>
|
||||
[Disclaimers](#disclaimers)<br/>
|
||||
[Related links](#related-links)<br/>
|
||||
|
||||
|
||||
<a name=about-this-sample></a>
|
||||
|
||||
## About this sample
|
||||
|
||||
- **Applies to:** SQL Server 2016 (or higher), Azure SQL Database
|
||||
- **Key features:** Migration assessments
|
||||
- **Programming Language:** PowerShell
|
||||
- **Authors:** Chris Lound
|
||||
|
||||
|
||||
<a name=before-you-begin></a>
|
||||
|
||||
## Before you begin
|
||||
|
||||
To run this sample, you need the following prerequisites.
|
||||
|
||||
**Software prerequisites:**
|
||||
|
||||
1. PowerShell
|
||||
2. SQL Server 2016 (or higher) or an Azure SQL Database
|
||||
3. Data Migration Assistant
|
||||
|
||||
**Azure prerequisites:**
|
||||
|
||||
1. Permission to create an Azure SQL Database
|
||||
|
||||
<a name=run-this-sample></a>
|
||||
|
||||
## Run this sample
|
||||
|
||||
|
||||
1. Open the script in a text editor and add the following values to the EXECUTE FUNCTIONS section.
|
||||
- serverName
|
||||
- databaseName
|
||||
- jsonDirectory
|
||||
- processTo
|
||||
|
||||
For more information, see [Consolidate Assessment Reports](https://docs.microsoft.com/sql/dma/dma-consolidatereports).
|
||||
|
||||
2. Set PowerShell execution policy to bypass for current session, as follows.
|
||||
|
||||
`Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass`
|
||||
1. Run the script in PowerShell.
|
||||
|
||||
<a name=sample-details></a>
|
||||
|
||||
## Sample details
|
||||
|
||||
PowerShell script for imports assessment results from JSON files into a SQL Server database. The results are imported into the table ReportData. Views, stored procedures, and table types are created in the SQL Server instance and database that you specified in the script. For more information, see [Consolidate Assessment Reports](https://docs.microsoft.com/sql/dma/dma-consolidatereports).
|
||||
|
||||
<a name=disclaimers></a>
|
||||
|
||||
## Disclaimers
|
||||
This sample code is provided for the purpose of illustration only and is not intended to be used in a production environment. The sample code and any related information are provided "as is" without warranty of any kind, either expressed or implied, including but not limited to the implied warranties of merchantability and/or fitness for a particular purpose.
|
||||
|
||||
<a name=related-links></a>
|
||||
|
||||
## Related Links
|
||||
|
||||
For more information, see these articles:
|
||||
|
||||
[Consolidate Assessment Reports](https://docs.microsoft.com/sql/dma/dma-consolidatereports)
|
||||
@@ -0,0 +1,8 @@
|
||||
# Samples for Data Migration Assistant
|
||||
|
||||
[Power BI Reports for Consolidated Migration Assessments](Power BI Reports/README.md)
|
||||
You can use the Power BI reports to view consolidated migration assessments. You can modify these reports to work with your environment.
|
||||
|
||||
[PowerShell Script for Importing Assessment Results](PowerShell Script/README.md)
|
||||
You can use the PowerShell script to import assessment results from JSON files into a SQL Server database.
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{F14B399A-7131-4C87-9E4B-1186C45EF12D}") = "PolicyReports", "PolicyReports\PolicyReports.rptproj", "{30FA2CD3-F4E3-4EA6-85A7-07AF4D922933}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Default = Debug|Default
|
||||
DebugLocal|Default = DebugLocal|Default
|
||||
Release|Default = Release|Default
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{30FA2CD3-F4E3-4EA6-85A7-07AF4D922933}.Debug|Default.ActiveCfg = Debug
|
||||
{30FA2CD3-F4E3-4EA6-85A7-07AF4D922933}.Debug|Default.Build.0 = DebugLocal
|
||||
{30FA2CD3-F4E3-4EA6-85A7-07AF4D922933}.Debug|Default.Deploy.0 = DebugLocal
|
||||
{30FA2CD3-F4E3-4EA6-85A7-07AF4D922933}.DebugLocal|Default.ActiveCfg = DebugLocal
|
||||
{30FA2CD3-F4E3-4EA6-85A7-07AF4D922933}.DebugLocal|Default.Build.0 = DebugLocal
|
||||
{30FA2CD3-F4E3-4EA6-85A7-07AF4D922933}.Release|Default.ActiveCfg = Release
|
||||
{30FA2CD3-F4E3-4EA6-85A7-07AF4D922933}.Release|Default.Build.0 = Release
|
||||
{30FA2CD3-F4E3-4EA6-85A7-07AF4D922933}.Release|Default.Deploy.0 = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{F14B399A-7131-4C87-9E4B-1186C45EF12D}") = "PolicyReports", "PolicyReports.rptproj", "{E0F65769-8BEA-4BFD-B715-44519AF1CF80}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Default = Debug|Default
|
||||
DebugLocal|Default = DebugLocal|Default
|
||||
Release|Default = Release|Default
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{E0F65769-8BEA-4BFD-B715-44519AF1CF80}.Debug|Default.ActiveCfg = Debug
|
||||
{E0F65769-8BEA-4BFD-B715-44519AF1CF80}.Debug|Default.Build.0 = DebugLocal
|
||||
{E0F65769-8BEA-4BFD-B715-44519AF1CF80}.Debug|Default.Deploy.0 = DebugLocal
|
||||
{E0F65769-8BEA-4BFD-B715-44519AF1CF80}.DebugLocal|Default.ActiveCfg = DebugLocal
|
||||
{E0F65769-8BEA-4BFD-B715-44519AF1CF80}.DebugLocal|Default.Build.0 = DebugLocal
|
||||
{E0F65769-8BEA-4BFD-B715-44519AF1CF80}.DebugLocal|Default.Deploy.0 = DebugLocal
|
||||
{E0F65769-8BEA-4BFD-B715-44519AF1CF80}.Release|Default.ActiveCfg = Release
|
||||
{E0F65769-8BEA-4BFD-B715-44519AF1CF80}.Release|Default.Build.0 = Release
|
||||
{E0F65769-8BEA-4BFD-B715-44519AF1CF80}.Release|Default.Deploy.0 = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual Studio 2010
|
||||
Project("{F14B399A-7131-4C87-9E4B-1186C45EF12D}") = "PolicyReports", "PolicyReports\PolicyReports.rptproj", "{30FA2CD3-F4E3-4EA6-85A7-07AF4D922933}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Default = Debug|Default
|
||||
DebugLocal|Default = DebugLocal|Default
|
||||
Release|Default = Release|Default
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{30FA2CD3-F4E3-4EA6-85A7-07AF4D922933}.Debug|Default.ActiveCfg = Debug
|
||||
{30FA2CD3-F4E3-4EA6-85A7-07AF4D922933}.Debug|Default.Build.0 = DebugLocal
|
||||
{30FA2CD3-F4E3-4EA6-85A7-07AF4D922933}.Debug|Default.Deploy.0 = DebugLocal
|
||||
{30FA2CD3-F4E3-4EA6-85A7-07AF4D922933}.DebugLocal|Default.ActiveCfg = DebugLocal
|
||||
{30FA2CD3-F4E3-4EA6-85A7-07AF4D922933}.DebugLocal|Default.Build.0 = DebugLocal
|
||||
{30FA2CD3-F4E3-4EA6-85A7-07AF4D922933}.Release|Default.ActiveCfg = Release
|
||||
{30FA2CD3-F4E3-4EA6-85A7-07AF4D922933}.Release|Default.Build.0 = Release
|
||||
{30FA2CD3-F4E3-4EA6-85A7-07AF4D922933}.Release|Default.Deploy.0 = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
Sample order processing workload that can be used for benchmarking transactional processing with in-memory technologies. The scripts in this folder leverage the In-Memory OLTP feature in SQL Server 2016.
|
||||
|
||||
Some results from this benchmark:
|
||||
* [4 Terabyte and 343,000 transactions per second with SQL Server 2016 on Hyper-V](https://blogs.technet.microsoft.com/windowsserver/2016/09/28/windows-server-2016-hyper-v-large-scale-vm-performance-for-in-memory-transaction-processing/)
|
||||
* [11X perf gain with In-Memory OLTP in Azure SQL Database](https://azure.microsoft.com/blog/in-memory-oltp-in-azure-sql-database/)
|
||||
|
||||
<a name=about-this-sample></a>
|
||||
|
||||
## About this sample
|
||||
|
||||
BIN
Binary file not shown.
+119
@@ -0,0 +1,119 @@
|
||||
# Load packages.
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import revoscalepy as revoscale
|
||||
from scipy.spatial import distance as sci_distance
|
||||
from sklearn import cluster as sk_cluster
|
||||
|
||||
|
||||
|
||||
def perform_clustering():
|
||||
################################################################################################
|
||||
|
||||
## Connect to DB and select data
|
||||
|
||||
################################################################################################
|
||||
|
||||
# Connection string to connect to SQL Server named instance.
|
||||
conn_str = 'Driver=SQL Server;Server=localhost;Database=tpcxbb_1gb;Trusted_Connection=True;'
|
||||
|
||||
input_query = '''SELECT
|
||||
ss_customer_sk AS customer,
|
||||
ROUND(COALESCE(returns_count / NULLIF(1.0*orders_count, 0), 0), 7) AS orderRatio,
|
||||
ROUND(COALESCE(returns_items / NULLIF(1.0*orders_items, 0), 0), 7) AS itemsRatio,
|
||||
ROUND(COALESCE(returns_money / NULLIF(1.0*orders_money, 0), 0), 7) AS monetaryRatio,
|
||||
COALESCE(returns_count, 0) AS frequency
|
||||
FROM
|
||||
(
|
||||
SELECT
|
||||
ss_customer_sk,
|
||||
-- return order ratio
|
||||
COUNT(distinct(ss_ticket_number)) AS orders_count,
|
||||
-- return ss_item_sk ratio
|
||||
COUNT(ss_item_sk) AS orders_items,
|
||||
-- return monetary amount ratio
|
||||
SUM( ss_net_paid ) AS orders_money
|
||||
FROM store_sales s
|
||||
GROUP BY ss_customer_sk
|
||||
) orders
|
||||
LEFT OUTER JOIN
|
||||
(
|
||||
SELECT
|
||||
sr_customer_sk,
|
||||
-- return order ratio
|
||||
count(distinct(sr_ticket_number)) as returns_count,
|
||||
-- return ss_item_sk ratio
|
||||
COUNT(sr_item_sk) as returns_items,
|
||||
-- return monetary amount ratio
|
||||
SUM( sr_return_amt ) AS returns_money
|
||||
FROM store_returns
|
||||
GROUP BY sr_customer_sk ) returned ON ss_customer_sk=sr_customer_sk'''
|
||||
|
||||
|
||||
# Define the columns we wish to import.
|
||||
column_info = {
|
||||
"customer": {"type": "integer"},
|
||||
"orderRatio": {"type": "integer"},
|
||||
"itemsRatio": {"type": "integer"},
|
||||
"frequency": {"type": "integer"}
|
||||
}
|
||||
|
||||
data_source = revoscale.RxSqlServerData(sql_query=input_query, column_info=column_info,
|
||||
connection_string=conn_str)
|
||||
|
||||
# import data source and convert to pandas dataframe.
|
||||
customer_data = pd.DataFrame(revoscalepy.rx_import(data_source))
|
||||
print("Data frame:", customer_data.head(n=20))
|
||||
|
||||
################################################################################################
|
||||
|
||||
## Determine number of clusters using the Elbow method
|
||||
|
||||
################################################################################################
|
||||
|
||||
cdata = customer_data
|
||||
K = range(1, 20)
|
||||
KM = (sk_cluster.KMeans(n_clusters=k).fit(cdata) for k in K)
|
||||
centroids = (k.cluster_centers_ for k in KM)
|
||||
|
||||
D_k = (sci_distance.cdist(cdata, cent, 'euclidean') for cent in centroids)
|
||||
dist = (np.min(D, axis=1) for D in D_k)
|
||||
avgWithinSS = [sum(d) / cdata.shape[0] for d in dist]
|
||||
plt.plot(K, avgWithinSS, 'b*-')
|
||||
plt.grid(True)
|
||||
plt.xlabel('Number of clusters')
|
||||
plt.ylabel('Average within-cluster sum of squares')
|
||||
plt.title('Elbow for KMeans clustering')
|
||||
plt.show()
|
||||
|
||||
|
||||
################################################################################################
|
||||
|
||||
## Perform clustering using Kmeans
|
||||
|
||||
################################################################################################
|
||||
|
||||
# It looks like k=4 is a good number to use based on the elbow graph.
|
||||
n_clusters = 4
|
||||
|
||||
means_cluster = sk_cluster.KMeans(n_clusters=n_clusters, random_state=111)
|
||||
columns = ["orderRatio", "itemsRatio", "monetaryRatio", "frequency"]
|
||||
est = means_cluster.fit(customer_data[columns])
|
||||
clusters = est.labels_
|
||||
customer_data['cluster'] = clusters
|
||||
|
||||
# Print some data about the clusters:
|
||||
|
||||
# For each cluster, count the members.
|
||||
for c in range(n_clusters):
|
||||
cluster_members=customer_data[customer_data['cluster'] == c][:]
|
||||
print('Cluster{}(n={}):'.format(c, len(cluster_members)))
|
||||
print('-'* 17)
|
||||
|
||||
# Print mean values per cluster.
|
||||
print(customer_data.groupby(['cluster']).mean())
|
||||
|
||||
|
||||
perform_clustering()
|
||||
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
USE [tpcxbb_1gb]
|
||||
GO
|
||||
|
||||
-- Stored procedure that performs customer clustering using Python and SQL Server ML Services
|
||||
CREATE OR ALTER PROCEDURE [dbo].[py_generate_customer_return_clusters]
|
||||
AS
|
||||
|
||||
BEGIN
|
||||
DECLARE
|
||||
|
||||
-- Input query to generate the purchase history & return metrics
|
||||
@input_query NVARCHAR(MAX) = N'
|
||||
SELECT
|
||||
ss_customer_sk AS customer,
|
||||
CAST( (ROUND(COALESCE(returns_count / NULLIF(1.0*orders_count, 0), 0), 7) ) AS FLOAT) AS orderRatio,
|
||||
CAST( (ROUND(COALESCE(returns_items / NULLIF(1.0*orders_items, 0), 0), 7) ) AS FLOAT) AS itemsRatio,
|
||||
CAST( (ROUND(COALESCE(returns_money / NULLIF(1.0*orders_money, 0), 0), 7) ) AS FLOAT) AS monetaryRatio,
|
||||
CAST( (COALESCE(returns_count, 0)) AS FLOAT) AS frequency
|
||||
FROM
|
||||
(
|
||||
SELECT
|
||||
ss_customer_sk,
|
||||
-- return order ratio
|
||||
COUNT(distinct(ss_ticket_number)) AS orders_count,
|
||||
-- return ss_item_sk ratio
|
||||
COUNT(ss_item_sk) AS orders_items,
|
||||
-- return monetary amount ratio
|
||||
SUM( ss_net_paid ) AS orders_money
|
||||
FROM store_sales s
|
||||
GROUP BY ss_customer_sk
|
||||
) orders
|
||||
LEFT OUTER JOIN
|
||||
(
|
||||
SELECT
|
||||
sr_customer_sk,
|
||||
-- return order ratio
|
||||
count(distinct(sr_ticket_number)) as returns_count,
|
||||
-- return ss_item_sk ratio
|
||||
COUNT(sr_item_sk) as returns_items,
|
||||
-- return monetary amount ratio
|
||||
SUM( sr_return_amt ) AS returns_money
|
||||
FROM store_returns
|
||||
GROUP BY sr_customer_sk
|
||||
) returned ON ss_customer_sk=sr_customer_sk
|
||||
'
|
||||
|
||||
EXEC sp_execute_external_script
|
||||
@language = N'Python'
|
||||
, @script = N'
|
||||
|
||||
import pandas as pd
|
||||
from sklearn.cluster import KMeans
|
||||
|
||||
#We concluded in step2 in the tutorial that 4 would be a good number of clusters
|
||||
n_clusters = 4
|
||||
|
||||
#Perform clustering
|
||||
est = KMeans(n_clusters=n_clusters, random_state=111).fit(customer_data[["orderRatio","itemsRatio","monetaryRatio","frequency"]])
|
||||
clusters = est.labels_
|
||||
customer_data["cluster"] = clusters
|
||||
|
||||
#OutputDataSet = customer_data
|
||||
'
|
||||
, @input_data_1 = @input_query
|
||||
, @input_data_1_name = N'customer_data'
|
||||
,@output_data_1_name = N'customer_data'
|
||||
with result sets (("Customer" int, "orderRatio" float,"itemsRatio" float,"monetaryRatio" float,"frequency" float,"cluster" float));
|
||||
END;
|
||||
GO
|
||||
|
||||
|
||||
--Creating a table for storing the clustering data
|
||||
DROP TABLE IF EXISTS [dbo].[py_customer_clusters];
|
||||
GO
|
||||
--Create a table to store the predictions in
|
||||
CREATE TABLE [dbo].[py_customer_clusters](
|
||||
[Customer] [bigint] NULL,
|
||||
[OrderRatio] [float] NULL,
|
||||
[itemsRatio] [float] NULL,
|
||||
[monetaryRatio] [float] NULL,
|
||||
[frequency] [float] NULL,
|
||||
[cluster] [int] NULL,
|
||||
) ON [PRIMARY]
|
||||
GO
|
||||
|
||||
--Execute the clustering and insert results into table
|
||||
INSERT INTO py_customer_clusters
|
||||
EXEC [dbo].[py_generate_customer_return_clusters];
|
||||
|
||||
-- Select contents of the table
|
||||
SELECT * FROM py_customer_clusters;
|
||||
|
||||
--Get email addresses of customers in cluster 0
|
||||
SELECT customer.[c_email_address], customer.c_customer_sk
|
||||
FROM dbo.customer
|
||||
JOIN
|
||||
[dbo].[py_customer_clusters] as c
|
||||
ON c.Customer = customer.c_customer_sk
|
||||
WHERE c.cluster = 0;
|
||||
|
||||
+64
-60
@@ -2,68 +2,72 @@ import pandas as pd
|
||||
from sklearn.linear_model import LinearRegression
|
||||
from sklearn.metrics import mean_squared_error
|
||||
|
||||
from revoscalepy.computecontext.RxInSqlServer import RxInSqlServer
|
||||
from revoscalepy.computecontext.RxInSqlServer import RxSqlServerData
|
||||
from revoscalepy.etl.RxImport import rx_import_datasource
|
||||
|
||||
#If you are running SQL Server 2017 RC1 and above:
|
||||
from revoscalepy import RxComputeContext, RxInSqlServer, RxSqlServerData
|
||||
from revoscalepy import rx_import
|
||||
|
||||
def get_rental_predictions():
|
||||
conn_str = 'Driver=SQL Server;Server=MYSQLSERVER;Database=TutorialDB;Trusted_Connection=True;'
|
||||
column_info = {
|
||||
"Year" : { "type" : "integer" },
|
||||
"Month" : { "type" : "integer" },
|
||||
"Day" : { "type" : "integer" },
|
||||
"RentalCount" : { "type" : "integer" },
|
||||
"WeekDay" : {
|
||||
"type" : "factor",
|
||||
"levels" : ["1", "2", "3", "4", "5", "6", "7"]
|
||||
},
|
||||
"Holiday" : {
|
||||
"type" : "factor",
|
||||
"levels" : ["1", "0"]
|
||||
},
|
||||
"Snow" : {
|
||||
"type" : "factor",
|
||||
"levels" : ["1", "0"]
|
||||
}
|
||||
}
|
||||
#Connection string to connect to SQL Server named instance
|
||||
conn_str = 'Driver=SQL Server;Server=MYSQLSERVER;Database=TutorialDB;Trusted_Connection=True;'
|
||||
|
||||
data_source = RxSqlServerData(table="dbo.rental_data",
|
||||
connectionString=conn_str, colInfo=column_info)
|
||||
computeContext = RxInSqlServer(
|
||||
connectionString = conn_str,
|
||||
numTasks = 1,
|
||||
autoCleanup = False
|
||||
)
|
||||
|
||||
|
||||
RxInSqlServer(connectionString=conn_str, numTasks=1, autoCleanup=False)
|
||||
|
||||
# import data source and convert to pandas dataframe
|
||||
df = pd.DataFrame(rx_import_datasource(data_source))
|
||||
print("Data frame:", df)
|
||||
# Get all the columns from the dataframe.
|
||||
columns = df.columns.tolist()
|
||||
# Filter the columns to remove ones we don't want.
|
||||
columns = [c for c in columns if c not in ["Year"]]
|
||||
# Store the variable we'll be predicting on.
|
||||
target = "RentalCount"
|
||||
# Generate the training set. Set random_state to be able to replicate results.
|
||||
train = df.sample(frac=0.8, random_state=1)
|
||||
# Select anything not in the training set and put it in the testing set.
|
||||
test = df.loc[~df.index.isin(train.index)]
|
||||
# Print the shapes of both sets.
|
||||
print("Training set shape:", train.shape)
|
||||
print("Testing set shape:", test.shape)
|
||||
# Initialize the model class.
|
||||
lin_model = LinearRegression()
|
||||
# Fit the model to the training data.
|
||||
lin_model.fit(train[columns], train[target])
|
||||
# Generate our predictions for the test set.
|
||||
lin_predictions = lin_model.predict(test[columns])
|
||||
print("Predictions:", lin_predictions)
|
||||
# Compute error between our test predictions and the actual values.
|
||||
lin_mse = mean_squared_error(lin_predictions, test[target])
|
||||
print("Computed error:", lin_mse)
|
||||
#Define the columns we wish to import
|
||||
column_info = {
|
||||
"Year" : { "type" : "integer" },
|
||||
"Month" : { "type" : "integer" },
|
||||
"Day" : { "type" : "integer" },
|
||||
"RentalCount" : { "type" : "integer" },
|
||||
"WeekDay" : {
|
||||
"type" : "factor",
|
||||
"levels" : ["1", "2", "3", "4", "5", "6", "7"]
|
||||
},
|
||||
"Holiday" : {
|
||||
"type" : "factor",
|
||||
"levels" : ["1", "0"]
|
||||
},
|
||||
"Snow" : {
|
||||
"type" : "factor",
|
||||
"levels" : ["1", "0"]
|
||||
}
|
||||
}
|
||||
|
||||
#Get the data from SQL Server Table
|
||||
data_source = RxSqlServerData(table="dbo.rental_data",
|
||||
connection_string=conn_str, column_info=column_info)
|
||||
computeContext = RxInSqlServer(
|
||||
connection_string = conn_str,
|
||||
num_tasks = 1,
|
||||
auto_cleanup = False
|
||||
)
|
||||
|
||||
|
||||
RxInSqlServer(connection_string=conn_str, num_tasks=1, auto_cleanup=False)
|
||||
|
||||
# import data source and convert to pandas dataframe
|
||||
df = pd.DataFrame(rx_import(input_data = data_source))
|
||||
print("Data frame:", df)
|
||||
# Get all the columns from the dataframe.
|
||||
columns = df.columns.tolist()
|
||||
# Filter the columns to remove ones we don't want to use in the training
|
||||
columns = [c for c in columns if c not in ["Year"]]
|
||||
# Store the variable we'll be predicting on.
|
||||
target = "RentalCount"
|
||||
# Generate the training set. Set random_state to be able to replicate results.
|
||||
train = df.sample(frac=0.8, random_state=1)
|
||||
# Select anything not in the training set and put it in the testing set.
|
||||
test = df.loc[~df.index.isin(train.index)]
|
||||
# Print the shapes of both sets.
|
||||
print("Training set shape:", train.shape)
|
||||
print("Testing set shape:", test.shape)
|
||||
# Initialize the model class.
|
||||
lin_model = LinearRegression()
|
||||
# Fit the model to the training data.
|
||||
lin_model.fit(train[columns], train[target])
|
||||
|
||||
# Generate our predictions for the test set.
|
||||
lin_predictions = lin_model.predict(test[columns])
|
||||
print("Predictions:", lin_predictions)
|
||||
# Compute error between our test predictions and the actual values.
|
||||
lin_mse = mean_squared_error(lin_predictions, test[target])
|
||||
print("Computed error:", lin_mse)
|
||||
|
||||
get_rental_predictions()
|
||||
|
||||
+10
-9
@@ -27,23 +27,24 @@ BEGIN
|
||||
@language = N'Python'
|
||||
, @script = N'
|
||||
|
||||
from sklearn import linear_model
|
||||
|
||||
import pickle
|
||||
|
||||
|
||||
df = rental_train_data
|
||||
|
||||
# Get all the columns from the dataframe.
|
||||
columns = df.columns.tolist()
|
||||
|
||||
|
||||
# Store the variable well be predicting on.
|
||||
target = "RentalCount"
|
||||
|
||||
from sklearn.linear_model import LinearRegression
|
||||
|
||||
# Initialize the model class.
|
||||
lin_model = LinearRegression()
|
||||
lin_model = linear_model.LinearRegression()
|
||||
# Fit the model to the training data.
|
||||
lin_model.fit(df[columns], df[target])
|
||||
|
||||
import pickle
|
||||
#Before saving the model to the DB table, we need to convert it to a binary object
|
||||
trained_model = pickle.dumps(lin_model)
|
||||
'
|
||||
@@ -75,7 +76,7 @@ AS
|
||||
BEGIN
|
||||
DECLARE @py_model varbinary(max) = (select model from rental_py_models where model_name = @model);
|
||||
|
||||
EXEC sp_execute_external_script
|
||||
EXEC sp_execute_external_script
|
||||
@language = N'Python'
|
||||
, @script = N'
|
||||
|
||||
@@ -83,7 +84,7 @@ BEGIN
|
||||
import pickle
|
||||
rental_model = pickle.loads(py_model)
|
||||
|
||||
|
||||
|
||||
df = rental_score_data
|
||||
#print(df)
|
||||
|
||||
@@ -106,7 +107,7 @@ lin_mse = mean_squared_error(lin_predictions, df[target])
|
||||
#print(lin_mse)
|
||||
|
||||
import pandas as pd
|
||||
predictions_df = pd.DataFrame(lin_predictions)
|
||||
predictions_df = pd.DataFrame(lin_predictions)
|
||||
OutputDataSet = pd.concat([predictions_df, df["RentalCount"], df["Month"], df["Day"], df["WeekDay"], df["Snow"], df["Holiday"], df["Year"]], axis=1)
|
||||
'
|
||||
, @input_data_1 = N'Select "RentalCount", "Year" ,"Month", "Day", "WeekDay", "Snow", "Holiday" from rental_data where Year = 2015'
|
||||
@@ -114,7 +115,7 @@ OutputDataSet = pd.concat([predictions_df, df["RentalCount"], df["Month"], df["D
|
||||
, @params = N'@py_model varbinary(max)'
|
||||
, @py_model = @py_model
|
||||
with result sets (("RentalCount_Predicted" float, "RentalCount" float, "Month" float,"Day" float,"WeekDay" float,"Snow" float,"Holiday" float, "Year" float));
|
||||
|
||||
|
||||
END;
|
||||
GO
|
||||
|
||||
|
||||
@@ -10,7 +10,11 @@ Master Data Services (MDS) is the SQL Server solution for master data management
|
||||
|
||||
[R Services](r-services)
|
||||
|
||||
SQL Server R Services brings R processing close to the data, allowing more scalable and more efficient predictive analytics.
|
||||
SQL Server R Services (in SQL Server 2016 and above) brings R processing close to the data, allowing more scalable and more efficient predictive analytics using R in-database.
|
||||
|
||||
[ML Services](ml-services)
|
||||
|
||||
SQL Server ML Services (SQL Server 2017) brings Python processing close to the data, allowing more scalable and more efficient predictive analytics using Python in-database.
|
||||
|
||||
[JSON Support](json)
|
||||
|
||||
@@ -28,4 +32,4 @@ Graph tables enable you to add a non-relational capability to your database.
|
||||
|
||||
[Reporting Services (SSRS)](reporting-services)
|
||||
|
||||
Reporting Services provides reporting capabilities for your organziation. Reporting Services can be integrated with SharePoint Server or used as a standalone service.
|
||||
Reporting Services provides reporting capabilities for your organziation. Reporting Services can be integrated with SharePoint Server or used as a standalone service.
|
||||
|
||||
Binary file not shown.
@@ -25,6 +25,6 @@ foreach($blob in $blobs)
|
||||
{
|
||||
echo ("Deleting blob " + $blob.Name)
|
||||
# Delete the blob.e
|
||||
Remove-AzureStorageBlob -Container $storageContainer -Context $context -Blob $blob.Name;
|
||||
Remove-AzureStorageBlob -Container $storageContainerName -Context $context -Blob $blob.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user