For Microsoft System Center Operations Manger 2012 R2 Update 3 here are the database changes I made to the OperationsManager database to improve performance.
Microsoft
Bulk Bing Maps Geocode Service Encoding using Powershell
Recently I had the need to geo-encode millions of addresses, after reviewing multiple technologies I found PowerShell provided excellent results. Here is the example solution.
You will need a Bing Maps Maps Account API Key and Microsoft SQL Server
The first step is to create a database with sample data, below is the script:
USE [master] GO /****** Object: Database [LocationDB] Script Date: 2012-10-20 12:42:43 AM ******/ CREATE DATABASE [LocationDB] GO ALTER DATABASE [LocationDB] SET COMPATIBILITY_LEVEL = 110 GO IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled')) begin EXEC [LocationDB].[dbo].[sp_fulltext_database] @action = 'enable' end GO ALTER DATABASE [LocationDB] SET ANSI_NULL_DEFAULT OFF GO ALTER DATABASE [LocationDB] SET ANSI_NULLS OFF GO ALTER DATABASE [LocationDB] SET ANSI_PADDING OFF GO ALTER DATABASE [LocationDB] SET ANSI_WARNINGS OFF GO ALTER DATABASE [LocationDB] SET ARITHABORT OFF GO ALTER DATABASE [LocationDB] SET AUTO_CLOSE OFF GO ALTER DATABASE [LocationDB] SET AUTO_CREATE_STATISTICS ON GO ALTER DATABASE [LocationDB] SET AUTO_SHRINK OFF GO ALTER DATABASE [LocationDB] SET AUTO_UPDATE_STATISTICS ON GO ALTER DATABASE [LocationDB] SET CURSOR_CLOSE_ON_COMMIT OFF GO ALTER DATABASE [LocationDB] SET CURSOR_DEFAULT GLOBAL GO ALTER DATABASE [LocationDB] SET CONCAT_NULL_YIELDS_NULL OFF GO ALTER DATABASE [LocationDB] SET NUMERIC_ROUNDABORT OFF GO ALTER DATABASE [LocationDB] SET QUOTED_IDENTIFIER OFF GO ALTER DATABASE [LocationDB] SET RECURSIVE_TRIGGERS OFF GO ALTER DATABASE [LocationDB] SET DISABLE_BROKER GO ALTER DATABASE [LocationDB] SET AUTO_UPDATE_STATISTICS_ASYNC OFF GO ALTER DATABASE [LocationDB] SET DATE_CORRELATION_OPTIMIZATION OFF GO ALTER DATABASE [LocationDB] SET TRUSTWORTHY OFF GO ALTER DATABASE [LocationDB] SET ALLOW_SNAPSHOT_ISOLATION OFF GO ALTER DATABASE [LocationDB] SET PARAMETERIZATION SIMPLE GO ALTER DATABASE [LocationDB] SET READ_COMMITTED_SNAPSHOT OFF GO ALTER DATABASE [LocationDB] SET HONOR_BROKER_PRIORITY OFF GO ALTER DATABASE [LocationDB] SET RECOVERY FULL GO ALTER DATABASE [LocationDB] SET MULTI_USER GO ALTER DATABASE [LocationDB] SET PAGE_VERIFY CHECKSUM GO ALTER DATABASE [LocationDB] SET DB_CHAINING OFF GO ALTER DATABASE [LocationDB] SET FILESTREAM( NON_TRANSACTED_ACCESS = OFF ) GO ALTER DATABASE [LocationDB] SET TARGET_RECOVERY_TIME = 0 SECONDS GO EXEC sys.sp_db_vardecimal_storage_format N'LocationDB', N'ON' GO USE [LocationDB] GO /****** Object: StoredProcedure [dbo].[usp_GetLocations] Script Date: 2012-10-20 12:42:44 AM ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Nathan Storms -- Create date: 2012-10-20 -- Description: Get Location that need encoding. -- ============================================= CREATE PROCEDURE [dbo].[usp_GetLocations] -- Add the parameters for the stored procedure here AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; -- Insert statements for procedure here SELECT TOP 1000 Id, ([Address] + ', ' + [City] + ', ' + [Region] + ', ' + [Country] + ', ' + [PostalCode]) AS Address FROM [dbo].[Locations] WITH (NOLOCK) WHERE SRID IS NULL END GO /****** Object: StoredProcedure [dbo].[usp_UpdateLocation] Script Date: 2012-10-20 12:42:44 AM ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Nathan Storms -- Create date: 2012-10-20 -- Description: Update locations with geocode -- ============================================= CREATE PROCEDURE [dbo].[usp_UpdateLocation] -- Add the parameters for the stored procedure here @ID int = 0, @Longitude float = 0, @Latitude float = 0, @SRID int = 4326 AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; -- Insert statements for procedure here UPDATE [dbo].[Locations] SET [Latitude] = @Latitude ,[Longitude] = @Longitude ,[SRID] = 4326 WHERE [ID] = @ID END GO /****** Object: Table [dbo].[Locations] Script Date: 2012-10-20 12:42:44 AM ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[Locations]( [Id] [int] IDENTITY(1,1) NOT NULL, [Address] [varchar](50) NOT NULL, [City] [varchar](50) NOT NULL, [Region] [char](2) NOT NULL, [Country] [varchar](50) NOT NULL, [PostalCode] [char](15) NOT NULL, [Latitude] [float] NULL, [Longitude] [float] NULL, [SRID] [int] NULL, [Point] AS ([geography]::Point([Latitude],[Longitude],[SRID])), CONSTRAINT [PK_Locations] PRIMARY KEY CLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO SET ANSI_PADDING OFF GO ALTER TABLE [dbo].[Locations] ADD CONSTRAINT [DF_Locations_Latitude] DEFAULT ((0)) FOR [Latitude] GO ALTER TABLE [dbo].[Locations] ADD CONSTRAINT [DF_Locations_Longitude] DEFAULT ((0)) FOR [Longitude] GO INSERT INTO [dbo].[Locations] ([Address],[City],[Region],[Country],[PostalCode]) VALUES ('6258 Amesbury St','San Diego','CA','United States','92114-6717'), ('8308 Fenway Rd','Bethesda','MD','United States','20817-2733'), ('10 Wall St','Burlington','MA','United States','01803-4749'), ('3315 W Greenway Rd','Phoenix','AZ','United States','85053-380'), ('1635 Camile Pl','Santa Ana','CA','United States','92703-4401') GO
Lastly here is the PowerShell Script to geo-encode the addresses in the database:
# Setup Connection To Bing $key = "{Add Bing Map API Key}" $ws = New-WebServiceProxy -uri http://dev.virtualearth.net/webservices/v1/geocodeservice/geocodeservice.svc?wsdl $wsgr = New-Object Microsoft.PowerShell.Commands.NewWebserviceProxy.AutogeneratedTypes.WebServiceProxy1ervice_geocodeservice_svc_wsdl.GeocodeRequest $wsc = New-Object Microsoft.PowerShell.Commands.NewWebserviceProxy.AutogeneratedTypes.WebServiceProxy1ervice_geocodeservice_svc_wsdl.Credentials $wsc.ApplicationId = $key $wsgr.Credentials = $wsc # Setup Connection To SQL Database function ConnectSQL { Param ($server, $query, $database) $conn = new-object ('System.Data.SqlClient.SqlConnection') $connString = "Server=$server;Integrated Security=SSPI;Database=$database" $conn.ConnectionString = $connString $conn.Open() $sqlCmd = New-Object System.Data.SqlClient.SqlCommand $sqlCmd.CommandText = $query $sqlCmd.Connection = $conn $Rset = $sqlCmd.ExecuteReader() ,$Rset ## The comma is used to create an outer array, which PS strips off automatically when returning the $Rset } function QuerySQL { Param ($server, $query, $database = "master") $data = ConnectSQL $server $query $database while ($data.read() -eq $true) { $max = $data.FieldCount -1 $obj = New-Object Object For ($i = 0; $i -le $max; $i++) { $name = $data.GetName($i) $obj | Add-Member Noteproperty $name -value $data.GetValue($i) } $obj } } Write-Host "Getting Records From Database..." $Locations = QuerySQL "localhost" "EXECUTE [dbo].[usp_GetLocations]" "LocationDB" $Locations | ForEach-Object {
$wsr = 0
$Longitude = 0
$Latitude = 0$ID = $_.ID $Address = $_.Address Write-Host "Processing record $LocationID for the address: $Address" $wsgr.Query = $Address $wsr = $ws.Geocode($wsgr) $Longitude = $wsr.Results[0].Locations[0].Longitude $Latitude = $wsr.Results[0].Locations[0].Latitude Write-Host "Location found for record $ID the location is $Longitude, $Latitude" QuerySQL "localhost" "EXECUTE [dbo].[usp_UpdateLocation] $ID, $Longitude, $Latitude" "LocationDB" }
That’s it.
Forefront TMG within Hyper-V Private Clouds
The following describes a high availability architecture for Forefront TMG within Hyper-V for IaaS Private Cloud supporting an web application tier and data storage tier with optimal path section (OPS).
Scenario
In this scenario I will use 4 identical Microsoft Hyper-V servers each with a LACP LAG tagging all VLANs to the Hyper-V constructing a virtual switch whereby each VM network interface is tagged to a VLAN ID.
Construct a TMG enterprise array placing a virtual TMG server on each Hyper-V host, you will need to provide each TMG a minimum of two network interfaces (LAN & WAN), give each VM 8GB of memory and 4 virtual processors reserving 100% for the CPU reservation. Next configure the TMG enterprise with a unicast NLB on each network interface creating bi-directional affinity. Note: real client traffic (IPs) will need to be able to route to the WAN interface on the TMG enterprise array.
Construct an application tier farm placing a virtual application server on each Hyper-V host, you will need to define the default gateway for each TMG server to be the primary NLB IP address on the LAN interface defined on the TMG enterprise array.
Construct a data tier farm placing a virtual database server on each Hype-V host. I recommend using database mirroring or AlawaysOn availability architecture to obtain application resiliency in favour of clustering, you will need to define the default gateway for each TMG server to be the primary NLB IP address on the LAN interface defined on the TMG enterprise array.
Deploy your IaaS database solution in your data tier farm, for example deploying multiple databases across with mirrors across all of your database servers.
Deploy your SaaS application solution in your application tier farm.
Behaviour
To recap you have deployed a TMG NLB in front of a web farm that uses a database tier backend comprised of multiple SQL servers, but the active database may only exist on one database server.
As you can see an external request is sent to TMG then load balanced out to one of the web application servers which is then routed to a database server. By default traffic is randomly distributed between one or all Hyper-V Hosts.
Problem
How to optimally route requests with affinity in TMG to the Web Application server where the primary database resides so that communication between the application and database don’t transmitting the physical IP network but end up transmitting over the hypervisor network at 10gb with zero latency.
Solution
Configure your web application with application request routing in a workflow to instrument the first request with affinity to sort out the shortest path then set the client origin IP affinity to get routed in the TMG enterprise array to the TMG server that contains the primary database and web farm affinity to send additional requests over time to the web application server that resides on the same server as the primary database.
The result is over time an NLB affinity cache is built where a client request automatically gets routed to the fastest communication path for TMG, web application server and the primary database while reducing traffic on your physical network using Optimal Path Selection (OPS).