Administración de índices en Amazon DocumentDB con Java - Amazon DocumentDB

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Administración de índices en Amazon DocumentDB con Java

Los índices permiten una recuperación eficaz de los datos de una colección de Amazon DocumentDB. Sin índices, DocumentDB debe digitalizar todos los documentos de la colección para obtener resultados que satisfagan una consulta determinada. En este tema se proporciona información sobre cómo crear, eliminar y enumerar índices mediante los controladores Java de MongoDB. También se explica cómo determinar si se está utilizando un índice específico en la consulta y cómo hacer sugerencias a Amazon DocumentDB para que utilice un índice específico.

Amazon DocumentDB admite muchos tipos de índices. Para obtener una descripción general integral de todos los índices compatibles, consulte esta entrada del blog.

Creación de índices con Java

Existen dos mecanismos para crear índices en Amazon DocumentDB con controladores Java de MongoDB: mediante runCommand(), y mediante el método createIndex() para un índice único o el método createIndexes() para varios índices. Uno de los motivos para utilizar los métodos createIndex() y createIndexes() es que permiten gestionar mejor los errores, ya que detecta errores específicos relacionados con la creación de índices. Otra razón para usar estos métodos en lugar de runCommand() es que el controlador Java de MongDB proporciona un amplio conjunto de clases admitidas para la creación y manipulación de índices. Tenga en cuenta que estas clases admitidas pueden utilizarse solamente cuando use los métodos createIndex() o createIndexes(). Hay tres clases admitidas:

  • Indexes: esta clase sirve como clase de utilidad y ofrece métodos de fábrica estáticos para crear varios tipos de índices. Simplifica el proceso de creación de definiciones de índices complejas y se suele usar junto con otras clases relacionadas con los índices.

  • IndexModel: se trata de una clase fundamental que condensa tanto la definición de las claves de índice como sus opciones. Representa una especificación de índice completa, que combina qué indexar (las claves) con cómo indexar (las opciones). Esta clase es particularmente útil cuando se crean varios índices simultáneamente, ya que permite definir un conjunto de especificaciones de índices que se pueden pasar al método createIndexes().

  • IndexOptions: se trata de una clase de configuración completa que proporciona un amplio conjunto de métodos para personalizar el comportamiento de los índices. Incluye ajustes para índices únicos, índices dispersos, tiempo de caducidad (TTL) y expresiones de filtrado parcial. Mediante el encadenamiento de métodos, puede configurar varias opciones, como la creación de índices en segundo plano y las restricciones únicas.

Creación de un índice único

En este ejemplo se muestra cómo crear un índice único con el método createIndex() en segundo plano. Para entender la creación de índices en segundo plano y en primer plano, consulte Tipos de creación de índices. El siguiente ejemplo de código usa IndexOptions para crear un índice único con el nombre «unique_restaurantId_idx» en segundo plano. A continuación, este objeto IndexOptions se pasa al método createIndex().

collection.createIndex( Indexes.ascending("restaurantId"), new IndexOptions() .unique(true) .name("unique_restaurantId_idx") .background(true));

Creación de índices múltiples

En este ejemplo, se crean índices múltiples mediante el método createIndexes(). Primero crea la opción para cada índice mediante el objeto de IndexModel y, a continuación, pasa una lista de objetos de IndexModel al método createIndexes(). En el siguiente ejemplo de código se muestra cómo crear un índice compuesto mediante la clase de utilidad Indexes. Esta clase también se usa para especificar si desea crear un índice con un orden de clasificación ascendente o descendente. Tras crear índices múltiples, llama al método listIndexes() para verificar la creación del índice.

// Single Field Index on cuisine IndexModel singleIndex = new IndexModel( Indexes.ascending("cuisine"), new IndexOptions().name("cuisine_idx")); // Compound Index IndexModel compoundIndex = new IndexModel( Indexes.compoundIndex( Indexes.ascending("address.state"), Indexes.ascending("priceRange")), new IndexOptions().name("location_price_idx")); // Build a list of IndexModel for the indexes List < IndexModel > indexes = Arrays.asList( singleIndex, compoundIndex ); collection.createIndexes(indexes); // Verify created indexes collection.listIndexes().forEach(index - > System.out.println("Created index: " + index.toJson()));

