quinta-feira, 25 de julho de 2013

     Tão importante quanto armazenar informações é consultá-las em um banco de dados. No post CRUD Operations no MongoDB - Parte 1 vimos as principais operações de leitura. É possível reduzir este tempo de consulta? Como fazemos?

     A resposta está na criação dos índices. Eles melhoram a eficiência das operações de leitura através da redução da quantidade de dados processados, simplificando assim o trabalhado realizado pelo banco no momento da consulta. Os próprios índices são uma estrutura de dados especial que MongoDB mantém ao inserir ou modificar documentos, e qualquer índice pode: apoiar e otimizar as consultas específicas e permitir a utilização do armazenamento mais eficiente.

     Para criar índices, temos a seguinte sintaxe:

db.collection.ensureIndex ({<campo1>: <order>, <campo2>: <order>, ...})

onde order é configurado como 1 para ascendente e -1 para descendente. O campo também pode ser um subdocumento com dot notation.

     Mas, antes de criar nossos índices, como saber o tempo que minha consulta leva para ser executada? A resposta é utilizar o comando explain()

db.collection.find(<query>).explain()

     Em nosso dataset zips (download dataset), ao realizamos uma consulta pela cidade de New Orleans, por exemplo, temos a seguinte saída com o comando explain():


     Vemos que esta consulta levou 9 milissegundos (veja o campo "millis":9). Rápido? Individualmente sim, mas se você tiver uma base realmente grande (esta possui 29.467 documentos...não é grande) e realizar muitas consultas, estes milissegundos serão uma eternidade. E por que?
     Note que o terceiro campo da saída, "nscannedObjects", indica a quantidade de documentos que foram analisados para retornar esta busca. Se você tiver uma base com 10 milhões de documentos, seu tempo de resposta, sem índices, será proibitivo. Neste exemplo, foram analisados 29.467 documentos para nos retornar 17 que contém a cidade New Orleans (campo "n":17)

     Para resolver este problema, vamos criar um índice para o campo "city", que é o objeto de nossa consulta.

db.zips.ensureIndex({city:1})

     Executando novamente a mesma query temos como saída:


     Veja que agora nosso tempo de resposta foram incríveis 0 milissegundos com apenas 17 documentos analisados.

     Mas todo este incremento na performance tem um preço: os índices são armazenados na memória RAM da máquina. Desta forma, é preciso cuidado ao criar índices, para que estes não superem o seu limite de memória, comprometendo a integridade de seu sistema de dados.

Até o próximo post!



0 comentários:

Postar um comentário