300 likes | 462 Views
Сергей Туленцев 42 bytes twitter.com / stulentsev. Что это за зверь? . база данных NoSQL документо-ориентированная производительная масштабирующаяся. Гибкая схема. В базу можно положить любой JSON db.presentations.insert ({ title : “ Доклад ”, author : { name : “ Сергей ”,
E N D
Сергей Туленцев 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});
Raw data • { • username : “Ivan”, • likes : 3, • text : “Preved world” • }
Map • varmapper = 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}}
Кластер config servers client mongod mongod mongos mongod replica set 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 объектов • Разделяются по медианному ключу • Хранят диапазон значений
Балансировка • В фоновом режиме • Данные не блокируются • Чтения – консистентны
Например, • Статистика • Rich key/value store • Прототипирование • Динамические данные (опросы, CMS)
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 • sergei.tulentsev@gmail.com • twitter.com/stulentsev