17.9.10

Cassandra Data Model #2

ถัดจากตอนแรก Cassandra Data Model #1 มาว่ากันต่อเรื่อง Data model

ColumnFamilies
เราสามารถจัดกลุ่มของ Column ได้ผ่าน ColumnFamily เพื่อให้มองภาพง่ายขึ้นตัวโดยโครงสร้างข้อมูลของ ColumnFamily จะเหมือนกับ table (ใช่แล้วผมหมายถึง table ใน RDBMS หนะแหละครับ) ซึ่งแต่ละ table ก็จะประกอบด้วยกี่ Row ก็ได้ และแต่ละ Row ก็จะเก็บ Column เท่าไหร่ก็ได้
ความยืดหยุ่นในโครงสร้างมันอยู่ตรงนี้ ให้สังเกตุว่าแต่ละ Row เราจะเก็บกี่ Column ก็ได้เท่ากับว่าเราไม่ต้องมีการกำหนดตายตัวว่าแต่ละ Row จะมีได้แค่เท่านั้นเท่านี้ Column จุดนี้เองจึงทำให้ Cassandra ได้คุณสมบัติ Schemaless
การเก็บข้อมูลของ Cassandra ตอนเก็บจะมีการเรียงลำดับข้อมูลทุกครั้งก่อนเก็บ ซึ่งการเรียงลำดับจะเรียงตาม key ของแต่ละ row
การสร้าง ColumnFamily เรากำหนดได้ในไฟล์ storage-conf.xml แต่ในกรณีที่เราต้องการเปลี่ยนแปลง (เพิ่ม, แก้ไข, ลบ) ColumnFamily จำเป็นที่จะต้อง Restart Cassandra process ก่อนนะครับ ถึงจะเห็นผล
ตัวอย่างการสร้าง ColumnFamily
<keyspaces>
<keyspace Name="Posts">  
<columnfamily CompareWith="UTF8Type" Name="Tags"></ColumnFamily>  
<columnfamily CompareWith="BytesType" Name="Authors"></ColumnFamily> 
</Keyspace>
</Keyspaces>
เราสร้าง ColumnFamily ชื่อ Tags, Authors และกำหนดชนิดข้อมูลที่ใช้เป็น UTF8Type, ByteType ตามลำดับ

ตัวอย่างโครงสร้างข้อมูลถ้ามองภาพในโลก Java
public class ColumnFamily{
 Byte[] name;
 Map value;
}
ColumnFamily cf = new ColumnFamily();
cf.name = "AddressBook";
Map row = new HashMap();
row.put("firstname", new Column("firstname", "Maomao"));
row.put("familyname", new Column("familyname", "Mathies"));
row.put("city", new Column("city", "Leiden"));
cf.put("person1", row);

Map row = new HashMap();
row.put("firstname", new Column("firstname", "Maomao"));
row.put("familyname", new Column("familyname", "Chen"));
row.put("city", new Column("city", "Leiden"));
cf.put("person2", row);
ตัวอย่างถ้ามองภาพในโลก JSON
UserProfile = {
 name: “phamonyut”, 
 value: {
  username: {name: “username”, value: “tofu”, timestamp: 123456789},
  blog: {name: “blog”, value: “http://phamonyut.blogspot.com”, timestamp: 123456789},
  gender: {name: “gender ”, value: “male”, timestamp: 123456789}
 },
 name: “plaumkamon”,
 value: {
  username: {name: “username”, value: “plaumkamon”, timestamp: 123456789},
  blog: {name: “blog”, value: “http://plaumkamon.blogspot.com”, timestamp: 123456789},
  gender: {name: “gender ”, value: “undecided”, timestamp: 123456789},
  age: {name: “age”, value: “25”, timestamp: 123456789},
  email: {name: “email”, value: “plaumkamon@example.com”, timestamp: 123456789}
 }
}
ด้วยความที่มัน Schemaless ค่าที่เก็บในแต่ละ row จึงแตกต่างกันได้ สังเกตุว่า row ที่สองจะมีเพิ่ม Column age และ name

Keyspace
ข้ามมาพูดถึง Keyspace ก่อนเข้าไปที่ SuperColumnFamily ตัว Keyspace เพื่อให้มองภาพง่ายขึ้นเปรียบได้กับ Database ใน RDBMS ซึ่งเป็น “มิติ” แรกของ Cassandra hash ที่เราใช้เวลาดึงข้อมูล (คำว่ามิติแรก ก็จะเทียบได้กับ syntax get[keyspace][columnFamily][...]) โดยภายในจะประกอบด้วย ColumnFamily (ซึ่งเปรียบได้กับ Table ใน RDBMS) ก็เท่ากับเรามีทั้ง Database และ table ที่ใช้เก็บข้อมูลแล้ว ซึ่งแต่ละ application ก็จะมีแค่หนึ่ง keyspace
แต่อย่างลืมว่า ColumnFamily ไม่ใช่ table จริงๆ และมันไม่มี Join จึงอย่าคาดหวังว่า key ของ row นึงจะต้องมีอยู่ในอีก ColumnFamily นึงด้วย
เราจะ config Keyspace ในไฟล์ storage-conf.xml
<keyspaces>
<keyspace name="Blogs"> 
... 
</Keyspace>
</Keyspaces>
SuperColumnFamily
โครงสร้างจะเหมือนกับ ColumnFamily แตกต่างตรงที่ ในแต่ละ row จะเก็บ SuperColumn ตัว map คือ key ที่เป็น name ของแต่ละ SuperColumn และ value คือตัว SuperColumn มัีนเอง
ตัวอย่างในมุมมองของ JSON
Posts= {
 name: "Cassandra-data-model", 
 value: {
 name: "Post"
 value: {
  "title": {name: "title", value: "Cassandra data model", timestamp: 123456789},
  "body": {name: "body", value: "Blah Blah ...", timestamp: 123456789},
  "author": {name: "author", value: "Phamonyut", timestamp: 123456789},
 }, 
 name: "Tag"
 value {
  "0": {name: "0", value: "cassandra", timestamp: 123456789},
  "1": {name: "1", value: "nosql", timestamp: 123456789},
 }
 }, 
 name: "Android-programming",
 value: {
 name: "Post"
 value: {
  "title": {name: "title", value: "Android Programming", timestamp: 123456789},
  "body": {name: "body", value: "Blah Blah ...", timestamp: 123456789},
  "author": {name: "author", value: "Plaumkamon", timestamp: 123456789},
  "createdate": {name: "createdate", value: "07/07/2007", timestamp: 123456789}
 }, 
 name: "Tag"
 value {
  "0": {name: "0", value: "Android", timestamp: 123456789},
  "1": {name: "1", value: "Tutorial", timestamp: 123456789},
 }
 }
}

No comments:

Post a Comment