Creación de índices dispersos y parciales

En este ejemplo se muestra la creación de un índice disperso y uno parcial mediante la creación de un IndexModel para cada tipo de índice.

// Sparse Index Model, this will identify only those documents that have a // michelin star rating IndexModel sparseIndex = new IndexModel( Indexes.ascending("michelin.star"), new IndexOptions() .name("michelin_sparse_idx") .sparse(true)); // Partial Index Model where the restaurant is active and has a rating of 4 and above IndexModel partialIndex = new IndexModel( Indexes.ascending("rating.average"), new IndexOptions() .name("high_rated_active_idx") .partialFilterExpression( Filters.and( Filters.eq("isActive", true), Filters.gte("rating.average", 4.0))));

Creación de un índice de texto

En este ejemplo se muestra cómo crear un índice de texto. Solo se permite un índice de texto en una colección, pero ese índice de texto puede ser un índice compuesto que abarque campos múltiples. Cuando usa varios campos en el índice de texto, también puede asignar pesos a cada uno de los campos del índice. Amazon DocumentDB no admite los índices de texto en campos de matriz y, aunque puede utilizar hasta 30 campos en el índice de texto compuesto, solo se puede asignar un peso a tres campos.

IndexModel textIndex = new IndexModel( new Document() .append("name", "text") .append("description", "text") .append("cuisine", "text"), new IndexOptions() .name("restaurant_text_idx") .weights(new Document() .append("name", 10) // Restaurant name gets highest weight .append("description", 5) // Description get medium weight .append("cuisine", 2) // Cuisine type gets low weight )); collection.createIndex(textIndex.getKeys(), textIndex.getOptions());

Creación de un índice mediante el runCommand()

Amazon DocumentDB admite la creación de índices en paralelo para reducir el tiempo que se tarda en crear índices. La indexación paralela utiliza varios procesos de trabajo simultáneos. La cantidad predeterminada de procesos de trabajo que se utilizan para la creación de índices son dos. Esta entrada del blog ofrece una discusión en profundidad sobre la indexación en paralelo. Actualmente, los controladores Java de MongDB no permiten especificar la opción de proceso de trabajo cuando se utiliza createIndex() o createIndexes() y, por lo tanto, la única forma de especificar los procesos de trabajo es mediante el runCommand. El siguiente ejemplo de código muestra cómo usar runCommand para crear un índice que aumente el número de procesos de trabajo a cuatro:

Document command = new Document("createIndexes", "Restaurants") .append("indexes", Arrays.asList( new Document("key", new Document("name", 1)) .append("name", "restaurant_name_idx") .append("workers", 4) // Specify number of workers )); Document commendResult = connectedDB.runCommand(command);

Eliminar índices

El controlador Java de MongoDB proporciona varios métodos para eliminar índices, ya que se adapta a diferentes situaciones y a sus preferencias. Puede eliminar los índices por nombre, por especificación de clave o eliminar todos los índices a la vez. Los métodos dropIndex() y dropIndexes() pueden invocarse en un objeto de colección para eliminar un índice. Cuando elimina un índice por nombre, debe asegurarse de que se use el nombre de índice correcto, lo que puede no ser siempre intuitivo, especialmente para los índices compuestos o generados de forma automática. Si intenta eliminar un índice inexistente, se obtendrá una MongoCommandException. El índice default _id no se puede eliminar, ya que garantiza la exclusividad del documento dentro de la colección.

En el siguiente ejemplo de código se muestra cómo eliminar un índice con el nombre del campo donde se creó el índice o mediante la eliminación de todos los índices:

String indexName = "unique_restaurantId_idx"; Document keys = new Document("cuisine", 1); // Drop index by name collection.dropIndex(indexName); // Drop index by keys collection.dropIndex(keys); // Drop all indexes collection.dropIndexes();

Cuando borra índices con claves múltiples, asegúrese de que haya un índice compuesto que contenga todas las claves especificadas y de que el orden de las claves sea correcto. El código de ejemplo de creación del índice anterior muestra una clave compuesta sobre «cocina» y características. Si intenta eliminar esa clave compuesta pero el orden no es el que se utilizó para la creación, se produce MongoCommnadException el siguiente error:

Document keys = new Document("features", 1) .append("cuisine", 1); try { // Drop index by keys collection.dropIndex(keys); System.out.println("Successfully dropped index with keys: " + keys.toJson()); } catch (MongoCommandException commErr) { System.out.println("Error dropping index: " + commErr.getErrorMessage()); throw new RuntimeException("MongoCommandException was thrown while dropping index", commErr); }

Se muestra el siguiente error:

Error dropping index: Cannot drop index: index not found. Tests run: 3, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.819 sec <<< FAILURE! com.amazon.docdb.guide.DocDBGuideTest.testindexGuide() Time elapsed: 0.817 sec <<< FAILURE! org.opentest4j.AssertionFailedError: Unexpected exception thrown: java.lang.RuntimeException: MongoCommandException was thrown while dropping index

Determinación de la selección del índice y proporción de una sugerencia sobre el índice

Trabajar con la funcionalidad de explicación de Amazon DocumentDB es fundamental para comprender el rendimiento de las consultas y el uso de los índices. Cuando ejecuta una consulta, puede añadir el método explain() para obtener información detallada sobre el plan de consulta, incluidos los índices, si los hubiera, que se están utilizando. El resultado explain() proporciona información sobre las etapas de ejecución de la consulta, el número de documentos examinados y el tiempo necesario para cada etapa. Esta información es inestimable para identificar si un índice en particular se está utilizando de manera eficaz o si la consulta podría beneficiarse de una estructura de índice diferente.

El método explain() se puede encadenar con el método find(). El método explain() puede utilizar un enumerador opcional ExplainVerbosity que determine el nivel de verbosidad devuelto por explain(). En este momento, DocumentDB admite solamente los enumeradores EXECUTION_STATS y QUERY_PLANNER. En el siguiente ejemplo de código se muestra cómo obtener el planificador de consultas para una consulta específica:

// Query we want to analyze Document query = new Document() .append("cuisine", "Thai") .append("rating.average", new Document("$gte", 4.0)); Document allPlansExplain = collection.find(query).explain(ExplainVerbosity.QUERY_PLANNER); System.out.println("All Plans Explain:\n" + allPlansExplain.toJson());

Se devuelve el siguiente documento JSON para el nivel de verbosidad del planificador de consultas:

{ "queryPlanner": { "plannerVersion": 1, "namespace": "ProgGuideData.Restaurants", "winningPlan": { "stage": "IXSCAN", "indexName": "cuisine_idx", "direction": "forward" } }, "serverInfo": { "host": "guidecluster3", "port": 27017, "version": "5.0.0" }, "ok": 1, "operationTime": { "$timestamp": { "t": 1739221668, "i": 1 } } }

Dispone de varias opciones para incitar o forzar a Amazon DocumentDB a utilizar un índice específico. Los métodos hint() y hintString() le permiten anular el comportamiento de selección de índices predeterminado del optimizador de consultas y especificar explícitamente qué índice debe usarse para una consulta. Si bien el optimizador de consultas de DocumentDB suele ser una buena opción para la selección de índices, hay situaciones en las que forzar la aprobación de un índice específico mediante hint() o hintString() puede resultar beneficioso, como cuando se trata de datos sesgados o se comprueba el rendimiento de un índice.

El siguiente ejemplo de código fuerza el uso de un índice compuesto «cuisine_features_idx» para la misma consulta que se ejecutó en el código anterior:

// Query we want to analyze Document query = new Document() .append("cuisine", "Thai") .append("rating.average", new Document("$gte", 4.0)); List < Document > queryDocs = new ArrayList < > (); collection.find(query).hintString("cuisine_features_idx").forEach(doc - > queryDocs.add(doc));