Фрагментация базы данных SQL Server

Tags: SQL Server, database, Azure

Этот пост охватывает обход базы данных SQL Server с использованием инструментов Azure и фрагментов сценария PowerShell.

Фрагментация или сегментация (Sharding) разбивает одну большую базу данных на несколько более мелких автономных. Обычно к ней прибегают компании, которым необходимо логически разбить данные, например, поставщик SaaS, разделяющий данные клиента. Преимущества этой работы очевидны, поскольку фрагментированная база данных, как правило, намного меньше оригинала, поэтому запросы, обслуживание и все другие задачи выполняются намного быстрее. Однако теперь компании приходится иметь дело со многими другими (возможно, сотнями) баз данных по сравнению с прошлым.

На высоком уровне фрагментация работает следующим образом:

  1. Компания выбирает логический метод для разделения данных под названием Sharding Key - ключ фрагментации
  2. В новой базе данных создается Shard Map (карта сегментов). Эта карта связывает ключ окантовки с базой данных, с которой связаны данные
  3. Создаются новые базы данных, и данные перемещаются в новый дом.
  4. Связи клиента изменены. Теперь они будут запрашивать карту сегментов, чтобы найти данные сегмента, а затем подключаться к новой базе данных.

Кроме того, с Azure и фрагментацией мы видим, что многие люди используют набор фрагментированных баз данных, а затем размещают их в Elastic Pool для повышения производительности и обслуживания.

Остальная часть этого сообщения в блоге описывает пошаговую фрагментацию базы данных.

Определение ключа сегментации

Ключ сегментации - это значение, которое будет использоваться для разбивки данных на отдельные сегменты. Ключ используется картой сегментации для определения места хранения требуемых пользовательских данных и надлежащего маршрутизации соединений. Крайне важно, чтобы ключ сегментации мог быть сопоставлен с каждым значением, которое будет перенесено. Любые значения без Sharding Key будут пропущены.

Например, розничный бизнес с несколькими магазинами в США может использовать значение StoreID в качестве Sharding Key. StoreID может быть уникальным идентификатором или INT IDENTITY, и логически это означает, что данные будут помечены хранилищем.

Определение метода фрагментации

Сегменты могут храниться в соответствующих базах данных одним из двух способов:

Фрагментация по диапазонам

Фрагментация по диапазонам (Range Sharding) хранит несколько сегментов в одной базе данных на основе ключа сегментации в пределах определенного диапазона значений.  Например, в системе с ключом Integer Sharding Key значения 1-10 могут храниться в одной базе данных, а данные со значениями 11-20 сохраняются во второй базе данных. Это позволяет совместно использовать ресурсы базы данных несколькими ключами сегментации и уменьшает общее количество баз данных, которые необходимо сохранить.

Фрагментация по спискам (точечная)

Точечная фрагментация (Point Sharding) хранит данные для каждого сегмента в отдельной базе данных для каждого ключа. Это позволяет обеспечить гарантированный уровень обслуживания для каждого сегмента, поскольку ресурсы базы данных не используются; однако это также означает, что многие базы данных созданы и должны поддерживаться.

Определение таблиц сегментов и ссылочных таблиц

Существует два типа таблиц в сегментированной базе данных.

Таблицы сегментов - это таблицы, которые были разбиты на основе ключа сегментации. Для этих таблиц данные будут разными, в зависимости от того, к какой базе данных подключается клиент.

Ссылочные таблицы абсолютно одинаковы независимо от базы данных.

В примере с розничным магазином таблица продуктов может быть ссылочной таблицей, потому что для всех магазинов потребуется полный список всех продуктов. С другой стороны, таблица ProductSold имела бы данные, которые относятся только к отдельному хранилищу, поэтому это таблица сегментов.

Перенос ключа сегментации в таблицы сегментов

Как упоминалось ранее, все таблицы, которые должны быть фрагментированы, должны иметь ключ сегментации в качестве столбца. Этот шаг просто создает столбец [StoreID] в каждой фрагментированной таблице и обновляет значение в соответствующем хранилище. Для этой части необходимо будет создать и запустить ручные скрипты.

Создание базы данных карты сегментов

