Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье описан векторный тип данных SQL, реализованный драйвером Microsoft ODBC для SQL Server, начиная с версии 18.6.1.1. В этом документе описано поведение драйвера Майкрософт для вектора и предоставляет рекомендации по использованию, заметки для API и фрагменты кода. Общие сведения о типах векторных данных см. в разделе "Тип данных Vector".
Обзор
Драйвер Microsoft ODBC для SQL Server изначально поддерживает тип векторных данных. Приложения могут эффективно хранить, извлекать и обрабатывать числовые внедрения фиксированного измерения, часто используемые в рабочих нагрузках машинного обучения и искусственного интеллекта. Драйвер предоставляет векторную поддержку через стандартные API ODBC и типы данных C. Приложения могут взаимодействовать с столбцами векторов SQL Server, не изменяя существующие рабочие процессы ODBC.
Применяется к: Драйвер Microsoft ODBC для SQL Server 18.6.1.1 и более поздних версий.
Для драйвера Майкрософт (18.6.1.1.1) поддержка векторов отключена по умолчанию и должна быть явно включена.
Представление нативного C
Если включена поддержка векторов, векторные столбцы обмениваются с помощью типизированной структуры C с именем SQL_SS_VECTOR_STRUCT.
typedef struct tagSQL_SS_VECTOR_STRUCT {
SQLSMALLINT dimension; /* Number of elements */
SQLSMALLINT type; /* Element type indicator (0 = float32) */
union {
float *f32; /* Pointer to float32 data */
} data;
} SQL_SS_VECTOR_STRUCT;
-
dimension: описывает количество элементов в векторе -
type: определяет базовый тип элемента (в настоящее времяfloat32) -
data.f32: указывает на буфер приложения, содержащий векторные значения
Включение поддержки векторов
Драйвер Microsoft предоставляет привязку C для конкретного драйвера
SQL_C_SS_VECTORи поддерживаетSQL_C_BINARYдля векторного вывода при настройке подключения или параметра драйвераvectorTypeSupportс значениемv1. На практике:При включении
vectorTypeSupport=v1API получения (например,SQLGetDataиSQLBindCol) могут возвращать векторные столбцы либо в видеSQL_C_SS_VECTOR, либоSQL_C_BINARY.SQL_C_SS_VECTORвозвращает вектор в компактной типизированной форме.SQL_C_BINARYвозвращает varbinary полезную нагрузку.Для ввода или привязки параметров драйвер Майкрософт (18.6.1.1 с
vectorTypeSupport=v1) поддерживает обаSQL_C_SS_VECTORиSQL_C_BINARY.SQL_C_SS_VECTORпредоставляет типизированные компактные входные привязки.SQL_C_BINARYэквивалентен и переносим. ИспользуйтеSQL_C_SS_VECTOR, если требуется, чтобы драйвер обрабатывал нагрузку как собственный тип вектора.Когда
vectorTypeSupport=off, векторные столбцы отображаются как varchar(max), содержащие массивы JSON.
Приложения также должны задать версию ODBC для ODBC 3.8, прежде чем использовать векторные типы:
SQLSetEnvAttr(
hEnv,
SQL_ATTR_ODBC_VERSION,
(SQLPOINTER)SQL_OV_ODBC3_80,
0);
Поддерживаемые форматы привязки
Нативное связывание вектора
Тип C: SQL_C_SS_VECTOR
Этот формат рекомендуется для критически важных для производительности приложений.
Двоичная привязка
Тип C: SQL_C_BINARY
Векторы возвращаются с использованием того же макета, что и SQL_C_SS_VECTOR. Приложения могут использовать этот формат для сценариев взаимодействия низкого уровня. Буфер указателя данных может быть непрерывным или несмежным по отношению к адресу памяти структуры.
Руководство по API ODBC
В этом разделе описывается взаимодействие API ODBC с данными вектора SQL Server, включая требования к макету буфера, NULL обработку и поддерживаемые представления данных. Все действия применяются, если vectorTypeSupport=v1 включена, и среда настроена для ODBC 3.8.
SQLBindCol
Используйте SQLBindCol для привязки векторных столбцов в результирующем наборе к буферам приложения.
- Типичный вызов:
SQLRETURN SQLBindCol(
SQLHSTMT StatementHandle,
SQLUSMALLINT ColumnNumber,
SQLSMALLINT TargetType,
SQLPOINTER TargetValuePtr,
SQLLEN BufferLength,
SQLLEN * StrLen_or_IndPtr);
TargetType: использованиеSQL_C_SS_VECTORилиSQL_C_BINARY.TargetValuePtr: указатель наSQL_SS_VECTOR_STRUCTмассив с плавающей запятой , еслиTargetTypeимеет значениеSQL_C_SS_VECTOR; в противном случае указатель на буфер с размером вStrLen_or_IndPtrкачестве значения.BufferLength:sizeof(SQL_SS_VECTOR_STRUCT)+ количество байтов, выделенных для буфера столбца (измерение * 4).StrLen_or_IndPtr: указатель, который получает длину байтов возвращаемого вектора (SQL_DESC_OCTET_LENGTH). Его значение равноsizeof(SQL_SS_VECTOR_STRUCT)+ размер массива с плавающей запятой (измерение * 4).
Ожидания макета буфера
Неконтигусный буфер (рекомендуется)
- Приложение выделяет по одному
SQL_SS_VECTOR_STRUCTна каждую строку. - Приложение выделяет память для
data.f32. - Драйвер заполняет векторные метаданные и записывает значения элементов в предоставленный буфер с плавающей запятой .
SQLLEN numberOfRow = 1000; // set to SQL_ATTR_ROW_ARRAY_SIZE
SQLULEN columnSize = x; // use SQLDescribeCol or SQLColAttributeW or sizeof(SQL_SS_VECTOR_STRUCT) + (dimension * 4)
SQL_SS_VECTOR_STRUCT vecBuffer[numberOfRow]
std::vector<SQLLEN> indicator(numberOfRow, 0);
for (int i = 0; i < numberOfRow; i++)
{
vecBuffer[i].dimension = static_cast<SQLUSMALLINT>((columnSizes[col - 1] - sizeof(SQL_SS_VECTOR_STRUCT)) / 4);
vecBuffer[i].type = SQL_VECTOR_TYPE_FLOAT32;
vecBuffer[i].data.f32 = (float*)malloc(vecBuffer[i].dimension * sizeof(float));
if (!vecBuffer[i].data.f32) {
std::cerr << "Memory allocation failed for vector data." << std::endl;
return SQL_ERROR;
}
}
SQLBindCol(hStmt, col, SQL_C_SS_VECTOR, vecBuffer, columnSize, indicators.data());
Непрерывный буфер
- Приложение выделяет один буфер и ODBC заполняет его соответствующим образом.
- Массив float должен начинаться сразу после структуры.
- Драйвер указывает
data.f32на эту смежную область.
SQLLEN numberOfRow = 1000; // set to SQL_ATTR_ROW_ARRAY_SIZE
SQLULEN columnSize = x; // use SQLDescribeCol or SQLColAttributeW or sizeof(SQL_SS_VECTOR_STRUCT) + (dimension * 4)
std::vector<BYTE> vecBuffer;
std::vector<SQLLEN> indicator(numberOfRow, 0);
vecBuffer.resize(numberOfRow * columnSize);
SQLBindCol(hStmt, col, SQL_C_BINARY, vecBuffer.data(), columnSize, indicators.data());
Обработка NULL для SQLBindCol
Если значение столбца равно NULL, драйвер устанавливает *StrLen_or_IndPtrSQL_NULL_DATA и не заполняет буфер. Всегда проверяйте индикатор перед доступом к содержимому вектора.
Замечание
Поведение чтения и извлечения строк для векторных столбцов подробно описано SQLFetch в разделе и SQLFetchScroll (см. эти ссылки на API для получения семантики и примера получения массива).
SQLGetData
Используется SQLGetData для извлечения векторных данных из несвязанных столбцов.
- Типичный вызов:
SQLRETURN SQLGetData(
SQLHSTMT StatementHandle,
SQLUSMALLINT Col_or_Param_Num,
SQLSMALLINT TargetType,
SQLPOINTER TargetValuePtr,
SQLLEN BufferLength,
SQLLEN * StrLen_or_IndPtr);
TargetType: использованиеSQL_C_SS_VECTORилиSQL_C_BINARY.TargetValuePtr: указатель наSQL_SS_VECTOR_STRUCTмассив с плавающей запятой , еслиTargetTypeимеет значениеSQL_C_SS_VECTOR; в противном случае указатель на буфер с размером вStrLen_or_IndPtrкачестве значения.BufferLength:sizeof(SQL_SS_VECTOR_STRUCT)+ количество байтов, выделенных для буфера столбца (измерение * 4).StrLen_or_IndPtr: указатель, который получает длину байтов возвращаемого вектора (SQL_DESC_OCTET_LENGTH). Его значение равноsizeof(SQL_SS_VECTOR_STRUCT)+ размер массива с плавающей запятой (измерение * 4).
Фрагментированное извлечение не поддерживается. Необходимо получить весь вектор в одном вызове.
Пример (собственный вектор):
SQLLEN dataLen = 0;
SQL_SS_VECTOR_STRUCT vec = {};
vec.data.f32 = (float*)malloc(x * sizeof(float)); // x is the dimension
if (!vec.data.f32) {
std::cerr << "Memory allocation failed for vector data." << std::endl;
return SQL_ERROR;
}
SQLGetData(hStmt, col, SQL_C_SS_VECTOR, &vec, sizeof(vec) + sizeof(float) * vec.dimension, &dataLen);
Обработка NULL для SQLGetData
Если значение столбца равно NULL, драйвер устанавливает *StrLen_or_IndPtrSQL_NULL_DATA и не заполняет буфер. Всегда проверяйте индикатор перед доступом к содержимому вектора.
Замечание
Поведение чтения и извлечения строк для векторных столбцов подробно описано SQLFetch в разделе и SQLFetchScroll (см. эти ссылки на API для получения семантики и примера получения массива).
SQLFetch
Для получения следующей строки и корректной обработки всех привязанных столбцов используется SQLFetch.
- Типичный вызов:
SQLRETURN SQLFetch(
SQLHSTMT StatementHandle);
Вызвать SQLFetch в стандартном цикле с привязанными через SqlVector столбцами SQLBindCol. Кроме того, используйте SQLGetData для извлечения данных в буфер приложения.
Пример (собственный вектор):
while ((ret = SQLFetch(hStmt)) == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO) {
// if SQLBindCol was used directly jump to read buffer
// else use SQLGetData and than read buffer.
std::cout << " data: [";
if (dataLen != SQL_NULL_DATA)
{
for (SQLUSMALLINT d = 0; d < vec.dimension; ++d) {
std::cout << vec.data.f32[d];
if (d + 1 < vec.dimension) std::cout << ", ";
}
}
std::cout << "]" << std::endl;
}
SQLFetchScroll
Используйте SQLFetchScroll для извлечения наборов строк в зависимости от заданной ориентации (следующей, предыдущей, абсолютной, относительной, по закладке). Драйвер правильно копирует векторные данные в буферы приложений.
- Типичный вызов:
SQLRETURN SQLFetchScroll(
SQLHSTMT StatementHandle,
SQLSMALLINT FetchOrientation,
SQLLEN FetchOffset);
Пример (собственный вектор):
// Fetch rows in batches
while ((ret = SQLFetchScroll(hStmt, SQL_FETCH_NEXT, 0)) != SQL_NO_DATA) {
for (SQLULEN i = 0; i < numRowsFetched; i++) {
// In case of Contiguous Buffer
SQL_SS_VECTOR_STRUCT* vecptr = reinterpret_cast<SQL_SS_VECTOR_STRUCT*>(
vecBuffer.data() + (i * columnSizes[col - 1]));
float* floats = reinterpret_cast<float*>(
reinterpret_cast<char*>(vecptr) + sizeof(SQL_SS_VECTOR_STRUCT)
);
// in Case of non-contiguous Buffer
SQL_SS_VECTOR_STRUCT* vecptr = &vecBuffer[i];
float* floats = vecptr->data.f32;
if (indicators[i] != SQL_NULL_DATA)
{
for (SQLUSMALLINT d = 0; d < vecptr->dimension; ++d) {
std::cout << floats[d];
if (d + 1 < vecptr->dimension) std::cout << ", ";
}
}
std::cout << "]" << std::endl;
}
}
SQLBindParameter
Используется SQLBindParameter для отправки векторных значений в SQL Server.
- Типичный вызов:
SQLRETURN SQLBindParameter(
SQLHSTMT StatementHandle,
SQLUSMALLINT ParameterNumber,
SQLSMALLINT InputOutputType,
SQLSMALLINT ValueType,
SQLSMALLINT ParameterType,
SQLULEN ColumnSize,
SQLSMALLINT DecimalDigits,
SQLPOINTER ParameterValuePtr,
SQLLEN BufferLength,
SQLLEN * StrLen_or_IndPtr);
-
ParameterValuePtr: указывает на заполненноеSQL_SS_VECTOR_STRUCT -
ColumnSize: игнорируется для входных параметров. Для выходных параметров и сценариев выполнения данных укажите общий размер вектора:sizeof(SQL_SS_VECTOR_STRUCT)+ (размер массива с плавающей запятой ) -
DecimalDigits: игнорируется для входных параметров. Для выходных параметров и сценариев выполнения данных укажите базовый тип вектора -
BufferLength: ≥sizeof(SQL_SS_VECTOR_STRUCT)+ (измерение *sizeof(float)) -
*StrLen_or_IndPtr: должен содержать тот же общий размер
Пример (собственный вектор):
float values[3] = {1.0f, 2.0f, 3.0f};
SQL_SS_VECTOR_STRUCT vec;
SQLLEN cb;
vec.dimension = 3;
vec.type = 0; /* float32 */
vec.data.f32 = values;
cb = sizeof(vec) + sizeof(values);
SQLBindParameter(
hStmt, 1, SQL_PARAM_INPUT, SQL_C_SS_VECTOR, SQL_SS_VECTOR, 0, 0, &vec, cb, &cb);
Обработка NULL для SQLBindParameter
Приложения могут указывать вектор NULL с использованием любого из поддерживаемых подходов.
Назначьте
*StrLen_or_IndPtrнаSQL_NULL_DATAи передайтеNULLкакParameterValuePtrПредоставьте следующие
SQL_SS_VECTOR_STRUCTвозможности:Тип набора измерений =
float32data.f32=NULL
SQLPutData
Драйвер поддерживает SQLPutData для параметров вектора с указанными ограничениями:
Необходимо указать весь вектор в первом вызове.
Драйвер не поддерживает фрагментированную или добавочную передачу векторов.
NULLобработке следуют те же правила, что иSQLBindParameter.Типичный вызов:
SQLRETURN SQLPutData(
SQLHSTMT StatementHandle,
SQLPOINTER DataPtr,
SQLLEN StrLen_or_Ind);
-
DataPtr: указывает на заполненноеSQL_SS_VECTOR_STRUCT -
StrLen_or_Ind:sizeof(SQL_SS_VECTOR_STRUCT)+ (измерение *sizeof(float))
Пример (собственный вектор):
std::vector<float> floatArray = { 1.0f, 2.0f, 3.0f };
SQL_SS_VECTOR_STRUCT vectorValue = {0};
vectorValue.type = SQL_VECTOR_TYPE_FLOAT32;
vectorValue.dimension = (SQLUSMALLINT)floatArray.size();
vectorValue.data.f32 = floatArray.data();
// Tell ODBC this parameter will be supplied at execution time
SQLLEN cbVectorLen = SQL_LEN_DATA_AT_EXEC(
(SQLLEN)(sizeof(SQL_SS_VECTOR_STRUCT) + floatArray.size() * sizeof(float))
);
// Optional token to identify which parameter needs data
SQLPOINTER token = (SQLPOINTER)1;
// Bind as DATA_AT_EXEC: BufferLength is 0, value pointer can be a token
SQLRETURN rc = SQLBindParameter(hStmt, 1, SQL_PARAM_INPUT, SQL_C_SS_VECTOR, SQL_SS_VECTOR, 0, 0, token, 0, &cbVectorLen);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
// handle error
}
rc = SQLExecute(hStmt);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NEED_DATA) {
// handle error
}
SQLPOINTER pParamToken = NULL;
rc = SQLParamData(hStmt, &pParamToken);
if (rc == SQL_NEED_DATA) {
// Provide entire vector in first SQLPutData call (no chunking)
rc = SQLPutData(
hStmt,
(SQLPOINTER)&vectorValue,
(SQLLEN)(sizeof(SQL_SS_VECTOR_STRUCT) + floatArray.size() * sizeof(float))
);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
// handle error
}
// Finalize parameter transfer
rc = SQLParamData(hStmt, &pParamToken);
}
Метаданные дескриптора
При включении поддержки векторов драйвер Microsoft ODBC для SQL Server предоставляет метаданные вектора через стандартные API дескриптора ODBC. Приложения могут использовать сведения о дескрипторе для обнаружения сведений о схеме векторов, размеров буфера вычислений и правильной настройки привязок для параметров и результирующих наборов.
Значения полей дескриптора для вектора
В следующей таблице перечислены значения полей дескриптора для столбцов и параметров векторов SQL Server.
| Поле дескриптора | Ценность | Description |
|---|---|---|
SQL_DESC_TYPE |
SQL_SS_VECTOR (-156) |
Идентификатор базового типа данных SQL |
SQL_DESC_CONCISE_TYPE |
SQL_SS_VECTOR |
Краткий тип данных SQL |
SQL_DESC_TYPE_NAME |
vector |
Имя типа SQL |
SQL_DESC_LOCAL_TYPE_NAME |
vector |
Имя локального типа драйвера |
SQL_DESC_LENGTH |
sizeof(SQL_SS_VECTOR_STRUCT) + (dimension * sizeof(float)) |
Логический размер векторного значения |
SQL_DESC_OCTET_LENGTH |
То же, что и SQL_DESC_LENGTH |
Физический размер в байтах |
SQL_DESC_PRECISION |
То же, что и SQL_DESC_LENGTH |
Используется для отчета о размере вектора |
SQL_DESC_SCALE |
SQL_VECTOR_TYPE_FLOAT32 |
Тип базового элемента вектора |
SQL_DESC_DISPLAY_SIZE |
dimension * VECTOR_FLOAT32_TO_CHAR_JSON_MAX_SIZE |
Максимальная длина отображения JSON |
SQL_DESC_FIXED_PREC_SCALE |
SQL_FALSE |
Vector не имеет фиксированной точности и масштабирования |
SQL_DESC_NULLABLE |
SQL_NULLABLE |
Векторные столбцы разрешают NULL значения |
SQL_DESC_NUM_PREC_RADIX |
0 |
Нечисленный тип |
SQL_DESC_SEARCHABLE |
SQL_PRED_NONE |
Непригодные для использования в предикаатах |
SQL_DESC_UNSIGNED |
SQL_TRUE |
Тип элемента не назначен |
SQL_DESC_AUTO_UNIQUE_VALUE |
SQL_FALSE |
Не автоуникальный |
SQL_DESC_CASE_SENSITIVE |
SQL_FALSE |
Регистрозависимость не имеет значения |
SQL_DESC_UPDATABLE |
SQL_ATTR_READWRITE_UNKNOWN |
Неизвестная обновляемость |
SQLDescribeCol
Когда вы вызываете SQLDescribeCol для векторного столбца:
-
DataTypeравенSQL_SS_VECTOR -
ColumnSizeсоответствуетSQL_DESC_PRECISION -
DecimalDigitsявляется0(индикатор базового типа, а не числовая шкала) -
NullableравенSQL_NULLABLE
Размер сообщаемого столбца представляет собственный размер полезных данных вектора: sizeof(SQL_SS_VECTOR_STRUCT) + (измерение * sizeof(float))
SQLDescribeParam
При использовании SQLDescribeParam для параметра вектора :
-
DataTypeравенSQL_SS_VECTOR -
ColumnSizeравен размеру полезной нагрузки собственного вектора -
DecimalDigitsявляется0(индикатор базового типа, а не числовая шкала) -
NullableравенSQL_NULLABLE
Эта информация позволяет приложениям правильно выделять буферы параметров перед привязкой.
SQLColAttribute
Используйте
SQLColAttribute(hstmt, ColumnNumber, SQL_DESC_OCTET_LENGTH, ...), чтобы получить точную длину в байтах полезной нагрузки вектора.SQL_DESC_LENGTHиSQL_DESC_PRECISIONможет содержать значения, относящиеся к драйверу. Для числа байтов предпочитайтеSQL_DESC_OCTET_LENGTH.-
NULLобработка: если столбец имеетNULLзначение (SQLColAttributeилиStrLen_or_IndPtrиспользуется сSQLBindCol) возвращаетсяSQL_NULL_DATA. Проверьте наличиеSQL_NULL_DATAперед использованием возвращаемых длин или буферов.
-
Копирование больших объемов данных (BCP)
Можно выполнять массовый импорт и экспорт векторных столбцов через файлы BCP и bcp_bind API, как и другие типы данных. В настоящее время импорт и экспорт векторов поддерживает только собственный формат (SQLVECTOR) или varbinary (SQLBINARY), но не символьный формат. Преобразование между векторным типом и типом символов не поддерживается.
Дополнительные сведения о маркере типа, длине префикса по умолчанию и длине поля по умолчанию для вектора см. в разделе "Тип хранилища файлов", "Длина префикса" и "Длина поля".
bcp_gettypename
При использовании bcp_gettypename для получения имени типа SQL вектор возвращается токен типа BCP (SQLVECTOR) и "vector".
bcp_bind
Используется bcp_bind для массового вставки переменных программы в векторный столбец.
Типичный вызов:
RETCODE bcp_bind (
HDBC hdbc,
LPCBYTE pData,
INT cbIndicator,
DBINT cbData,
LPCBYTE pTerm,
INT cbTerm,
INT eDataType,
INT idxServerCol);
-
pData: еслиcbIndicatorравно нулю, содержит указатель на данныеSQL_SS_VECTOR_STRUCT, которые содержат массив данных с плавающей запятой в поле . ЕслиcbIndicatorзначение ненулевое, индикатор отображается в памяти непосредственно перед данными. Таким образомpData, указывает на буфер, который сначала имеетcbIndicatorбайты индикатора длины, а затем структуру вектора. -
cbData: если задано, должно иметь точное значение -sizeof(SQL_SS_VECTOR_STRUCT)+ (sizeof(float32)* размерность). В противном случае возникает ошибка. -
eDataType:SQLVECTORилиSQLBINARY
При импорте данных в векторный столбец через bcp_bind, установите параметр eDataType на SQLVECTOR или SQLBINARY. В обоих случаях необходимо предоставить данные в виде SQL_SS_VECTOR_STRUCT.
Устранение неполадок и советы
- Если
SQLGetTypeInfoне содержитVECTOR, используйте хранение векторов в качестве varchar.