Guia do MapDB
1. Introdução
Neste artigo, veremos oMapDB library — an embedded database engine accessed through a collection-like API.
Começamos explorando as classes principaisDB andDBMaker que ajudam a configurar, abrir e gerenciar nossos bancos de dados. Então, vamos mergulhar em alguns exemplos de estruturas de dados MapDB que armazenam e recuperam dados.
Finalmente, veremos alguns dos modos na memória antes de comparar o MapDB com bancos de dados tradicionais e coleções Java.
2. Storing Data in MapDB
Primeiro, vamos apresentar as duas classes que usaremos constantemente ao longo deste tutorial -DB andDBMaker. The DB class represents an open database. Seus métodos invocam ações para criar e fechar coleções de armazenamento para lidar com registros de banco de dados, também como tratamento de eventos transacionais.
DBMaker handles database configuration, creation, and opening. Como parte da configuração, podemos escolher hospedar nosso banco de dados na memória ou em nosso sistema de arquivos.
2.1. Um exemplo simples deHashMap
Para entender como isso funciona, vamos instanciar um novo banco de dados na memória.
Primeiro, vamos criar um novo banco de dados na memória usando o sclassDBMaker :
DB db = DBMaker.memoryDB().make();
Assim que nossoDB object estiver funcionando, podemos usá-lo para construir umHTreeMap to trabalho com nossos registros de banco de dados:
String welcomeMessageKey = "Welcome Message";
String welcomeMessageString = "Hello example!";
HTreeMap myMap = db.hashMap("myMap").createOrOpen();
myMap.put(welcomeMessageKey, welcomeMessageString);
HTreeMap is simplificação deHashMap do MapDB. Portanto, agora que temos dados em nosso banco de dados, podemos recuperá-los usando o métodoget :
String welcomeMessageFromDB = (String) myMap.get(welcomeMessageKey);
assertEquals(welcomeMessageString, welcomeMessageFromDB);
Finalmente, agora que terminamos com o banco de dados, devemos fechá-lo para evitar mais mutações:
db.close();
Para armazenar nossos dados em um arquivo, em vez de na memória, tudo o que precisamos fazer é alterar a maneira como nosso objetoDB é instanciado:
DB db = DBMaker.fileDB("file.db").make();
Nosso exemplo acima não usa parâmetros de tipo. Como resultado, estamos presos em lançar nossos resultados para trabalhar com tipos específicos. Em nosso próximo exemplo, apresentaremosSerializers para eliminar a necessidade de fundição.
2.2. Colecções
MapDB includes different collection types. Para demonstrar, vamos adicionar e recuperar alguns dados de nosso banco de dados usando umNavigableSet, que funciona como você pode esperar de um JavaSet:
Vamos começar com uma instanciação simples de nossoDB objeto:
DB db = DBMaker.memoryDB().make();
A seguir, vamos criar nossoNavigableSet:
NavigableSet set = db
.treeSet("mySet")
.serializer(Serializer.STRING)
.createOrOpen();
Aqui, oserializer garante que os dados de entrada de nosso banco de dados sejam serializados e desserializados usando objetosString.
A seguir, vamos adicionar alguns dados:
set.add("example");
set.add("is awesome");
Agora, vamos verificar se nossos dois valores distintos foram adicionados ao banco de dados corretamente:
assertEquals(2, set.size());
Finalmente, como este é um conjunto, vamos adicionar uma string duplicada e verificar se nosso banco de dados ainda contém apenas dois valores:
set.add("example");
assertEquals(2, set.size());
2.3. Transações
Muito parecido com bancos de dados tradicionais, oDB class provides methods to commit and rollback the data we add to our database.
Para habilitar essa funcionalidade, precisamos inicializar nossoDB com o métodotransactionEnable :
DB db = DBMaker.memoryDB().transactionEnable().make();
A seguir, vamos criar um conjunto simples, adicionar alguns dados e confirmá-lo no banco de dados:
NavigableSet set = db
.treeSet("mySet")
.serializer(Serializer.STRING)
.createOrOpen();
set.add("One");
set.add("Two");
db.commit();
assertEquals(2, set.size());
Agora, vamos adicionar uma terceira string não confirmada ao nosso banco de dados:
set.add("Three");
assertEquals(3, set.size());
Se não estivermos satisfeitos com nossos dados, podemos reverter os dados usando o métodoDB’s rollback:
db.rollback();
assertEquals(2, set.size());
2.4. Serializadores
MapDB oferece uma grande variedade deserializers, which handle the data within the collection. O parâmetro de construção mais importante é o nome, que identifica a coleção individual dentro do sobjetoDB :
HTreeMap map = db.hashMap("indentification_name")
.keySerializer(Serializer.STRING)
.valueSerializer(Serializer.LONG)
.create();
Embora a serialização seja recomendada, ela é opcional e pode ser ignorada. No entanto, é importante notar que isso levará a um processo de serialização genérico mais lento.
3. HTreeMap
HTreeMap provides HashMap and HashSet collections for working with our database.HTreeMap do MapDB é uma árvore hash segmentada e não usa uma tabela hash de tamanho fixo. Em vez disso, ele usa uma árvore de índice de expansão automática e não refaz todos os dados à medida que a tabela cresce. Para completar,HTreeMap is thread-safe and supports parallel writes using multiple segments.
Para começar, vamos instanciar umHashMap t simples que usaString para chaves e valores:
DB db = DBMaker.memoryDB().make();
HTreeMap hTreeMap = db
.hashMap("myTreeMap")
.keySerializer(Serializer.STRING)
.valueSerializer(Serializer.STRING)
.create();
Acima, definimosserializers separados para a chave e o valor. Agora que nossoHashMap foi criado, vamos adicionar dados usando o métodoput :
hTreeMap.put("key1", "value1");
hTreeMap.put("key2", "value2");
assertEquals(2, hTreeMap.size());
ConformeHashMap muda em um métodoObject’s hashCode , adicionar dados usando a mesma chave faz com que o valor seja sobrescrito:
hTreeMap.put("key1", "value3");
assertEquals(2, hTreeMap.size());
assertEquals("value3", hTreeMap.get("key1"));
4. SortedTableMap
SortedTableMap stores keys in a fixed-size table and uses binary search for retrieval.It’s worth noting that once prepared, the map is read-only. do MapDB
Vamos percorrer o processo de criação e consulta de umSortedTableMap. . Começaremos criando um volume mapeado na memória para armazenar os dados, bem como um coletor para adicionar dados. Na primeira chamada de nosso volume, definiremos o sinalizador somente leitura comofalse, garantindo que possamos gravar no volume:
String VOLUME_LOCATION = "sortedTableMapVol.db";
Volume vol = MappedFileVol.FACTORY.makeVolume(VOLUME_LOCATION, false);
SortedTableMap.Sink sink =
SortedTableMap.create(
vol,
Serializer.INTEGER,
Serializer.STRING)
.createFromSink();
A seguir, adicionaremos nossos dados e chamaremos o métodocreate no coletor para criar nosso mapa:
for(int i = 0; i < 100; i++){
sink.put(i, "Value " + Integer.toString(i));
}
sink.create();
Agora que nosso mapa existe, podemos definir um volume somente leitura e abrir nosso mapa usando o métodoSortedTableMap’s open:
Volume openVol = MappedFileVol.FACTORY.makeVolume(VOLUME_LOCATION, true);
SortedTableMap sortedTableMap = SortedTableMap
.open(
openVol,
Serializer.INTEGER,
Serializer.STRING);
assertEquals(100, sortedTableMap.size());
4.1. Pesquisa binária
Antes de prosseguirmos, vamos entender como oSortedTableMap utiliza a pesquisa binária em mais detalhes.
SortedTableMap divide o armazenamento em páginas, com cada página contendo vários nós compostos de chaves e valores. Dentro desses nós, estão os pares de valores-chave que definimos em nosso código Java.
SortedTableMap executa três pesquisas binárias para recuperar o valor correto:
-
As chaves para cada página são armazenadas na pilha em uma matriz. OSortedTableMap executa uma pesquisa binária para encontrar a página correta.
-
Em seguida, ocorre a descompressão para cada chave no nó. Uma pesquisa binária estabelece o nó correto, de acordo com as chaves.
-
Finalmente, oSortedTableMap pesquisa as chaves dentro do nó para encontrar o valor correto.
5. Modo na memória
MapDB oferecethree types of in-memory store. Vamos dar uma olhada rápida em cada modo, entender como ele funciona e estudar seus benefícios.
5.1. On-Heap
O modo na pilhastores objects in a simple Java Collection Map. Itdoes not employ serialization and can be very fast for small datasets.
No entanto, como os dados são armazenados na pilha, o conjunto de dados é gerenciado pela coleta de lixo (GC). A duração do GC aumenta com o tamanho do conjunto de dados, resultando em quedas de desempenho.
Vejamos um exemplo especificando o modo em pilha:
DB db = DBMaker.heapDB().make();
5.2. Byte[]
O segundo tipo de armazenamento é baseado em matrizes de bytes. Nesse modo,data is serialized and stored into arrays up to 1MB in size. Embora tecnicamente no heap, esse método é mais eficiente para a coleta de lixo.
Isso é recomendado por padrão e foi usado em nosso ‘Hello example' example:
DB db = DBMaker.memoryDB().make();
5.3. DirectByteBuffer
O armazenamento final é baseado na memória diretaDirectByteBuffer., introduzida no Java 1.4, permite a passagem de dados diretamente para a memória nativa em vez do heap Java. Como resultado, os dados serão armazenadoscompletely off-heap.
Podemos invocar uma loja desse tipo com:
DB db = DBMaker.memoryDirectDB().make();
6. Porquê MapDB?
Então, por que usar o MapDB?
6.1. MapDB x banco de dados tradicional
O MapDB oferece uma grande variedade de funcionalidades de banco de dados configuradas com apenas algumas linhas de código Java. Quando empregamos o MapDB, podemos evitar a configuração que consome muito tempo de vários serviços e conexões necessários para que nosso programa funcione.
Além disso, o MapDB nos permite acessar a complexidade de um banco de dados com a familiaridade de um Java Collection. Com MapDB, não precisamos de SQL e podemos acessar registros com chamadas smethodget imples.
6.2. MapDB vs coleções Java simples
O Java Collections não persistirá os dados de nosso aplicativo depois que ele parar de ser executado. O MapDB oferece um serviço simples, flexível e conectável que permite persistir com rapidez e facilidade os dados em nosso aplicativo, mantendo o utilitário dos tipos de coleção Java.
7. Conclusão
Neste artigo, mergulhamos profundamente no mecanismo de banco de dados incorporado e na estrutura de coleta do MapDB.
Começamos olhando para as classes principaisDB andDBMaker para configurar, abrir e gerenciar nosso banco de dados. Em seguida, percorremos alguns exemplos de estruturas de dados que o MapDB oferece para trabalhar com nossos registros. Por fim, analisamos as vantagens do MapDB em relação a um banco de dados tradicional ou Java Collection.
Como sempre, o código de exemplo está disponívelover on GitHub.