Copie y transforme datos en Azure Database for PostgreSQL mediante Azure Data Factory o Synapse Analytics.
SE APLICA A: Azure Data Factory Azure Synapse Analytics
Sugerencia
Pruebe Data Factory en Microsoft Fabric, una solución de análisis todo en uno para empresas. Microsoft Fabric abarca todo, desde el movimiento de datos hasta la ciencia de datos, el análisis en tiempo real, la inteligencia empresarial y los informes. Obtenga información sobre cómo iniciar una nueva evaluación gratuita.
En este artículo se explica el uso de la actividad de copia en las canalizaciones de Azure Data Factory y Synapse Analytics para copiar datos desde y hacia Azure Database for PostgreSQL, y cómo usar Data Flow para transformarlos en datos de Azure Database for PostgreSQL. Para obtener más información, lea los artículos de introducción para Azure Data Factory y Synapse Analytics.
Ese conector se usa especialmente para el servicio Azure Database for PostgreSQL. Para copiar datos desde una base de datos PostgreSQL genérica ubicada en el entorno local o en la nube, use el conector PostgreSQL.
Funcionalidades admitidas
Este conector de Azure Database for PostgreSQL es compatible con las capacidades siguientes:
Funcionalidades admitidas | IR | Puntos de conexión privados administrados de Synapse (versión preliminar) |
---|---|---|
Actividad de copia (origen/receptor) | ① ② | ✓ |
Flujo de datos de asignación (origen/receptor) | ① | ✓ |
Actividad de búsqueda | ① ② | ✓ |
① Azure Integration Runtime ② Entorno de ejecución de integración autohospedado
Las tres actividades funcionan en todas las opciones de implementación de Azure Database for PostgreSQL:
Introducción
Para realizar la actividad de copia con una canalización, puede usar una de los siguientes herramientas o SDK:
- La herramienta Copiar datos
- Azure Portal
- El SDK de .NET
- El SDK de Python
- Azure PowerShell
- API REST
- La plantilla de Azure Resource Manager
Creación de un servicio vinculado a Azure Database for PostgreSQL mediante la interfaz de usuario
Siga estos pasos para crear un servicio vinculado a Azure Database for PostgreSQL en la interfaz de usuario de Azure Portal.
Vaya a la pestaña Administrar del área de trabajo de Azure Data Factory o Synapse y seleccione Servicios vinculados; luego haga clic en Nuevo:
Busque PostgreSQL y seleccione el conector de Azure Database for PostgreSQL.
Configure los detalles del servicio, pruebe la conexión y cree el nuevo servicio vinculado.
Detalles de configuración del conector
En las secciones siguientes se proporcionan detalles sobre las propiedades que se usan para definir entidades de Data Factory específicas para el conector de Azure Database for PostgreSQL.
Propiedades del servicio vinculado
Las siguientes propiedades son compatibles con el servicio vinculado de Azure Database for PostgreSQL:
Propiedad | Descripción | Obligatorio |
---|---|---|
type | La propiedad type debe establecerse en: AzurePostgreSql. | Sí |
connectionString | Cadena de conexión de ODBC para conectarse a Azure Database for PostgreSQL. También puede establecer una contraseña en Azure Key Vault y extraer la configuración de password de la cadena de conexión. Consulte los siguientes ejemplos y el artículo Almacenamiento de credenciales en Azure Key Vault con información detallada. |
Sí |
connectVia | Esta propiedad representa el tiempo de ejecución de integración que se usará para conectarse al almacén de datos. Puede usar los entornos Integration Runtime (autohospedado) (si el almacén de datos se encuentra en una red privada) o Azure Integration Runtime. Si no se especifica, se usará Azure Integration Runtime. | No |
Una cadena de conexión típica es Server=<server>.postgres.database.azure.com;Database=<database>;Port=<port>;UID=<username>;Password=<Password>
. Aquí encontrará más propiedades que puede establecer para su caso:
Propiedad | Descripción | Opciones | Obligatorio |
---|---|---|---|
EncryptionMethod (EM) | Método que usa el controlador para cifrar los datos enviados entre el controlador y el servidor de bases de datos. Por ejemplo: EncryptionMethod=<0/1/6>; |
0 (sin cifrado) (valor predeterminado) / 1 (SSL) / 6 (RequestSSL) | No |
ValidateServerCertificate (VSC) | Determina si el controlador valida el certificado que envía el servidor de bases de datos cuando está habilitado el cifrado SSL (método de cifrado = 1). Por ejemplo: ValidateServerCertificate=<0/1>; |
0 (deshabilitado) (valor predeterminado) / 1 (habilitado) | No |
Ejemplo:
{
"name": "AzurePostgreSqlLinkedService",
"properties": {
"type": "AzurePostgreSql",
"typeProperties": {
"connectionString": "Server=<server>.postgres.database.azure.com;Database=<database>;Port=<port>;UID=<username>;Password=<Password>"
}
}
}
Ejemplo:
Guardar la contraseña en Azure Key Vault
{
"name": "AzurePostgreSqlLinkedService",
"properties": {
"type": "AzurePostgreSql",
"typeProperties": {
"connectionString": "Server=<server>.postgres.database.azure.com;Database=<database>;Port=<port>;UID=<username>;",
"password": {
"type": "AzureKeyVaultSecret",
"store": {
"referenceName": "<Azure Key Vault linked service name>",
"type": "LinkedServiceReference"
},
"secretName": "<secretName>"
}
}
}
}
Propiedades del conjunto de datos
Si desea ver una lista completa de las secciones y propiedades disponibles para definir conjuntos de datos, consulte Conjuntos de datos. En esta sección se proporciona una lista de las propiedades que Azure Database for PostgreSQL admite en los conjuntos de datos.
Para copiar datos de Azure Database for PostgreSQL, establezca la propiedad type del conjunto de datos en AzurePostgreSqlTable. Se admiten las siguientes propiedades:
Propiedad | Descripción | Obligatorio |
---|---|---|
type | La propiedad "type" del conjunto de datos debe establecerse en AzurePostgreSqlTable. | Sí |
tableName | Nombre de la tabla | No (si se especifica "query" en el origen de la actividad) |
Ejemplo:
{
"name": "AzurePostgreSqlDataset",
"properties": {
"type": "AzurePostgreSqlTable",
"linkedServiceName": {
"referenceName": "<AzurePostgreSql linked service name>",
"type": "LinkedServiceReference"
},
"typeProperties": {}
}
}
Propiedades de la actividad de copia
Para ver una lista completa de las secciones y propiedades disponibles para definir actividades, consulte Canalizaciones y actividades. En esta sección se proporciona una lista de las propiedades compatibles con el origen de Azure Database for PostgreSQL.
Azure Database for PostgreSQL como origen
Para copiar datos de Azure Database for PostgreSQL, establezca el tipo de origen de la actividad de copia en AzurePostgreSqlSource. Se admiten las siguientes propiedades en la sección source de la actividad de copia:
Propiedad | Descripción | Obligatorio |
---|---|---|
type | La propiedad "type" del origen de la actividad de copia debe establecerse en AzurePostgreSqlSource. | Sí |
Query | Use la consulta SQL personalizada para leer los datos. Por ejemplo: SELECT * FROM mytable o SELECT * FROM "MyTable" . Tenga en cuenta que en PostgreSQL el nombre de la entidad se trata sin distinción de mayúsculas y minúsculas si no está entre comillas. |
No (si se especifica la propiedad tableName en el conjunto de datos) |
queryTimeout | El tiempo de espera antes de terminar el intento de ejecutar un comando y generar un error, el valor predeterminado es de 120 minutos. Si se establece el parámetro para esta propiedad, los valores permitidos son intervalos de tiempo, como "02:00:00" (120 minutos). Para más información, consulte CommandTimeout. | No |
partitionOptions | Especifica las opciones de creación de particiones de datos que se usan para cargar datos desde Azure SQL Database. Los valores permitidos son: None (valor predeterminado), PhysicalPartitionsOfTable y DynamicRange. Cuando se habilita una opción de partición (es decir, no None ), el grado de paralelismo para cargar datos de forma simultánea desde una instancia de Azure SQL Database se controla mediante el valor parallelCopies en la actividad de copia. |
No |
partitionSettings | Especifique el grupo de configuración para la creación de particiones de datos. Se aplica si la opción de partición no es None . |
No |
En partitionSettings : |
||
partitionNames | Lista de particiones físicas que deben copiarse. Se aplica si la opción de partición es PhysicalPartitionsOfTable . Si usa una consulta para recuperar datos de origen, enlace ?AdfTabularPartitionName en la cláusula WHERE. Para ver un ejemplo, consulte la sección Copia en paralelo desde Azure Database for PostgreSQL. |
No |
partitionColumnName | Especifique el nombre de la columna de origen de tipo entero o date/datetime (int , smallint , bigint , date , timestamp without time zone , timestamp with time zone o time without time zone ) que se va a usar en la creación de particiones por rangos para la copia en paralelo. Si no se especifica, se detectará automáticamente la clave principal de la tabla y se usará como columna de partición.Se aplica si la opción de partición es DynamicRange . Si usa una consulta para recuperar datos de origen, enlace ?AdfRangePartitionColumnName en la cláusula WHERE. Para ver un ejemplo, consulte la sección Copia en paralelo desde Azure Database for PostgreSQL. |
No |
partitionUpperBound | El valor máximo de la columna de partición para copiar datos. Se aplica si la opción de partición es DynamicRange . Si usa una consulta para recuperar datos de origen, enlace ?AdfRangePartitionUpbound en la cláusula WHERE. Para ver un ejemplo, consulte la sección Copia en paralelo desde Azure Database for PostgreSQL. |
No |
partitionLowerBound | El valor mínimo de la columna de partición para copiar datos. Se aplica si la opción de partición es DynamicRange . Si usa una consulta para recuperar datos de origen, enlace ?AdfRangePartitionLowbound en la cláusula WHERE. Para ver un ejemplo, consulte la sección Copia en paralelo desde Azure Database for PostgreSQL. |
No |
Ejemplo:
"activities":[
{
"name": "CopyFromAzurePostgreSql",
"type": "Copy",
"inputs": [
{
"referenceName": "<AzurePostgreSql input dataset name>",
"type": "DatasetReference"
}
],
"outputs": [
{
"referenceName": "<output dataset name>",
"type": "DatasetReference"
}
],
"typeProperties": {
"source": {
"type": "AzurePostgreSqlSource",
"query": "<custom query e.g. SELECT * FROM mytable>",
"queryTimeout": "00:10:00"
},
"sink": {
"type": "<sink type>"
}
}
}
]
Azure Database for PostgreSQL como receptor
Para copiar datos en Azure Database for PostgreSQL, se admiten las siguientes propiedades en la sección de receptor de la actividad de copia:
Propiedad | Descripción | Obligatorio |
---|---|---|
type | La propiedad "type" del receptor de la actividad de copia debe establecerse en AzurePostgreSQLSink. | Sí |
preCopyScript | Especifique una consulta de SQL para que la actividad de copia se ejecute antes de escribir datos en Azure Database for PostgreSQL en cada ejecución. Puede usar esta propiedad para limpiar los datos cargados previamente. | No |
writeMethod | El método usado para escribir datos en Azure Database for PostgreSQL. Los valores admitidos son:CopyCommand (valor predeterminado, que es más eficaz), BulkInsert. |
No |
writeBatchSize | Número de filas cargadas en Azure Database for PostgreSQL por lote. El valor permitido es un entero que representa el número de filas. |
No (el valor predeterminado es 1 000 000) |
writeBatchTimeout | Tiempo de espera para que la operación de inserción por lotes se complete antes de que se agote el tiempo de espera. Los valores permitidos son las cadenas de intervalo de tiempo. Un ejemplo es 00:30:00 (30 minutos). |
No (el valor predeterminado es 00:30:00) |
Ejemplo:
"activities":[
{
"name": "CopyToAzureDatabaseForPostgreSQL",
"type": "Copy",
"inputs": [
{
"referenceName": "<input dataset name>",
"type": "DatasetReference"
}
],
"outputs": [
{
"referenceName": "<Azure PostgreSQL output dataset name>",
"type": "DatasetReference"
}
],
"typeProperties": {
"source": {
"type": "<source type>"
},
"sink": {
"type": "AzurePostgreSQLSink",
"preCopyScript": "<custom SQL script>",
"writeMethod": "CopyCommand",
"writeBatchSize": 1000000
}
}
}
]
Copia paralela de Azure Database for PostgreSQL
En la actividad de copia, el conector de Azure Database for PostgreSQL proporciona la opción de crear particiones de datos integradas para copiar los datos en paralelo. Puede encontrar las opciones de creación de particiones de datos en la pestaña Origen de la actividad de copia.
Al habilitar la copia con particiones, la actividad de copia ejecuta consultas en paralelo en el origen de Azure Database for PostgreSQL para cargar los datos por particiones. El grado en paralelo se controla mediante el valor parallelCopies
de la actividad de copia. Por ejemplo, si establece parallelCopies
en cuatro, el servicio genera y ejecuta al mismo tiempo cuatro consultas de acuerdo con la configuración y la opción de partición que ha especificado, y cada consulta recupera una porción de la instancia de Azure Database for PostgreSQL.
Se sugiere habilitar la copia en paralelo con la creación de particiones de datos, especialmente si se cargan grandes cantidades de datos de Azure Database for PostgreSQL. Estas son algunas configuraciones sugeridas para diferentes escenarios. Cuando se copian datos en un almacén de datos basado en archivos, se recomienda escribirlos en una carpeta como varios archivos (solo especifique el nombre de la carpeta), en cuyo caso el rendimiento es mejor que escribirlos en un único archivo.
Escenario | Configuración sugerida |
---|---|
Carga completa de una tabla grande con particiones físicas. | Opción de partición: particiones físicas de la tabla. Durante la ejecución, el servicio detecta automáticamente las particiones físicas y copia los datos por particiones. |
Carga completa de una tabla grande, sin particiones físicas, aunque con una columna de enteros para la creación de particiones de datos. | Opciones de partición: partición por rangos dinámica. Columna de partición: especifique la columna usada para crear la partición de datos. Si no se especifica, se usa la columna de clave principal. |
Cargue una gran cantidad de datos mediante una consulta personalizada con particiones físicas. | Opción de partición: particiones físicas de la tabla. Consulta: SELECT * FROM ?AdfTabularPartitionName WHERE <your_additional_where_clause> .Nombre de la partición: especifique los nombres de las particiones desde las que se copiarán los datos. Si no se especifican, el servicio detecta automáticamente las particiones físicas en la tabla que ha especificado en el conjunto de datos de PostgreSQL. Durante la ejecución, el servicio reemplaza ?AdfTabularPartitionName por el nombre real de la partición y se lo envía a Azure Database for PostgreSQL. |
Carga de grandes cantidades de datos mediante una consulta personalizada, sin particiones físicas, aunque cuenta con una columna de enteros para la creación de particiones de datos. | Opciones de partición: partición por rangos dinámica. Consulta: SELECT * FROM ?AdfTabularPartitionName WHERE ?AdfRangePartitionColumnName <= ?AdfRangePartitionUpbound AND ?AdfRangePartitionColumnName >= ?AdfRangePartitionLowbound AND <your_additional_where_clause> .Columna de partición: especifique la columna usada para crear la partición de datos. Puede crear particiones en la columna con el tipo de datos entero o date/datetime. Límite de partición superior y límite de partición inferior: especifique si quiere filtrar en la columna de partición para recuperar solo los datos entre el intervalo inferior y el superior. Durante la ejecución, el servicio reemplaza ?AdfRangePartitionColumnName , ?AdfRangePartitionUpbound , y ?AdfRangePartitionLowbound por el nombre real de la columna y los rangos de valor para cada partición y los envía a Azure Database for PostgreSQL. Por ejemplo, si establece la columna de partición "ID" con un límite inferior de 1 y un límite superior de 80, con la copia en paralelo establecida en 4, el servicio recupera los datos de 4 particiones. Los identificadores están comprendidos entre [1, 20], [21, 40], [41, 60] y [61, 80] respectivamente. |
Procedimientos recomendados para cargar datos con la opción de partición:
- Seleccione una columna distintiva como columna de partición (como clave principal o clave única) para evitar la asimetría de datos.
- Si la tabla tiene una partición integrada, use la opción de partición "Particiones físicas de tabla" para obtener un mejor rendimiento.
- Si usa Azure Integration Runtime para copiar datos, puede establecer "unidades de integración de datos (DIU)" mayores (>4) para usar más recursos de cálculo. Compruebe los escenarios aplicables allí.
- "Grado de paralelismo de copia" controla los números de partición. Si se establece en un número demasiado grande, puede resentirse el rendimiento, así que se recomienda establecerlo como (DIU o número de nodos de IR autohospedados) * (2 a 4).
Ejemplo: carga completa de una tabla grande con particiones físicas
"source": {
"type": "AzurePostgreSqlSource",
"partitionOption": "PhysicalPartitionsOfTable"
}
Ejemplo: consulta con partición por rangos dinámica
"source": {
"type": "AzurePostgreSqlSource",
"query": "SELECT * FROM <TableName> WHERE ?AdfDynamicRangePartitionCondition AND <your_additional_where_clause>",
"partitionOption": "DynamicRange",
"partitionSettings": {
"partitionColumnName": "<partition_column_name>",
"partitionUpperBound": "<upper_value_of_partition_column (optional) to decide the partition stride, not as data filter>",
"partitionLowerBound": "<lower_value_of_partition_column (optional) to decide the partition stride, not as data filter>"
}
}
Propiedades de Asignación de instancias de Data Flow
Al transformar datos en el flujo de datos de asignación, puede leer tablas y escribir en ellas desde Azure Database for PostgreSQL. Para más información, vea la transformación de origen y la transformación de receptor en los flujos de datos de asignación. Puede optar por usar un conjunto de datos de Azure Database for PostgreSQL o un conjunto de datos insertado como tipo de origen y receptor.
Transformación de origen
En la tabla siguiente se enumeran las propiedades compatibles con el origen de Azure Database for PostgreSQL. Puede editar estas propiedades en la pestaña Source options (Opciones de origen).
Nombre | Descripción | Obligatorio | Valores permitidos | Propiedad de script de flujo de datos |
---|---|---|---|---|
Tabla | Si selecciona Tabla como entrada, el flujo de datos captura todos los datos de la tabla especificada en el conjunto de datos. | No | - | (solo para conjunto de datos en línea) tableName |
Consultar | Si selecciona Consultar como entrada, especifique una consulta SQL para capturar datos del origen, lo que invalida cualquier tabla que especifique en el conjunto de datos. El uso de consultas es una excelente manera de reducir las filas para pruebas o búsquedas. La cláusula Ordenar por no se admite, pero puede establecer una instrucción SELECT FROM completa. También puede usar las funciones de tabla definidas por el usuario. select * from udfGetData() es un UDF in SQL que devuelve una tabla que puede utilizar en el flujo de datos. Ejemplo de consulta: select * from mytable where customerId > 1000 and customerId < 2000 o select * from "MyTable" . Tenga en cuenta que en PostgreSQL el nombre de la entidad se trata sin distinción de mayúsculas y minúsculas si no está entre comillas. |
No | String | Query |
Nombre del esquema | Si selecciona Procedimiento almacenado como entrada, especifique un nombre de esquema del procedimiento almacenado o seleccione Actualizar para pedir al servicio que detecte los nombres de esquema. | No | String | schemaName |
Procedimiento almacenado | Si selecciona "Procedimiento almacenado" como entrada, especifique el nombre del procedimiento almacenado para leer datos de la tabla de origen o seleccione "Actualizar" para pedir al servicio que detecte los nombres de procedimiento. | Sí (si selecciona "Procedimiento almacenado" como entrada) | String | procedureName |
Parámetros de procedimiento | Si selecciona "Procedimiento almacenado" como entrada, especifique los parámetros de entrada del procedimiento almacenado en el orden establecido en el procedimiento o seleccione "Importar" para importar todos los parámetros de procedimiento mediante el formulario @paraName . |
No | Array | inputs |
Tamaño de lote | Especifique un tamaño de lote para fragmentar datos de gran tamaño en lotes. | No | Entero | batchSize |
Nivel de aislamiento | Elija uno de los siguientes niveles de aislamiento: - Read Committed - Read Uncommitted (predeterminado) - Repeatable Read - Serializable - None (ignorar el nivel de aislamiento) |
No | READ_COMMITTED READ_UNCOMMITTED REPEATABLE_READ SERIALIZABLE NONE |
isolationLevel |
Ejemplo de script de origen de Azure Database for PostgreSQL
Cuando se usa Azure Database for PostgreSQL como tipo de origen, el script de flujo de datos asociado es:
source(allowSchemaDrift: true,
validateSchema: false,
isolationLevel: 'READ_UNCOMMITTED',
query: 'select * from mytable',
format: 'query') ~> AzurePostgreSQLSource
Transformación de receptor
En la tabla siguiente se enumeran las propiedades compatibles con el receptor de Azure Database for PostgreSQL. Puede editar estas propiedades en la pestaña Opciones del receptor.
Nombre | Descripción | Obligatorio | Valores permitidos | Propiedad de script de flujo de datos |
---|---|---|---|---|
Método de actualización | Especifique qué operaciones se permiten en el destino de la base de datos. El valor predeterminado es permitir solamente las inserciones. Para actualizar, upsert o eliminar filas, se requiere una transformación de alteración de fila a fin de etiquetar filas para esas acciones. |
Sí | true o false |
deletable insertable updateable upsertable |
Columnas de clave | En el caso de las actualizaciones, upserts y eliminaciones, se deben establecer columnas de clave para determinar la fila que se va a modificar. El nombre de columna que elija como clave se usará como parte de las operaciones posteriores de actualización, upsert y eliminación. Por lo tanto, debe seleccionar una columna que exista en la asignación del receptor. |
No | Array | claves |
Omitir escritura de columnas de clave | Si no quiere escribir el valor en la columna de clave, seleccione "Skip writing key columns" (Omitir escritura de columnas de clave). | No | true o false |
skipKeyWrites |
Acción Table | determina si se deben volver a crear o quitar todas las filas de la tabla de destino antes de escribir. - Ninguno: no se realizará ninguna acción en la tabla. - Volver a crear: se quitará la tabla y se volverá a crear. Obligatorio si se crea una nueva tabla dinámicamente. - Truncar: se quitarán todas las filas de la tabla de destino. |
No | true o false |
recreate truncate |
Tamaño de lote | Especifique el número de filas que se escriben en cada lote. Los tamaños de lote más grandes mejoran la compresión y la optimización de memoria, pero se arriesgan a obtener excepciones de memoria al almacenar datos en caché. | No | Entero | batchSize |
Selección del esquema de base de datos de usuario | De forma predeterminada, se creará una tabla temporal en el esquema receptor como almacenamiento provisional. También puede desactivar la opción Usar esquema receptor y, en su lugar, especificar un nombre de esquema con el que Data Factory creará una tabla de almacenamiento provisional para cargar datos ascendentes y limpiarlos automáticamente al finalizar. Asegúrese de que tiene permiso para crear tablas en la base de datos y modificar permisos en el esquema. | No | String | stagingSchemaName |
Scripts SQL anteriores y posteriores | Especifique scripts de SQL de varias líneas que se ejecutarán antes (preprocesamiento) y después (procesamiento posterior) de que los datos se escriban en la base de datos del receptor. | No | String | preSQLs postSQLs |
Sugerencia
- Se recomienda dividir los scripts por lotes únicos con varios comandos en varios lotes.
- Tan solo las instrucciones de lenguaje de definición de datos (DDL) y lenguaje de manipulación de datos (DML) que devuelven un recuento de actualizaciones sencillo se pueden ejecutar como parte de un lote. Obtenga más información en Realización de operaciones por lotes
Habilitar extracción incremental: use esta opción para indicar a ADF que procese solo las filas que hayan cambiado desde la última vez que se ejecutó la canalización.
Columna incremental: si se usa la característica de extracción incremental, es preciso elegir la columna numérica o de fecha y hora que desea se usar como marca de agua en la tabla de origen.
Empezar a leer desde el principio: si se establece esta opción con extracción incremental, se indicará a ADF que lea todas las filas en la primera ejecución de una canalización con la extracción incremental activada.
Ejemplo de script de receptor de Azure Database for PostgreSQL
Cuando se usa Azure Database for PostgreSQL como tipo de receptor, el script de flujo de datos asociado es:
IncomingStream sink(allowSchemaDrift: true,
validateSchema: false,
deletable:false,
insertable:true,
updateable:true,
upsertable:true,
keys:['keyColumn'],
format: 'table',
skipDuplicateMapInputs: true,
skipDuplicateMapOutputs: true) ~> AzurePostgreSQLSink
Propiedades de la actividad de búsqueda
Para más información sobre las propiedades, consulte Actividad de búsqueda.
Contenido relacionado
Para obtener una lista de almacenes de datos que la actividad de copia admite como orígenes y receptores, vea Almacenes de datos que se admiten.