Изменение кода R/Python для выполнения в экземплярах SQL Server (в базе данных)
Область применения: SQL Server 2016 (13.x) и более поздних версий Управляемый экземпляр SQL Azure
В этой статье показано, как изменить код R или Python для выполнения в качестве хранимой процедуры SQL Server, чтобы повысить производительность при обращении к данным SQL.
Перемещенный из локальной среды IDE или другой среды в SQL Server код R/Python обычно работает без необходимости вносить дальнейшие изменения. Это в частности справедливо для простого кода, например функции, принимающей некоторые входные данные и возвращающей значение. Кроме того, удобно переносить решения с пакетами RevoScaleR/revoscalepy, которые поддерживают разные контексты выполнения с минимальными изменениями. Обратите внимание, что MicrosoftML применяется к SQL Server 2016 (13.x), SQL Server 2017 (14.x) и SQL Server 2019 (15.x) и не отображается в SQL Server 2022 (16.x).
Тем не менее, в следующих случаях может потребоваться значительная переработка кода:
- Вы используете библиотеки, которые обращаются к сети или которые нельзя установить в SQL Server.
- В коде выполняются отдельные вызовы источников данных, расположенных вне среды SQL Server, таких как листы Excel, файлы в общих папках или другие базы данных.
- Вам необходимо параметризировать хранимую процедуру и выполнить код в параметре @script sp_execute_external_script.
- Исходное решение включает несколько шагов, которые в рабочей среде эффективнее выполнять по отдельности. В качестве примера можно сравнить подготовку данных или формирование признаков с обучением модели, оценкой и созданием отчетов.
- Вы хотите оптимизировать производительность, изменяя библиотеки, используя параллельное выполнение или передавая нагрузки некоторых процессов в SQL Server.
Шаг 1. Планирование ресурсов и требований
Пакеты
Определите необходимые пакеты и убедитесь, что они работают в SQL Server.
Заранее установите пакеты в заданную по умолчанию библиотеку пакетов, которую используют службы машинного обучения. Пользовательские библиотеки не поддерживаются.
Источники данных
Если вы планируете внедрить код в процедуру sp_execute_external_script, определите первичный и вторичный источники данных.
В качестве первичных источников выступают большие наборы данных, например обучающие данные модели или входные данные для прогнозирования. Спланируйте сопоставление самого большого набора данных с входным параметром процедуры sp_execute_external_script.
В качестве вторичных источников обычно используются наборы меньшего размера, например списки факторов или дополнительные переменные группирования.
На данный момент процедура sp_execute_external_script поддерживает только один набор данных в качестве входного параметра. При необходимости вы можете добавить несколько скалярных или двоичных входов.
Вызовы хранимой процедуры, которым предшествует EXECUTE, нельзя использовать в качестве входных данных процедуры sp_execute_external_script. При этом вы можете использовать запросы, представления и любые другие допустимые инструкции SELECT.
Определите нужные выходные данные. Если код выполняется с помощью хранимой процедуры sp_execute_external_script, она сможет вернуть только один кадр данных. Но вы можете определить несколько наборов скалярных выходных данных, таких как графики и модели в двоичном формате, а также другие скалярные значения, получаемые на основе кода или параметров SQL.
Типы данных
Подробные сведения о сопоставлении типов данных между R/Python и SQL Server см. в следующих статьях:
- Сопоставления типов данных между R и SQL Server
- Сопоставления типов данных между Python и SQL Server
Рассмотрите типы данных, используемые в коде R/Python, и сделайте следующее:
Составьте контрольный список возможных проблем с типами данных.
Службы машинного обучения SQL Server поддерживают все типы данных R/Python. Однако SQL Server поддерживает более разнообразные типы данных, чем R или Python. Поэтому некоторые неявные преобразования типов данных выполняются при перемещении данных SQL Server в код и из нее. Кроме того, может потребоваться явным образом привести или преобразовать некоторые данные.
Значения NULL поддерживаются. Тем не менее, R использует структуру данных
na
для представления отсутствующих значений, подобных значениям NULL.Рекомендуется убрать зависимости от данных, которые нельзя использовать в R. Например, типы данных rowid и GUID из SQL Server не поддерживаются в R, а их использование приводит к возникновению ошибок.
Шаг 2. Преобразование или переупаковка кода
Объем необходимых изменений в коде зависит от того, планируете ли вы отправлять код с удаленного клиента для выполнения в контексте вычислений SQL Server или хотите развернуть код в составе хранимой процедуры. Второй способ позволяет повысить производительность и безопасность данных, хотя он и накладывает некоторые дополнительные требования.
Чтобы избежать перемещения данных, по возможности определяйте в качестве первичных входных данных SQL-запрос.
При выполнении кода в хранимой процедуры вы можете передать несколько наборов скалярных входных данных. Для всех параметров, которые требуется использовать в выходных данных, добавьте ключевое слово OUTPUT.
Например, следующий скалярный вход
@model_name
содержит имя модели, которое также позже изменяется с помощью скрипта R и включается в выходные данные в отдельном столбце:-- declare a local scalar variable which will be passed into the R script DECLARE @local_model_name AS NVARCHAR (50) = 'DefaultModel'; -- The below defines an OUTPUT variable in the scope of the R script, called model_name -- Syntactically, it is defined by using the @model_name name. Be aware that the sequence -- of these parameters is very important. Mandatory parameters to sp_execute_external_script -- must appear first, followed by the additional parameter definitions like @params, etc. EXECUTE sp_execute_external_script @language = N'R', @script = N' model_name <- "Model name from R script" OutputDataSet <- data.frame(InputDataSet$c1, model_name)' , @input_data_1 = N'SELECT 1 AS c1' , @params = N'@model_name nvarchar(50) OUTPUT' , @model_name = @local_model_name OUTPUT; -- optionally, examine the new value for the local variable: SELECT @local_model_name;
Все переменные, передаваемые в качестве параметров хранимой процедуры sp_execute_external_script, должны быть сопоставлены с переменными в коде. По умолчанию переменные сопоставляются по имени. Все столбцы во входном наборе данных также должны быть сопоставлены с переменными в скрипте.
Предположим, что скрипт R содержит следующую формулу:
formula <- ArrDelay ~ CRSDepTime + DayOfWeek + CRSDepHour:DayOfWeek
Если входной набор данных не содержит столбцы с именами ArrDelay, CRSDepTime, DayOfWeek, CRSDepHour и DayOfWeek, возникает ошибка.
В некоторых случаях необходимо заранее определить схему выходных данных для результатов.
Например, чтобы вставить данные в таблицу, необходимо использовать инструкцию WITH RESULT SET для определения схемы.
Схема выходных данных также требуется, если скрипт использует аргумент
@parallel=1
. Дело в том, что SQL Server может распределить запрос между несколькими параллельными процессами и собирать результаты в конце. Поэтому схему вывода необходимо подготовить до того, как могут быть созданы параллельные процессы.В других случаях схему результатов можно опустить, указав параметр WITH RESULT SETS UNDEFINED. Эта инструкция возвращает набор данных из скрипта, не присваивая имена столбцам и не определяя типы данных SQL.
Рассмотрите возможность создания данных времени и отслеживания с использованием T-SQL вместо R/Python.
Например, для передачи системного времени или других сведений, используемых при аудите и хранении, можно добавить вызов T-SQL, который передается в результаты, чтобы не создавать аналогичные данные в скрипте.
Повышение производительности и безопасности
- Не рекомендуется записывать прогнозы или промежуточные результаты в файл. Чтобы избежать перемещения данных, записывайте прогнозы в таблицу.
Выполняйте все запросы заранее и используйте планы запросов SQL Server для определения задач, которые могут выполняться параллельно.
Если входной запрос может выполняться параллельно, задайте параметр
@parallel=1
как часть аргументов процедуры sp_execute_external_script.Параллельная обработка с использованием этого параметра обычно поддерживается, если SQL Server может работать с секционированными таблицами или распределять запрос между несколькими процессами и выполнять статистическую обработку результатов в конце. Параллельная обработка с использованием этого флага обычно не поддерживается, если для обучения моделей применяются алгоритмы, требующие считывания всех данных, или если вам нужно создать агрегаты.
Определите, нет ли в коде действий, которые можно выполнять отдельно или более эффективно с помощью вызова отдельной хранимой процедуры. Например, вы можете повысить производительность, конструируя или извлекая признаки отдельно и сохраняя значения в таблице.
Найдите способы выполнения вычислений на основе наборов с использованием кода T-SQL, а не R/Python.
Например, это решение R показывает, как определяемые пользователем функции T-SQL и R могут выполнять ту же задачу проектирования функций: Обработка и анализ данных сквозное пошаговое руководство.
Вместе с разработчиком базы данных определите способы повышения производительности с помощью таких компонентов SQL Server, как таблицы, оптимизированные для памяти, или, если вы используете выпуск Enterprise, Resource Governor.
Если вы используете R, по возможности замените обычные функции R функциями RevoScaleR, которые поддерживают распределенное выполнение. Дополнительные сведения см. в статье Сравнение функций Base R и RevoScaleR.
Шаг 3. Подготовка к развертыванию
Обратитесь к администратору, чтобы установить и протестировать пакеты до развертывания кода.
В среде разработки допустимо устанавливать пакеты как часть кода, но это не рекомендуется делать в рабочей среде.
Пользовательские библиотеки не поддерживаются, даже если вы используете хранимые процедуры или выполняете код R/Python в контексте вычислений SQL Server.
Упаковка кода R/Python в хранимую процедуру
Создайте определяемую пользователем функцию T-SQL, внедрив код с помощью инструкции sp-execute-external-script.
Если у вас более сложный код R, используйте пакет R sqlrutils, чтобы преобразовать код. С помощью этого пакета опытные пользователи R могут создавать эффективный код хранимых процедур. Вам нужно переписать код R как единую функцию с четко определенными входными и выходными данными, а затем с помощью пакета sqlrutils создать входные и выходные данные в правильном формате. Пакет sqlrutils создает полный код хранимой процедуры и также может зарегистрировать ее в базе данных.
Дополнительные сведения и примеры см. в статье, посвященной пакету sqlrutils (SQL).
Интеграция с другими рабочими процессами
Используйте средства T-SQL и процессы извлечения, преобразования и загрузки. Выполняйте формирование и извлечение признаков, а также очистку данных, заранее в рамках процессов обработки данных.
Работая в специализированной среде разработки, вы можете извлекать данные на компьютер и выполнять их итеративный анализ, а также записывать и отображать результаты. Но при переносе кода в SQL Server большую часть этого процесса можно упростить или делегировать другим средствам SQL Server.
Используйте безопасные стратегии асинхронной визуализации.
Пользователи SQL Server часто не могут получить доступ к файлам на сервере, а клиентские средства SQL обычно не поддерживают графические устройства R/Python. Если в вашем решении создаются диаграммы и другие графические элементы, рекомендуется экспортировать их в виде двоичных данных и записывать или сохранять в таблицу.
Упакуйте функции прогнозирования и оценки в хранимые процедуры, что позволит приложениям напрямую обращаться к ним.
Следующие шаги
Примеры развертывания решения R и Python в SQL Server можно найти в следующих руководствах:
Учебники по R
Разработка прогнозной модели в R с помощью машинного обучения SQL
Прогнозирование стоимости поездки в нью-йоркском такси с использованием двоичной классификации