Вы находитесь на странице: 1из 79

Please Participate!

MongoDB's Goal:
be the best database for (most)
web apps
...not the best DB for everything.
What do Web Apps Want?
 Performance
 Scalability
 Availability
What do developers want?
 Easier development,
 Less server maintenance (at 3am)
 Great support
Goals
 Easy-to-use
 Fast
 Always available
 Easy to scale
Installing a New Database
1. Download the archive from
http://www.mongodb.org
2. Make a directory for database files
3. bin/mongod --dbpath ~/dbdir
4. sudo pecl install mongo
Connecting
$connection = new Mongo();
Database
$connection = new Mongo();
$db = $connection->foo;
Collection
$connection = new Mongo();
$db = $connection->foo;
$collection = $db->bar;

...I'll be using $c, not $collection, for collections in


code examples because it's shorter.
Documents
class Post {
public $comments = array();
public function __construct($author, $title, $content) {
$this->author = $author;
$this->title = $title;
$this->content = $content;
}
}

$post = new Post("Fred", "My first blog post", "Hello!");


$c->insert($post);
Documents
$c->insert(array('name' => "Joe", 'age' => 34));

var_dump($c->findOne(array('name' => "Joe")));


array(3) {
["_id"]=>
object(MongoId)#6 (0) {
}
["name"]=>
string(3) "Joe",
["age"]=>
int(34)
}
MongoId
Q: How do we make a unique ID quickly that is guaranteed to
be unique across multiple servers?

A:
echo $x['_id'];
2fe3e4d892aa73234c910bed
|------||----||--||----|
ts mac pid inc

Built-in document creation timestamp: $x['_id']->getTimestamp()


Getting an Encounter
In SQL:
SELECT * FROM encounters LIMIT 1

In Mongo:
$db->encounters->findOne()
Getting a Bunch of Encounters
$cursor = $db->encounters->find();

foreach($cursor as $id => $encounter) {


// do stuff
}
Pagination
$cursor = $db->encounters->find()
->limit($numPerPage)
->skip($pageNum)
->sort(array("difficulty" => 1));