Карта сегментов отслеживает, какие сегменты находятся в базе данных. Она также обрабатывает правильную строку подключения к приложению.

Важно, чтобы она была размещена в отдельной базе данных, чтобы гарантировать, что производительность может поддерживаться для всех клиентов, независимо от того, какой из клиентов имеет проблемы.

База данных Shard Map представляет собой обычную базу данных Azure SQL и должна быть создана через интерфейс Azure portal. Эта база данных будет удалена всеми клиентами, чтобы узнать, к какой базе данных сегментов они должны подключиться, поэтому убедитесь, что она достаточно мощная для обработки ожидаемой нагрузки.

Регистрация схемы базы данных в карте сегментов

Схема базы данных должна быть зарегистрирована в карте сегментов. Она используется процессом Split-Merge для идентификации сегментированных и ссылочных таблиц.

Ниже приведены примеры команд PowerShell. Обратите внимание, что он использует модуль, написанный командой Azure Shard.

$ShardMapManager = new-ShardMapManager -UserName 'example' -Password '*****!' -SqlServerName 'example.database.windows.net' -SqlDatabaseName 'ShardAdmin'

 

# $ShardMapManager is the shard map manager object

new-ListShardMap -KeyType $([guid]) -ShardMapManager $ShardMapManager -ListShardMapName 'ListShardMap'

 

$SchemaInfo = New-Object Microsoft.Azure.SqlDatabase.ElasticScale.ShardManagement.Schema.SchemaInfo

 

# Reference Table

$ReferenceTableName = "Product"

$SchemaInfo.Add($(New-Object Microsoft.Azure.SqlDatabase.ElasticScale.ShardManagement.Schema.ReferenceTableInfo($ReferenceTableName)))

 

# Sharded Table

$ShardedTableSchemaName = "dbo"

$ShardedTableName = "ProductSold"

$ShardedTableKeyColumnName = "StoreID"

$SchemaInfo.Add($(New-Object Microsoft.Azure.SqlDatabase.ElasticScale.ShardManagement.Schema.ShardedTableInfo($ShardedTableSchemaName, $ShardedTableName, $ShardedTableKeyColumnName)))

 

$SchemaInfoCollection = $ShardMapManager.GetSchemaInfoCollection()

 

# Add the SchemaInfo for this Shard Map to the Schema Info Collection

$SchemaInfoCollection.Add('StoreListShardMap', $SchemaInfo)

Создание облачных сервисов для запуска процесса Split-Merge

Процесс  Split-Merge выполняется через облачную службу в Azure. После регистрации сегмента с помощью карты сегмента в процесс Split-Merge отправляется уведомление, и новый запрос помещается в очередь. Каждый запрос обрабатывается последовательно, и из-за этого мы рекомендуем иметь несколько облачных сервисов для запуска различных запросов Split-Merge.

Создание новых баз данных и назначение сегментов

Для каждого сегмента в существующей базе данных должны быть выполнены следующие шаги:

Создайте новую базу данных Azure SQL и объекты базы данных, такие как таблицы, отображения и т. д. ...

В зависимости от количества сегментов, с которыми вы имеете дело, это скорее всего будет проще осуществить с помощью сценария PowerShell. Важно, чтобы на данный момент вы не создавали или, по крайней мере, не разрешали ограничений. Утилита split-merge не ссылается на них при вставке данных, и процесс завершится с ошибкой.

Свяжите новую базу данных с значением параметра GUID shard в Shard Map

Следующий фрагмент кода сделает следующее:

$ShardMapManager = Get-ShardMapManager -UserName 'example' -Password '****!' -SqlServerName 'example.database.windows.net' -SqlDatabaseName 'ShardAdmin'

 

# Get Shard Map.

$ShardMap = Get-ListShardMap -KeyType $([guid]) -ShardMapManager $ShardMapManager -ListShardMapName $ShardMapName

 

# Add new DB to shard map

Add-Shard -ShardMap $ShardMap -SqlServerName $FullSQLServerName -SqlDatabaseName $ShardName | wait-process

 

# Add shard to shard map -- Mapped to $SourceDB because that's where it is currently

