Сергей Туленцев 42bytes twitter.com/stulentsev Что это за зверь? база данных NoSQL документо-ориентированная производительная масштабирующаяся Гибкая схема В базу можно положить любой JSON db.presentations.insert({ title : “Доклад”, author : { name : “Сергей”, last_name : “Туленцев”}, date : new Date() }); Нет джойнов Потому что они вредные и не нужны. db.users.insert({ name : “Ivan Petrov”, address : { country : “Russia”, city : “Moscow”}, interests : [“women”, “hunting”] }); Нет транзакций Штука хорошая Но страшно мешает масштабируемости Есть атомарные апдейты db.users.update({ _id : 1}, { $set : { status : ‘banned’ }}); Есть индексы db.foo.ensureIndex({ a : 1 }); db.foo.ensureIndex({ a : 1, b : -1}); db.foo.ensureIndex({c : 1}, {unique : true}); db.foo.ensureIndex({ d : 1}, {background : true}); db.foo.ensureIndex({e : 1}, {sparse : true}); Map/Reduce Raw data { username : “Ivan”, likes : 3, text : “Preved world” } Map var mapper = function () { emit( this.username, { count : 1, likes : this.likes}) } Reduce var reducer = function(key, values) { var result = {count : 0, likes : 0}; values.forEach(function(value) { result.count += value.count; result.likes += value.likes; }); return result; } Execute db.runCommand({mapreduce : “comments”, map : mapper, reduce : reducer, out : “mr_result” }); PROFIT! db.mr_result.find(); {_id : 1, value : {likes : 20, count : 3}} {_id : 40, value : {likes : 0, count : 100}} {_id : 55, value : {likes : 100500, count : 1}} Server-side JavaScript GridFS Масштабирование Кластер config servers client mongod mongod mongos replica set mongod mongod mongod mongod mongod mongod mongod Выбираем shard key Определяет распределение данных Очень трудно изменить Самое важное решение в плане производительности Примеры users {email : …, name : …} twitter {user_id : …, event_id : …, text : …} photos {photo_id : ???, photo_blob : …} Чанки Лимит – 64 Мб или 100,000 объектов Разделяются по медианному ключу Хранят диапазон значений key from key to shard min key M shard001 M max key shard002 Балансировка В фоновом режиме Данные не блокируются Чтения – консистентны Где использовать? Например, Статистика Rich key/value store Прототипирование Динамические данные (опросы, CMS) Tips & Tricks Initial data import Импорт может тормозить db.runCommand( { split : ‘test.foo’, middle : { _id : 1000} ); db.runCommand( {moveChunk : ‘test.foo’, find : { _id : 500 }, to : “shard001” }); Cached counters db.users.find() { _id : “123”, name : “Ivan”, friends : [1, 2, 3, …]} db.users.update({ _id : “123”, {$push : { friends : 55}, $inc : { friend_count : 1} }); Covered indexes db.users.ensureIndex( {email : 1, name : 1}); Random access vs right-balanced Надо держать весь индекс в RAM Random access vs right-balanced Нужно держать только небольшую часть Hot writes memory mapped files Документы должны быть в памяти Спасибо за внимание Сергей Туленцев 42bytes [email protected] twitter.com/stulentsev