$total = $cursor->count();
Kingdom of Loathing
{
"description" : "You munch the sausage.
Sausage muncher.",
"type" : "food",
"effect" : {
"adventures" : [3, 10]
}
}
Kingdom of Loathing
{
"title" : "Ninja Snowman Weaponmaster",
"type" : "fight",
"stats" : {
"hit points" : [200, 230],
"offense" : [20, 30]
}
"attacks" : [
{"desc" : "He strangles you mercilessly with a length of
chain...", damage : [30, 40]},
{"desc" : "He backflips over your head clocking you
with...", damage : [40, 50]}
]
"areas" : ["Mt. McLargeHuge"]
}
Kingdom of Loathing - User

{
"username" : "kristina",
"level" : 9,
}
I acquire a pet
$db->users->update(
array('username' => 'kristina'),
array('$set' => array('pet' => array(
'name' => 'Trot',
'species' => 'Mosquito',
'weight' => 20))));
Kingdom of Loathing
{
"username" : "kristina",
"level" : 9,
"pet" : {
"name" : "Trot",
"species" : "Mosquito",
"weight" : 20
}
}
Kingdom of Loathing
$users->find(array("pet.weight" => 20));

$users->find(array("pet.weight" =>
array('$gt' => 20));

$users->find(array("pet.weight" =>
array('$gte' => 20));

$users->find(array("pet.weight" =>
array('$ne' => 20));
Updates
In SQL:
UPDATE foo SET bar="baz" WHERE bar="bat"

In Mongo:
$db->foo->update(
array("bar" => "bat"),
array('$set' =>
array("bar" => "baz")));
Analytics
{
"url" : "www.example.com",
"pageviews" : 0
}
Analytics - Increment Pageviews
$page = $analytics->findOne(array(
"url" => "www.example.com"));

if ($page != NULL) {
$page['pageviews']++;
$analytics->save($page);
}
else {
$analytics->insert(array(
"url" => "www.example.com",
"pageviews" => 1));
}
...that's 1 round trip + 1 update or insert.
Analytics - Upsert

$analytics->update(
array("url" => "www.example.com"),
array('$inc' => array("pageviews" => 1)),
array("upsert" => true));

...all in one update!


Performance
"Any operation that takes longer than 0 milliseconds is
suspect."
- Mongo user on IRC
Performance
100,000 inserts (with indexes for MongoDB and MySQL)

Database Average Insert


MongoDB 0.00011
MySQL 0.00083
CouchDB 0.00640
Memcached 0.00279
Performance

Database Average Query (Indexed)


MongoDB 0.00035
MySQL 0.00772
CouchDB 0.01640
Memcached 0.00015
Indexes
$c->ensureIndex(array("x" => 1));

$c->ensureIndex(array("x" => 1),


array("unique" => true));

$c->ensureIndex(
array("x" => 1, "y" => -1));
Indexes
array("foo" =>
array("bar" =>
array("baz" => 1)
)
);

$c->ensureIndex(
array("foo.bar.baz" => 1));
Goals
 Easy-to-use
 Fast
 Always available
 Easy to scale
Master-Slave
master

slave slave slave


Replica Pairs
master

slave
Replica Pairs

slave
Replica Pairs

master
Replica Pairs
slave

master
Goals
 Easy-to-use
 Fast
 Always available
 Easy to scale
Scaling with Auto-Sharding
April - July 2009

January - March 2009 August - December 2009


Comments from Bob?
Those are stored here.
Server #3, you're
getting overloaded.

Configuration
Server #3, lockdown.
Split the data,
migrate half to the
new shard.

Router, server #3 has


A-M, server #5 has N-Z.
Shards
Shard

Configuration

Routers
"Yeah, the RDBMS went down
at 2am. There wasn't any need
to wake the DBA. She can fix it
later today."

- Steve Yen, "NoSQL is a Horseless Carriage"


Sacrifices
 Durability through transactions
 Consistency
A Transaction

Insert this.

Okay, got it.

Phew, my data's safe.


A Transaction
A Transaction
Get Paranoid

Insert this.

Okay, got it.

Phew, my data's safe.


Get Paranoid
Get Paranoid

? I have no idea what


you're talking about.
Get Real Paranoid
Write this to disk

I know better than


he does, I'll just
let this sit in a
buffer for a while.
All over it!
Trust No One!

...trust a bunch of ones. Mostly.


Consistency

Hey Twitter, I'm eating


a donut.

Okay
Fred
Consistency

Hey Twitter, I'm eating


a donut.

x 1,000,000

Fred

Fail Whale
Consistency

Hey Twitter, I'm eating


a donut.

Okay
Fred
Consistency

Hey Twitter, I'm eating Nothing new


a donut. from Fred

Okay
Fred

Bob
Consistency

Hey Twitter, I'm eating


a donut.

One sec
Fred
Consistency
Wait a sec, Bob

Bob
Consistency

I'd rather have Twitter up and know


what Fred is doing later.

Bob

...eventual consistency works for your customers


Consistency

I MUST KNOW WHAT FRED IS


DOING RIGHT THIS SECOND!

Bob

...you need "real" consistency


Other Neat Stuff
Logging & Capped Collections
4 GB, 50 MB, 97 documents, etc.
Storing Files - GridFS
Max: 4 MB
Storing Files - GridFS

(More than 4 MB)


Storing Files - GridFS

J J J

chunks
J J J

J J J
_id : J files
Storing Files - GridFS
$grid = $db->getGridFS();

$grid->insert($filename,
array("permissions" => 644,
"comment" => "vacation pics");

But wait, there's more!


Also includes MD5 hash and upload date.
Storing Files - GridFS
$file = $grid->findOne($query);

$file->write($filename);

or

echo $file->getBytes();
Mongo Knows JavaScript
$ ./mongo
MongoDB shell version: 1.3.2-
url: test
connecting to: test
type "help" for help
> x = 123+1
124
> db.foo.insert({name : "Fred"})
>
$where
$c->findOne(array('$where' =>
'this.y == (this.x + this.z)'));

Will work:
array("x" => 1, "y" => 4, "z" => 3)
array("x" => "hi", "y" => "hibye", "z" => "bye")

Won’t work:
array("x" => 1, "y" => 1)
JavaScript Functions
$db->execute("function() { return 'hello'; }")

hello

$func = <<<JSFUNC
function(x) {
return "hello "+ x + "!";
}
JSFUNC;

$db->execute($func, array("joe"))

hello, joe!
"Stored Procedures"
$db->system->js->insert(array(
"_id" => "x",
"value" => 3));

$db->system->js->insert(array(
"_id" => "y",
"value" => 4));

$db->execute("return x+y");
Wrap Up: PHP Frameworks
 CakePHP
 Drupal
 Kohana
 Lithium
 Symfony

Zend Framework proposal


PHPMoAdmin
Mongo Console
Thank You!
kristina@mongodb.org
@mongodb, @kchodorow

irc.freenode.net#mongodb

www.mongodb.org

Вам также может понравиться