Add-ListMapping -keyType $([guid]) -ListShardMap $ShardMap -ListPoint $Guid -SqlServerName $FullSQLServerName -SQLDatabaseName $SourceDB | wait-process

Назначьте новый сегмент для облачной службы для процесса Split-Merge

Опять же, этот фрагмент кода является примером этого. В этом случае значение модуля используется для назначения каждого сегмента другой службе Split-Merge.

$mod = $NumOfShards % $NumOfMergeSplitApps

 

if ($mod -eq 1) {

 $SplitMergeURL = "https://example-mergesplit.cloudapp.net"

 $LogOutput = (Get-Date).ToShortDateString() + " " + (Get-Date).ToShortTimeString() + " : " + $ShardName + " sent to " + $SplitMergeURL

 Add-Content -Path $LogFile -value $LogOutput

}

elseif ($mod -eq 2) {

 $SplitMergeURL = "https://example-mergesplit2.cloudapp.net"

 $LogOutput = (Get-Date).ToShortDateString() + " " + (Get-Date).ToShortTimeString() + " : " + $ShardName + " sent to " + $SplitMergeURL

 Add-Content -Path $LogFile -value $LogOutput

}

else{

 $SplitMergeURL = "https://example-mergesplit10.cloudapp.net"

 $LogOutput = (Get-Date).ToShortDateString() + " " + (Get-Date).ToShortTimeString() + " : " + $ShardName + " sent to " + $SplitMergeURL

 Add-Content -Path $LogFile -value $LogOutput

}

 

# Queue up the split database operation

$OperationID = Submit-ShardletMoveRequest `

 -SplitMergeServiceEndpoint $SplitMergeURL `

 -ShardMapManagerServerName $ShardMapServerName `

 -ShardMapManagerDatabaseName $ShardMapDB `

 -ShardMapName $ShardMapName `

 -ShardKeyType 'guid' `

 -ShardletValue $Guid `

 -TargetServerName $FullSQLServerName `

 -TargetDatabaseName $ShardName `

 -UserName $AdminLogin `

 -Password $AdminPasswd `

 -CertificateThumbprint '####' #Unique to your project. See MS Tutorial

 

$LogOutput = (Get-Date).ToShortDateString() + " " + (Get-Date).ToShortTimeString() + " : " + "Operation ID: " + $OperationID

Add-Content -Path $LogFile -value $LogOutput

Мониторинг процессов Split-Merge

Процесс Split-Merge регистрирует свое текущее состояние в базе данных, и каждый процесс имеет свой собственную БД. Базы данных для этого примера будут размещены на сервере базы данных картысегментов и названы example-mergesplitN, где N - число.

В приведенных ниже запросах будут возвращены сведения о выполняемом в данный момент процессе разделения, любом успешном или неудачном процессе и количестве оставшихся процессов в очереди.

SELECT

 [TimeStamp] LastUpdateTime,

 [Status],

 Progress [EstPercentDone],

 OperationID,

 CancelRequest [Cancelled],

 Details

FROM

 RequestStatus

WHERE

 OperationID IN (select operationid from requeststatus where [status] not in ('Queued', 'Canceled', 'Failed', 'Succeeded'))

ORDER BY

 LastUpdateTime desc;

 

SELECT

 *

FROM

 RequestStatus

WHERE

 status IN ('Failed', 'Succeeded')

ORDER BY

 [timestamp] desc;

 

SELECT

 *

FROM

 RequestStatus

WHERE

 status = 'queued'

ORDER BY

 [timestamp] desc;

Измените код приложения для использования Shard Map

Microsoft написала набор библиотек, называемых ShardMapManagerFactory, чтобы обеспечить легкий переход к фрагментированной базе данных. Эти библиотеки позволяют клиенту переходить в Sharding Key и возвращать строку соединения в базу данных, связанную с этим сегментом.

Включение ограничений внешнего ключа

Процесс Split-Merge не выполняет операции INSERT или DELETE в любом конкретном порядке и не учитывает ограничения внешнего ключа. Из-за этого все ограничения должны быть отключены до запуска процесса Split-Merge.

No Comments

Add a Comment