2014-06-25

MSSQL: псевдопартиционирование

Допустим, у нас есть (а у нас есть) таблица огромных размеров, с огромными индексами и вообще всё у неё огромное. Скажем, это записи из твиттера. Из этой таблицы часто делаются выборки по полю DATETIME. И, хотя на этом поле есть индекс, и несомненно есть Primary Key (вобщем все как надо), доступ к данным осуществляется дольше, чем хотелось бы: для использования индекс загружается в оперативную память, а он, как вы помните, огромный.

Здравые размышления приводят к выводу - нужно табличку поделить, чтобы индексы стали поменьше и помещались в память без проблем. В тоже время шардить табличку не хочется, периодически она нужна целиком. Ну и расширяться пока возможностей нет.

Вариантом временного решения может стать VIEW. Мы разделим таблицу на несколько поменьше, которые будут содержать данные в некоторых заранее известных границах. Создадим VIEW, в котором укажем на эти пределы:

CREATE VIEW table AS
SELECT * FROM table1 WHERE created_at BETWEEN '2014-02-01 00:00:00.000' AND '2014-03-01 00:00:00.000'
UNION ALL
SELECT * FROM table2 WHERE created_at BETWEEN '2014-03-01 00:00:00.000' AND '2014-04-01 00:00:00.000'

Фокус в том, что если запросить данные с указанием условия, присутствующего во VIEW, таблица, не удовлетворяющая этому условию затронута не будет вовсе. Например:

SELECT * FROM table WHERE created_at > '2014-03-01 00:00:00.000'

заденет только вторую таблицу, соответственно поднимет только ее индекс. Как-то так.

2014-06-20

MongoDB: шардинг по быстрому

Шардинг, как известно, позволяет раскидать данные по нескольким серверам БД, распределяя их согласно некоторым условиям. В MongoDB это бесплатно, так сказать all inclusive, к тому же невероятно просто.

Запустим несколько шардов, например на разных портах (или серверах, если есть). Я это делаю в нескольких терминалах, чтобы видеть, что происходит. Но можно добавить ключ --fork для отвязки от терминала.

$ mongod --dbpath db1 --port 27001 --shardsvr
$ mongod --dbpath db2 --port 27002 --shardsvr
$ mongod --dbpath db3 --port 27003 --shardsvr

Запустим шард-сервер и назначим ему один из шардов (на порту 27001) в помощь - там он будет хранить информацию о том, куда что записал:

$ mongos --configdb 127.0.0.1:27001

Цепляемся к шард-серверу, подключаем шарды, указываем что шардить и по какому ключу:

$ mongo
> use admin
> db.runCommand({addshard: "127.0.0.1:27002"})
> db.runCommand({addshard: "127.0.0.1:27003"})
> db.runCommand({enablesharding: "social"})
> db.runCommand({shardcollection: "social.tweets", key: {id:1}})

MongoDB: репликация по быстрому

Вдохновленный этой краткой заметкой решил сделать себе мемо в блоге, дополнив некоторыми замечаниями. Итак, репликация в несколько строк:
Создаем каталоги для данных:

mkdir -p db1 db2 db3

В терминалах запустим несколько реплик в одном наборе "myset", на своих портах и со своими каталогами для данных:

$ mongod --port 27001 --dbpath db1 --replSet myset
$ mongod --port 27002 --dbpath db2 --replSet myset
$ mongod --port 27003 --dbpath db3 --replSet myset

Подключаемся к одной из реплик, делаем ее "мастером", подключаем к ней остальные реплики и проверяем:

$ mongo --port 27001
> rs.initiate()
> rs.add("myhost:27002")
> rs.add("myhost:27003")
> use test
> db.test.insert({id:1})
> db.test.find()

где "myhost" - имя хоста, которое можно увидеть в выводе команды rs.status()

Примечательно и прекрасно, что реплики могут находиться на разных машинах, увеличивая бутылочное горлышко I/O. В своих экспериментах я размещал реплики на PC с Windows 7 на борту, на Macbook и на Ubuntu в VirtualBox.

Важно, чтобы машина с репликой могла однозначно интерпретировать хост "мастера" в IP. На макбуке мне для этого пришлось добавить запись в /etc/hosts:

myhost 192.168.10.130