go to http://oracle.in.th

Wednesday, June 30, 2010

Oracle Application Express 4.0 พร้อมดาวน์โหลดแล้ว!!!


สำหรับคนที่เล่นตัว Oracle Application Express หรือ APEX อยู่นั้น เห็นข่าวนี้คงจะดีใจนะครับ เพราะว่าทาง Oracle ได้ออกตัว Oracle Application Express Release 4.0 มาให้ดาวน์โหลดกันไปใช้แล้ว หลังจากที่เคยออกมาให้ทดลองเล่นกันในแบบ Oracle Application Express 4.0 Early Access ให้ติดใจกันก่อน แล้วค่อยปล่อยของจริงในวันนี้นี่เอง

สนใจดาวน์โหลดตัว Oracle Application Express 4.0 คลิก ที่นี่ เลยครับ
ถ้าได้ทดสอบกันแล้ว เป็นอย่างไร อย่าลืมมาแชร์ประสบการณ์กันนะครับ :)

อ้างอิง
ข้อเขียนนี้ช่วยฉัน:  

Saturday, June 26, 2010

JSF 2.0 Navigation Rules

ฟังคนเขียนพร่ามก่อนเริ่มเนื้อหากันหน่อยครับ ล่าสุดก็ให้เพือนที่เก่ง(กว่าผม) ช่วยตรวจ #jsftutorial ที่ผ่านมาหลายๆตอน ก็ได้มีการแก้ไขจุกจิก เพิ่มรายละเอียดเข้าไปนิดๆหน่อย เอาเป็นว่าถ้าใครอ่านแล้ว งง สงสัย ก็แจ้งกันไว้ทาง comment ได้เลยครับ หรือถ้าใครว่างก็ลองกลับไปไล่อ่านอันเก่าๆใหม่บ้างนะครับ เผือผมกลับไปเพิ่มอะไรไว้ได้ไม่พลาดไป ถือซะว่าเป็นการทบทวนกันไปในตัว เพราะอันนี้ก็เขียนกันแบบฉุกละหุก แต่ละบทความใช้เวลา เขียน รวมรวม ทำตัวอย่าง ที่ประมาณสามชั่วโมงเท่านั้น(ดูก็รู้ว่าคนเขียนไม่ตั้งใจสุดๆ 555+) จริงๆคือเนื้อหามันเยอะมากครับ กลัวเขียนไม่จบ สรุปว่าคงต้องให้คนอ่านช่วยครับ รบกวนลองทำตามกันแล้วถ้าใครสะดุดยังไง ติดตรงไหนก็ comment กันเข้ามาได้แก้ได้ แต่ตอนนี้เรามาดูกันต่อดีกว่าครับ

วันนี้คงจะพูดถึงเรื่อง Navigation Rules ครับ คืออะไร ก็เป็นเหมือนข้อกำหนดสำหรับไว้ทำเวลาที่เรา action กลับไปที่ backing bean แล่้วพอจบให้มัน return ไปที่หน้าไหนต่อนั่งเอง โดยใน JSF2.0 นั่นเรายังต้องไปสร้าง navigation rules ใน faces-config.xml เหมือนใน 1.x แต่เราจะมี default มาเลยด้วย

จริงๆแล้วเราเคยผ่านการใช้งาน Navigation ของ JSF ผ่านมาแล้วครับ ถ้านึกไม่ออกผมจะย้อนให้ดูกัน

helloform ----> helloManagedBean ----> hello จำกันได้ยังครับใน action hello ใน helloManagedBean นั่นเราได้มีการ return "hello" จะเห็นว่าหลังจบ action มันได้ forward เราไปที่หน้า hello.jsf นั่นเอง เห็นยังครับ navi แบบ default ก็คือชื่อไฟล์ xhtml เรานี่เองแต่ตัด .xhtml ออกไป ทีนี้ถ้าเราอยากให้มัน forward ไปที่อื่นเราก็แค่เปลี่ยน String ที่ return ตอนจบ action ใน ManagedBean นั่นๆซะ
แต่ถ้าไฟล์ xhtml อยู่ใน sub directory เราก็ต้องใส่ชื่อ directory นั่นๆด้วยตามนี้

$WEB-FOLDER/
----$WEB-INF/
----$SUB-DIRECTORY1/abc.xhtml


default navigation rules สำหรับ abc.xhtml ก็จะเป็น /$SUB-DIRECTORY1/abc นั่นเอง
เรายังมี default อีกอย่างคือ return null ครับ ความหมายถือให้ redirect กลับไปที่หน้าเดิม

ต่อๆ แล้วถ้าเกิดว่าเราคิดว่าแบบข้างบนยาวไปหร่ะเราจะทำไงได้ ก็ทำให้สั่นลงครับด้วย xml config ด้านล่างนั่นเอง

<navigation-rule>
----<description />
----<display-name />
----<icon />
----<from-view-id />
----<navigation-case>
--------<description />
--------<display-name />
--------<icon />
--------<from-action />
--------<from-outcome />
--------<to-view-id />
--------<redirect />

<description />, <display-name />, <icon /> : สามอันนี้เป็นแค่ meta-data ครับ ไม่ต้องสนใจ (จุดประสงค์ทำให้เปิดมาอ่านแล้วไม่งงกับทำให้พวก GUI Tool ทั่้งหลายใช้ซะมากกว่า

<from-view-id >helloform.xhtml</from-view-id > : อันนี้สำหรับไว้กำหนดเป็น rules สำหรับ pages ไหนครับ (สามารถใส่ * ได้แทนความว่า apply rules เข้ากับทุกหน้า)

<from-action >#{helloManagedBean.hello}</from-action >, <from-outcome>hello</from-outcome> : จะมีสี่กรณีที่เป็นไปได้ครับ
1. กรณีที่ไม่มีทั้งสองตัวจะหมายถึง default ของ rule นั้นๆ ในกรณีที่ไม่ตรงกับ criteria อะไรเลย
2. กรณีที่มีแค่ <from-action /> คือไม่ว่าจะ return อะไรที่มาจาก action ที่กำหนดไว้จะไปที่ <to-view-id />
3. กรณีที่มีแค่ <from-outcome/> คือจะไปที่ <to-view-id /> โดยไม่สนว่ามาจาก action ไหนๆ
4. กรณีสุดท้ายคือมีทั้งคู่ คือต้องเป็น outcome ที่มาจาก action นั่นๆเท่านั้นถึงจะไปที่ <to-view-id /> ที่กำหนดไว้

<to-view-id>hello.xhtml</to-view-id> : สำหรับกำหนด jsf page ของ rule นั้นๆ

<redirect /> : อันนี้สำหรับกำหนดว่าจะให้มันไปแบบ forward, redirect ครับ (รายละเอียดอ่านได้ในเนื้อหาเกี่ยวกับ Servlet)
** ใน 1 <navigation-rules> สามารมี <navigation-case> ได้มากกว่า 1 นะครับ

อ่ะ เสร็จแล้วๆ อะฮิๆ ทีนี้ก็ Checkout/Update Code ลงมาแล้วลุยกันเลยครับ โดยไฟล์สำหรับดูเรื่อง Navigation rules จะมีดังนี้ NavigationManagedBean.java, navigation.xhtml, bangkok.xhtml, tokyo.xhtml, paris.xhtml, faces-config.xml

ปล. รอบนี้แอบใจร้ายนะครับ เพราะว่าทั้งใน faces-config.xml, NavigationManagedBean ยังไม่เสร็จทั้งคู่ โดยผมได้ใส่ @TODO ไว้แล้วว่าต้องทำอะไรเพิ่มบ้าง

copyright 2010 @nuboat in wonderland
ข้อเขียนนี้ช่วยฉัน:  

Wednesday, June 23, 2010

JSF 2.0 Expression Language

มาแล้วตอนต่อของ JSF 2.0 ก่อนหน้านี้พอดีมีคนมาถามเรือง Session ในทวิตเตอร์ครับ ก็ขอโทษทีช้านะครับ อาจจะช้าๆกันสักนิดนะครับ ผมเผาเนื้อหาให้ไม่ทันค้าบบบ JSF ไ่ม่ใช่น้อยๆนะ ได้บ่นก่อนเขียนแล้วก็มาดูกันต่อดีกว่า ก่อนหน้านี้เราก็ได้เห็น Expression Language หรือ #{helloManagedBean.name} พวกนี้แทรกๆอยู่ตามหน้า xhtml ต่างๆของเรานะครับ ทีนี้แหละเราจะมาดูส่วนนี้แบบละเอียดๆ กันครับว่าเราจะใช้ EL ได้ในรูปแบบใดๆบ้างนะครับ

1. เราจะใช้มันในการ set/get data ระหว่างหน้าจอกับ bean ครับผมแบ่นเป็นให้ดูเป็นสามรูปแบบนะครับ
1.1 อ้างถึง Element แบบธรรมดาก่อนละกันครับ เช่น
#{helloManagedBean.name} หรืออาจจะ nested ลงไปก็ได้เช่นถ้าให้ userView เป็น POJO ที่มี name เป็น property อีกทีก็ #{expressionManagedBean.userView.name}

1.2 อ้างถึง Element ที่เป็น array, list ต่างๆ ดังรูปแบบนี้นะครับ #{bean.array[index]}
#{expressionManagedBean.listdata[0]}
#{expressionManagedBean.listdata[1]}
ตามตัวออย่างนี้ listdata เป็น String[] listdata = new String[4]
#{expressionManagedBean.userList[0].name}
#{expressionManagedBean.userList[0].username}
#{expressionManagedBean.userList[0].group}
#{expressionManagedBean.userList[1].name}
#{expressionManagedBean.userList[1].username}
#{expressionManagedBean.userList[1].group}
ตามตัวออย่างนี้ userListเป็น List<UserView> userList = new LinkedList<UserView>()

1.3 อ้างถึง Element ที่เป้น Map, Hash โดยจะมีรูปแบบดังนี้คือ #{bean.hashtable[key]}
#{expressionManagedBean.mapdata["HOTMAIL"]}
#{expressionManagedBean.mapdata["GMAIL"]}
ตามตัวออย่างนี้ Map<String, String> mapdata = new HashMapString, String>()
ex. <h:inputText value="#{helloManagedBean.name}" /> หรือใช้ print ตรงๆ เลยก็ได้ {helloManagedBean.name}

โดยการทำแบบนี้นั้นตัว HelloManagedBean ก็ต้องมีการประกาศ set/get ของ property name ไว้ด้วยเพือให้สามารถเข้าถึงข้อมูลได้นะครับ


2. เราจะใช้ในการให้ JSF call ไปที่ action ต่างๆของ ManagedBean ตัวนี้ดูง่ายครับ ก็เรียกตรงๆได้เลย
ex. <h:commandButton value="OK" action="#{helloManagedBean.hello}" />
hello เป็น method นะครับไม่ใช่ property ไม่ต้องสร้าง getHello นะครับ ;P

3. ใช้ EL Operators ต่างๆ ดังนี้
Arithmetic :: – +-*/div%mod
Relational :: Use eq, ne, lt, gt, ge, instead of ==, !=, <, >, >=
Logical :: Use and, or, not instead of &&, ||, !
Empty :: empty โดยที่จะเป็น true เมือเป็น null, empty string, empty array, empty list, empty map และเป็น False ในกรณี่อื่นๆ

ex. #{3+2-1}, #{3+2-1}, #{3%2}, #{3/4 == 0.75}, #{ null == "test" }, #{true ? 'true' : 'false'}

update svn แล้วก็มาลองรันกันดูเลยครับ
1. http://127.0.0.1:8080/easyjsf/expression.jsf
2. http://127.0.0.1:8080/easyjsf/operators.jsf


copyright 2010 @nuboat in wonderland
ข้อเขียนนี้ช่วยฉัน:  

Tuesday, June 22, 2010

JSF 2.0 ManagedBean

ผ่านไปแล้วกับ Getting Started นะครับ ในส่วนนั้นเราคงไม่มีอะไรมาก นอกจากแค่อยากให้ทุกคนสามารถที่จะ Startup project ได้แบบ full loop คือ New -> Implement -> Build -> Deploy -> Test และในส่วนตัวผม ผมว่าทุกเรื่องนี่ยากที่สุดก็ Startup นี่แหละครับแต่พอมันได้แล้วที่เหลือมันก็ได้ไปเรื่อยๆเองนั่นแหละ เท่ากับว่าทุกคนจงดีใจได้เลยเราว่าผ่านส่วนที่ยากที่สุดของ JSF มาแล้วนั่นเอง (หุหุ ใครจะเชือผมมั่งเนี่ย)

JSF คือไรก็ได้บอกไปแล้ว ทีนี้ JSF มีส่วนสำคัญคืออะไร ก็คงเป็น ManagedBean ที่เราจะมาดูกันต่อนี่แหละ มันมีไว้ทำไม ก็เป็นส่วนที่ไว้คำนวนทุกอย่างที่เราต้องการให้โปรแกรมทำได้นั่นแหละครับ โดยในบทที่แล้วเราก็จะเห็นว่า JSF สร้าง ManagedBean ได้ง่ายๆ โดยการใส่ @ManagedBean ไว้ที่ส่วนหัวของ Class IndexManagedBean, HelloManagedBean แค่นั่นเอง แต่จริงๆแล้ว Annotation ที่มีสำหรับ ManagedBean มันมีมากกว่านั่นนะสิครับ ทีนี้แหละที่เราจะมาดูกันว่ามันมีอะไรกันบ้าง

โดยผมแบ่งเป็นสองกลุ่มใหญ่ๆครับ
1. สำหรับกำหนดให้ Class ที่ถูกกำหนดเป็น ManagedBean ซึ่งใช้
@ManagedBean( name="", eager = true/false )
name จะไว้สำหรับกำหนดชือสำหรับเรียกครับ โดย default จะเป็นชื่อ Class ที่เปลี่ยนชือตัวหน้าเป็นตัวเล็กนั่นแหละครับ เช่น helloManagedBean, indexManagedBean แต่จริงแล้วเราสามารถที่จำกำหนดให้มันเองเลยก็ได้ (เดี๊ยวไปดูในตัวอย่างละกันครับ) ส่วน eager=true จะมีผมแค่ตอนที่ Scope เป็น @ApplicationScoped เท่านั้น จะเป็นการสั่งให้ Container สร้าง ManagedBean ไว้ก่อนเลย (ถ้าเป็นปกติจะสร้างเมือมีการเรียกเข้ามาครั้งแรก)

2. สำหรับกำหนด Scope ของ Data ว่าจะให้เป็นอะไร เช่น (request, session, application)
@RequestScoped
@SessionScoped
@ApplicationScoped
@ViewScoped
@CustomScoped(value="#{somemap}")
@NoneScoped

โดยเราจะมาดูที่ 4 อันแรกครับ
1. @RequestScoped - จะมีการสร้างและทำลายทุกๆครั้งที่จบ http request
2. @SessionScoped - จะมีการสร้างและไม่ทำลายจนกว่าจะมีการสร้างทำลาย session หรือ session timeout(ตามค่าใน web.xml)
3. @ApplicationScoped - จะมีการสร้างครั้งแรกเท่านั้นจากนั้นจะไม่สร้างอีกแล้ว
4. @ViewScoped - จะมีการสร้างและคงไว้ตราบเท่าที่เรายังอยู่ในหน้านั่นๆ ไม่เปลี่ยนหน้าไปไหน (ใช้สำหรับงานประเทภ AJAX) นั่นแหละครับและอยู่บนพื้นฐานว่า session ต้องยังไม่หมดอายุด้วยถ้าเป็น request ใหม่ก็หายนะครับ (สำหรับตัวนี้คงไปเห็นภาพ

@CustomScoped, @NoneScoped คงยังไม่พูดถึง (คือผมก็ยังไม่ได้อ่านหรือลองมันดูจริงๆเลยครับ) พอดีผมทำโปรเจคด้วย JSF1.2 ครับ แต่เห็นว่าไหนๆจะเขียนแล้วก็เลยมาเขียนที่ JSF2.0 ไปเลยดีกว่า


โอเคเรียบร้อยแล้วครับ http://easyjsf.googlecode.com/svn/trunk/EasyJSF2.0 easyjsf-read-only แล้วลองรัน scope.xhtml (http://127.0.0.1:8080/easyjsf/scope.jsf) กันดูเลยครับ

ขี้เกียจก๊อปโค้ดมาใส่ครับ เอาว่าถ้าอ่านแล้วเอาจากโค้ดลงมาแล้วไม่เข้าใจผมจะอธิบายเพิ่มให้อีกทีนะครับ (ดึกแล้วไม่ไหวแล้วแหะๆ)

ถ้าดู scope.xhtml จะเห็นว่าตัว JSF ทำให้เราสามารถทำให้ .xhtml ต่อกับ java ได้แบบ 1-n ซึ่งผิดกับสมัยก่อนที่ใช้พวก Servlet, Struts ที่จะเป็นลักษณะ 1-1 ( a.jsp -> Servlet/StrutsAction) ถ้าใช้ไปเรือยๆแล้วจะรู้ว่ามันช่วยในการ reuse code ส่วน mvc มากครับ แต่คงไม่เห็นกันตอนนี้หรอกจะเห็นเมือได้เอาไปทำในโปรเจคที่เป็นรุปธรรมซะมากกว่า สำหรับผมผมว่าอันนี้แหละเป็นส่วนที่เก่งที่สุดของ JSF เลยหร่ะ

ปล. เรายังยืนยันว่า Tutorial นี้เหมาะสำหรับคนที่พอรู้ Web Programming มาบ้างแล้วครับ ^ ^

copyright 2010 @nuboat in wonderland
ข้อเขียนนี้ช่วยฉัน:  

Sunday, June 20, 2010

Getting Started with JSF 2.0 (ต่อ)

มาดู WEB.XML config กันก่อนดีกว่าครับ อันนี้ก็ถ้าใครไม่รู้พื้นฐาน Servlet ผมก็ช่วยไม่ได้นะครับแนะนำว่าให้กลับไปอ่านบทความเก่าผมเรือง Servlet ที่ http://thaidev.org ก่อนถ้าสนใจแบบละเอียด แต่ตอนนี้เรามาดู config เฉพาะที่เกี่ยวข้องกับ jsf กันก่อนดีกว่าครับ

<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
อันนี้จะทำให้เวลา JSF เกิด Error มันจะพ่น log มากกว่าปกติเพือช่วยให้แก้ปัญหาได้ดีขึ้น(จริงหรือเปล่า ?)

<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
อันนี้เป็นตัวที่เราจะให้มันทำงานเมื่อเราเรียกไปที่ xxx.jsf สามารถเปลี่ยนเป็นอะไรก็ได้เช่น *.htm, *.pl, *.php, *.xxx (แต่ตัวไฟล์เราจะใช้เป็น .xhtml) นะครับ

ต่อไปเราจะมาสร้าง ManagedBean สำหรับ Process งานของ JSF กันครับ

เอาแบบง่ายๆก่อนคือเราจะสร้าง ManagedBean สำหรับโชว์ข้อมูลบนหน้า JSF
1. สร้าง package cc.nuboat.easyjsf.managedbean
2. สร้าง IndexManagedBean.java
/*
* copyright 2010
*/

package cc.nuboat.easyjsf.managedbean;

import javax.faces.bean.ManagedBean;

/**
*
* @author nuboat
*/

@ManagedBean
public class IndexManagedBean {
private String hellostr;

public IndexManagedBean() {
hellostr = "Hello from Facelets";
}

public String getHellostr() {
return hellostr;
}

public void setHellostr(String hellostr) {
this.hellostr = hellostr;
}

}

แก้ index.xhtml ในส่วนของ body ตามด้านล่าง
<h:body>
#{indexManagedBean.hellostr}
</h:body>

ทดลองรันดูเลยครับ พอเสร็จแล้วก็กลับไปแก้ IndexManagedBean
public IndexManagedBean() {
hellostr = "Hello from IndexManagedBean";
}
save แล้วลองไปรัน browser ดูใหม่ว่า text มันเปลี่ยนไปหรือยังนะครับ

มาดู requirement ต่อไปกันดีกว่าครับทีนี้จะยากขึ้นหน่อยคือให้มีหน้าจอสำหรับรับข้อมูลชื่อทาง Textbox แล้วก็ มีปุ่ม Submit แล้วให้ไปหน้าแสดงผลที่โชว์ว่า Hello [Name]. นะครับ เราจะมามองก่อนว่าเราต้องสร้างอะไรบ้าง

1. hello.xhtml
2. helloform.xhtml
3. HelloManagedBean.java

hello.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Hello</title>
</h:head>
<h:body>
Hi Khun. #{helloManagedBean.name}.
</h:body>
</html>


helloform.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f ="http://java.sun.com/jsf/core">
<h:head>
<title>Hello Form</title>
</h:head>
<h:body>
<h:form>
What's your name? : <h:inputText value="#{helloManagedBean.name}" /> : <h:commandButton value="OK" action="#{helloManagedBean.hello}" /> <br />
</h:form>
</h:body>

</html>

HelloManagedBean.java
/*
* copyright 2010
*/

package cc.nuboat.easyjsf.managedbean;

import javax.faces.bean.ManagedBean;

/**
*
* @author nuboat
*/
@ManagedBean
public class HelloManagedBean {
private String name;

public String hello() {
return "hello";
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

}


ปล. ใครอยากได้ Sourcecode ก็สามารถมา checkout ลงไปดูกันได้ครับ
svn checkout http://easyjsf.googlecode.com/svn/trunk/EasyJSF2.0 easyjsf-read-only


copyright 2010 @nuboat in wonderland
ข้อเขียนนี้ช่วยฉัน:  

Saturday, June 19, 2010

Getting Started with JSF 2.0

สวัสดีครับ ก็จะมาแนะนำ Tutorial ของ JSF 2.0 ครับ อืมจะว่าไงดีนะ ไม่ได้เขียนบทความมานานแถมผมยังเป็นพวกที่คนบอกกันว่า พูดภาษาคนไม่รู้เรื่องซะด้วย ยังไงก็ตั้งใจอ่านกันหน่อยละกันครับ อ๋อ แนะนำตัวกันก่อน ก็ @nuboat ครับเป็นคนที่ว่ารักในการเขียนโปรแกรมก็ว่าได้ ปัจจุบันก็เป็น System Analyst and Banking Specialist ที่แบงค์สีเขียวแห่งหนึ่ง ก็มีหน้าที่ออกแบบและพัฒนาระบบเกี่ยวกับ Treasury ครับ เป็นคนที่ใช้ Java อยู่เป็นนิจ เรียกได้ว่าผมมีประสบการ์ณกับ Java กันแทบทุก platform เลยทีเดียว JavaSE, JavaME, JavaEE, JavaCard ... ว่าไปขาด JavaFX แหะ นอกเรื่องนาน มาดูกันดีกว่ากับ JSF 2.0

JSF เป็นอะไร เอาจากที่ตัวผมเห็นมานะครับ JSF เป็น Web Framework ตัวหนึ่งแต่มันมีลักษณะเหมือน Window Programming มากกว่า Web ที่เป็น Request, Response นะสิครับ ทีนี้ ถ้าคิดจะพัฒนาโปรแรกมด้วย JSF ผมอยากให้คนที่มีพื้นฐานการพัฒนาเว็บเปลี่ยนมุมมองมาเป็นว่ากำลังพัฒนา Window Application ที่เป็น

จริงๆ อยากให้เข้าใจแก่นของ JSF จริงๆก่อน coding แต่ผมว่าเราไป coding กันก่อนให้ชินกับ JSF แล้วค่อยมาดูมันก็ยังไม่สายครับ

ทีนี้เนื่องจาก JavaEE เป็นสิ่งที่มีปัญหาเรื่อง การ config, setup, build, deploy มากพอดู (มากมากเลยแหละ) เพื่อไม่ให้เกิดปัญหา ผมขอบังคับให้ใช้ทุกอย่างตามนี้นะครับ ถ้าใครใช้ไม่เหมือนผมแล้วมาถามว่า Error อะไร ก็ ... ช่วยตัวเองกันครับ 555+

จากการไปเป็น TA ให้กับ #springtrainingday ของ spring66.com ตลอดทุกครั้งคือ แต่ละคนมี environment เป็นของตัวเองกันทั้งนั้น แล้วทีนี้อะไรเกิดขึ้นหร่ะ กว่าจะแค่ทำให้รันได้นี่อย่างเหนือย แล้วนะถ้าคนที่เข้าใจ java architecture จริงๆก็ง่าย ... แต่ความจริงคือหลายคนไม่รู้นะสิ อาจจะเขียน java ได้แต่ไม่เข้าใจมันในหลายๆเรื่อง ทีนี้เพือให้งานนี้ smooth ผมจะขอบังคับ IDE ละกันครับเพราะอยากให้ scope ความรู้ไปที่ JSF จริงๆ

1. JavaSE JDK 1.6 u14 up

2. Netbeans 6.8 up ต้องเป็น release ที่ support Java Web and EE
* default netbeans จะไม่ติดตั้ง tomcat ให้แต่ผมแนะนำให้ customize แล้วเลือกมันมาด้วยเพราะเล็กและง่ายกว่า

โอเค ถ้าเตรียมตัวกันเรียบร้อยก็เริ่มกันเลยครับ เปิด Netbeans แล้วกด New Project กันเลย

1. เลือก Categories เป็น Java Web -> Web application
2. ตั้งชื่อ Project แล้วก็ Browse ไปที่ path ที่จะวาง Projec
3. เลือก Server เป็น Tomcat 6.x Java EE version Java EE 5, context path เป็น /easyjsf
4. เลือก Java Server Faces ,ไปที่ Tap Libraries เลือก Registered Libraries เป็น JSF2.0
5. แล้วไปที่ Tap Confuguration ที่ JSF Servlet URL Pattern ให้กำหมดเป็น *.jsf
6. Finish ได้เลยครับ


เสร็จแล้วยังไม่ต้องคิดอะไรครับ คลิกขวาที่ project แล้วสั่ง deploy เลยครับ
จากนั้นลองเข้า browser ด้วย URL ตามนี้ครับ http://127.0.0.1:8080/easyjsf/index.jsf

จะขึ้นหน้าเปล่าๆ ว่า "Hello from Facelets" .... หวังว่าจะไม่มี error กันทุกคนนะครับ

copyright 2010 @nuboat in wonderland
ข้อเขียนนี้ช่วยฉัน:  

Thursday, June 17, 2010

การ set ให้ Web server เราสามารถรองรับคนจำนวนมากได้

วันนี้ผมได้รับคำถามจาก Twitter (@oracleinth) อีกแล้วครับ โดยที่คำถามเค้าได้ถามมาว่า...
"ขอถามหน่อยนะครับว่า ถ้าเราลง apache tomcat 6.x เพื่อรัน jsp เป็น Web server เราต้องเซตอะไรบ้างเพื่อให้มันรองรับคนจำนวนมากๆ ? "

ถ้าจะพูดถึงการ set ให้ Web server ของเราสามารถรองรับคนจำนวนมากนั้น สามารถทำได้หลายวิธี ซึ่งถ้าเป็นวิธีพื้นฐานเลย นั่นคือ การ set session timeout วิธีนี้ก็จะช่วยได้ในระดับนึง แต่ set session timeout นั้นมันไม่ได้ช่วยอะไรได้มากเท่าไร จากประสบการณ์ที่เคยเจอมากับตัวนะครับ แต่อีกเรื่องนึงที่พอเราไป set รับรองว่ารับคนได้เยอะขึ้นชัวร์คือไปเพิ่ม memory ให้กับ java นั่นเอง

การไป set parameter ดังนี้
JVM option passed to Resin Meaning
-Xms initial java heap size
-Xmx maximum java heap size
-Xmn the size of the heap for the young generation

แต่การเพิ่มพวกนี้ Ram ต้องเยอะด้วยนะ

การไป set ต้องไป set ที่ Environment variable ของ OS เช่นที่ Windows

set JAVA_OPTS=-Xms512m -Xmx1024m

นอกจากจะ set ที่ Environment variable ของ OS ยังไป set ที่ Tomcat ตรงๆได้ ไป set ที่ file %TOMCAT_HOME%\bin\catalina.bat
ไป search ที่ parameter JAVA_OPTS แล้วไปแก้ไขตรงนั้น

ที่เห็นผลได้ชัดเจน client รองรับได้เยอะขึ้น

...จะบอกว่าการ config อย่างเดียวมันก็ไม่ได้ช่วยได้ที่จะทำให้ Tomcat รองรับได้เยอะขึ้น
อย่างการเพิ่ม memory ให้กับ java, การ set session timeout เป็นการแก้ปัญหาที่ปลายเหตุทั้งสิ้น ถึงการแก้แบบนี้จะรองรับ client ได้เยอะขึ้นแต่เอาเข้าจริงไม่มีทางเกินหลักพัน (ใช้พร้อมกัน) เคยลองใช้ jmeter ลองจำลอง client พันตัวพร้อมกันก็ไม่ไหวแล้ว

พอดีผมได้ฟังประสบการณ์ที่มาจากรุ่นพี่ ซึ่งเค้าเคยทำงานกับ web ที่ uip เป็นหลักหมื่นต่อวัน
ซึ่ง web นี้ใช้ php เป็นภาษา developer ส่วน database ก็เป็นเพียง mysql หรือง่ายๆก็คือ LAMP

ผมเลยถามเค้าว่าทำยังไงถึงได้รองรับ user ได้เยอะขนาดนี้ ?
เค้าก็ตอบว่าทำ web ยังไงก็ได้อย่าให้มีการติดต่อ database เป็นดีที่สุด อย่าไปดึงมาเด็ดขายไม่งั้น web ล่มแน่
พี่เค้าก็บอกว่า เชื่อหรือไม่ว่าหน้าแรกของ web ดังทั้งหลายในไทยเป็น HTML ล้วนๆ โดยจะมีการ generate หน้าแรกตั้งทิ้งไว้เป็น HTML จากนั้นเวลาที่ใครมาเรียกก็จะเรียกจากหน้าที่ generate นั้น (ตรงนี้การแยก HTTP server กับ Servlet Container ออกจากกันจะช่วยให้ทำงานได้ดีมากขึ้น เพราะ PHP ก็ต้องแยกเหมือนกัน)

แล้วผมก็ถามต่อว่าถ้าเป็นหน้าข่าวที่มีคน comment เรื่อยๆหละจะทำยังไง เค้าบอกว่าใช้เทคโนโลยี Caches เข้ามาช่วย จะทำการติดต่อ database ก็ต่อเมื่อ insert, update, และ delete เท่านั้น ถ้าจะ select จะ select แค่ครั้งเดียวเท่านั้น แต่จะ select ใหม่ถ้ามีการ update โดยข้อมูลทั้งหมดจะถูกเก็บลง cache ทั้งหมด ที่ต้องเก็บลง cache ทั้งหมดนั้นจะดีกว่าการ select ใหม่ทุกครั้ง เพราะจะมี overhead สูงมากในการติดต่อ DB

ซึ่งใน java นั้นก็มีอยู่นะ เยอะด้วยยกตัวอย่าง Coherence Caches ของ oracle http://www.oracle.com/technology/pub/articles/vohra-coherence.html ซึ่งเคยได้ยินมา แต่ไม่เคยทดลองเล่นดู...

นอกจาก database cache แล้วใน java ยังมี lib หลายๆส่วนที่สามารถทำ cache ได้ อย่างเช่น connection cache ของการติดต่อ DB (Connection Pooling), การทำ cache ของ object เป็นต้น

และมีอีกประเด็นที่จะเสริมเกี่ยวกับการใช้งาน tomcat เพื่อรับ load จำนวนมาก ควร config tomcat เข้ากับ apache(http server) เพื่อแยกงานการ render web (html) กับงานประมวลผล Java ออกจากกัน
จะทำให้ประสิทธิภาพโดยรวมดีขึ้น

ดูที่ http://tomcat.apache.org/connectors-doc/webserver_howto/apache.html

Credit by @plaumkamon, Kim
ข้อเขียนนี้ช่วยฉัน:  

การ recovery PFILE และ SPFILE

บทความนี้ ผมขอเอาใจ DBA ทุกท่านโดยเฉพาะเลย สมมุติว่าถ้า DBA เผลอทำ parameter file หาย และ shutdown instance ไปแล้วด้วย, แถมยังไม่เคยมีการ backup ไว้ก่อนเลย, DBA สามารถแก้ไขอย่างไรได้บ้าง ? โดยปกติแล้ว ถ้าเกิดเราทำ file ใด ๆ ในเครื่องคอมหาย การจะกู้คืนกลับมาเราจะใช้การ recovery, ฉะนั้น เรามาดู วิธีการ recovery PFILE และ SPFILE ที่ไม่ได้มีการ backup ไว้กันเลยดีกว่า

ผมได้ทดสอบทำดู เลยจะขอแจงแจงรายละเอียดเป็นขั้นตอนต่อไปนี้ครับ

1. ทำการ shutdown instance และลบไฟล์ทั้ง 2 file นะครับ คือ PFILE และ SPFILE โดย
PFILE จะอยู่ที่ Path /oracle/admin/orcl/pfile
SPFILE จะอยู่ที่ Path /oracle/db11201/dbs

2. ไปเปิด alert log เพื่อดู parameter โดย alert log จะอยู่ที่ Path
/oracle/diag/rdbms/orcl/orcl/trace
โดยมีชื่อไฟล์ว่า alert_orcl.log

3. ทำการ copy ในส่วนนี้ของไฟล์ alert log มานะครับ
processes                = 150
  memory_target            = 812M
  control_files            = "/oracle/oradata/orcl/control01.ctl"
  control_files            = "/oracle/flash_recovery_area/orcl/control02.ctl"
  db_block_size            = 8192
  compatible               = "11.2.0.0.0"
  db_recovery_file_dest    = "/oracle/flash_recovery_area"
  db_recovery_file_dest_size= 3852M
  undo_tablespace          = "UNDOTBS1"
  remote_login_passwordfile= "EXCLUSIVE"
  db_domain                = "co.th"
  dispatchers              = "(PROTOCOL=TCP) (SERVICE=orclXDB)"
  audit_file_dest          = "/oracle/admin/orcl/adump"
  audit_trail              = "DB"
  db_name                  = "orcl"
  open_cursors             = 300
  diagnostic_dest          = "/oracle"
4. ทำการสร้าง PFILE ชื่อ initorcl.ora ไว้ที่ Path /oracle/db11201/dbs โดยนำ content ของ alert log ที่ copy มาใส่ลงไปในไฟล์

5. เข้า sqlplus ด้วย user sys และทำการ start instance
$ sqlplus /nolog
sql> conn / as sysdba
sql> startup

6. ทำการสร้าง SPFILE จาก PFILE ไปไว้ที่ Path /oracle/db11201/dbs ด้วยคำสั่งต่อไปนี้
sql> create spfile='spfileorcl.ora'
       from pfile='/oracle/db11201/dbs/initorcl.ora';
7. เราจะได้ spfile ที่ชื่อ spfileorcl.ora มานะครับ

8. ทดสอบ startup instance อีกครั้ง พบว่าสามารถ start ได้ครับ
SQL> startup
ORACLE instance started.

Total System Global Area  849530880 bytes
Fixed Size                  1339824 bytes
Variable Size             499125840 bytes
Database Buffers          343932928 bytes
Redo Buffers                5132288 bytes
Database mounted.
Database opened.
SQL> 

เท่านี้เราก็สามารถนำ PFILE และ SPFILE กลับมาได้เหมือนเดิมแล้วครับ :)

Credit by Ice
ข้อเขียนนี้ช่วยฉัน:  

Tuesday, June 15, 2010

มารู้จักกับ Oracle interMedia กันดีกว่า

Oracle interMedia เป็น feature ที่ทำให้ Oracle Database สามารถที่จะทำการเก็บ บริหารจัด หรือกู้คืนข้อมูลประเภท image, audio, video หรือ media data อื่นๆ โดย Oracle interMedia เพิ่ม reliacility, availability และ data management ในด้านของ multimedia ให้กับ Oracle Database ที่ multimedia เป็นเนื้อหาหรือส่วนต่างๆของ internet, e-commerce และ media-rich application

แต่ Oracle interMedia ไม่ได้ทำการควบคุม media capture หรือ output ของ device เนื่องจากส้วนนี้เป็นหน้าที่ของ application software

โดย Oracle interMedia ทำการบริหารจัดการกับ multimedia โดยรองรับสิ่งต่างๆเหล่านี้
  • การจัดเก็บและการกู้คืน
  • การบริหารจัดการกับ metadata ของ media และ application
  • สามารถที่จะรองรับได้หลาย format
  • สามารถ access ผ่านแบบปกติ และได้กับ web interface
  • ทำการ query ด้วยการใช้ความสัมพันธ์ของข้อมูล
  • ทำการ query ด้วย extracted metadata
  • ทำการ query ด้วยการใช้ media content ที่มี optional specialized indexing
Oracle interMedia รองรับ media content สำหรับ Oracle JDeveloper, Oracle Content Management SDK, Oracle Application Server Porta และ Oracle Partner ด้วย

ตัวอย่างการใช้งาน Oracle interMedia

1. ทำการ connect เข้า database ด้วย sqlplus และทำการ สร้าง table ที่ชื่อว่า "image_table" เพื่อใช้ในการเก็บรูป
connect hr/hr
create table image_table (id number primary key, image ordsys.ordimage);
2. ทำการสร้าง directory ที่เก็บรูปไว้โดย ตั้งให้ตรงกับ directory ที่เก็บรูปไว้อยู่ ด้วย user sys และทำการให้สิทธิในการอ่าน directory แก่ user hr
connect / as sysdba
create or replace directory imagedir as '/home/oracle/quickstart/';
grant read on directory imagedir to hr;
3. ใช้ user hr ในการสร้าง PL/SQL procedure ในการ import รูปเข้ามายัง table
create or replace procedure image_import(dest_id number, filename varchar2) is
img ordsys.ordimage;
ctx raw(64) := null;
begin
delete from image_table where id = dest_id;
insert into image_table (id,image)
values (dest_id, ordsys.ordimage.init())
returning image into img;

img.importFrom(ctx, 'file', 'IMAGEDIR', filename);
update image_table set image=img where id=dest_id;
end;
/
! ที่ IMAGEDIR จะต้องพิมพ์เป็นตัวใหญ่ทั้งหมด แม้ในตอนที่สร้าง directory ขึ้นมาจาพิมพ์ด้วยตัวพิมพ์เล็กก็ตาม

4. ทดลองเรียกใช้ procedure ที่สร้างขึ้นมา
call image_import(1,’book2.jpg’);
call image_import(2,’check.png’);
เสร็จแล้วรูปทั้งสองรูปจะถูกเพิ่มเข้าไปยัง table

5. ตรวจสอบรูปภาพด้วยคำสั่ง select ต่อไปนี้ โดยสามารถใช้ดูได้หลายคุณสมบัติของรูป แต่คำสั่งในตัวอย่างนี้จะเป็นการดูความกว้างความยาวของรูป
SQL> select id,t.image.getheight(),t.image.getwidth() from image t;

ID T.IMAGE.GETHEIGHT() T.IMAGE.GETWIDTH()
---------- ------------------- ------------------
1                 134                572
2                 464                667

ในลิ้งค์อ้างอิงยังมีตัวอย่างการใช้ Oracle interMedia อีก แต่ขอยกตัวอย่างมาเพียงเท่านี้ครับ

Credit by Ice

อ้างอิง
ข้อเขียนนี้ช่วยฉัน:  

Thursday, June 10, 2010

มาลดเวลาการ Start Oracle Database ด้วย Auto Start กันเถอะ

โดยปกติ เวลาผมจะ Start Database นั้น ผมจะ Start แบบ manual มีวันนึงผมก็เริ่มขี้เกียจมา อยากจะให้ Database มัน Start เองเลยหลังจาก Boot OS เสร็จ...ผมเลยไปหาวิธีที่จะให้มัน Auto Start Database หลังจากการ boot OS เลยโดยที่ผมไม่ต้องไปทำ manual start อีกต่อไป วันนี้เลยอยากจะแชร์บทความนี้ไว้ เผื่อใครอยากทำบ้างนะครับ

มาดูวิธีที่จะทำให้ Oracle Database auto start ขึ้นมาหลังจากการ boot OS โดยที่ admin ไม่ต้อง manual start กันเลยดีกว่า

1. login root

2. เข้าไปแก้ที่ /etc/oratab
โดยสังเกตุที่บรรทัด orcl:/oracle/db11201:N
ถ้าเป็น N อยู่ให้เปลี่ยนเป็น Y ดังนี้ orcl:/oracle/db11201:Y

3.สร้างไฟล์ใหม่ชื่อ dbora ไว้ที่ /etc/init.d/ โดยรายละเอียดตามด้านล่าง

#!/bin/sh
#chkconfig: 345 99 10
#description: Oracle auto start-stop script.
#
#Set ORA_HOME to be equivalent to the $ORACLE_HOME
#from which you wish to execute dbstart and dbshut;
#
#Set ORA_OWNER to the user id of the owner of the
#Oracle database in ORA_HOME.

ORA_HOME=/oracle/db11201
ORA_OWNER=oracle

if [ ! -f $ORA_HOME/bin/dbstart ]
then
echo "Oracle startup: cannot start"
exit
fi

case "$1" in
'start')
#Start the Oracle databases:
#The following command assumes that the oracle login
#will not prompt the user for any values
su - $ORA_OWNER -c "$ORA_HOME/bin/emctl start dbconsole" &
su - $ORA_OWNER -c "$ORA_HOME/bin/dbstart $ORA_HOME"
touch /var/lock/subsys/dbora
;;
'stop')
#Stop the Oracle databases:
#The following command assumes that the oracle login
#will not prompt the user for any values
su - $ORA_OWNER -c "$ORA_HOME/bin/emctl stop dbconsole" &
su - $ORA_OWNER -c "$ORA_HOME/bin/dbshut $ORA_HOME"
rm -f /var/lock/subsys/dbora
;;
esac

ข้อควรระวัง ต้องแก้ส่วน path ORA_HOME ให้ตรงตามที่เราเซ็ต $ORACLE_HOME ไว้ด้วย

4. ทำการ execute โดยใช้คำสั่งตามด้านล่างนี้

#chmod 750 /etc/init.d/dbora
#ln -s /etc/init.d/dbora /etc/rc.d/rc0.d/K01dbora
#ln -s /etc/init.d/dbora /etc/rc.d/rc3.d/S99dbora
#ln -s /etc/init.d/dbora /etc/rc.d/rc4.d/S99dbora
#ln -s /etc/init.d/dbora /etc/rc.d/rc5.d/S99dbora
#ln -s /etc/init.d/dbora /etc/rc.d/rc6.d/K01dbora

5. ทำการ reboot เครื่องใหม่ ก็เป็นอันเสร็จ

เราจะทราบได้อย่างไรว่าสิ่งที่เราทำไป database ได้ start หรือ shutdown ได้ถูกต้องจริงๆ
  • ตรวจสอบ log file เมื่อเปิดเครื่อง ที่ $ORACLE_HOME/startup.log
  • ตรวจสอบ log file ไฟล์เมื่อปิดเครื่อง ที่ $ORACLE_HOME/shutdown.log

Credit by Bie

อ้างอิงจาก
ข้อเขียนนี้ช่วยฉัน:  

Tuesday, June 8, 2010

ทำไมการใช้ index จึงทำให้ query ข้อมูลได้ไวขึ้น?

การทำ index ในฐานข้อมูล ก็คลายกับการทำ index ในท้ายเล่มของหนังสือ การที่เราจะหาเนื้อหาในหนังสือเราก็เปิดไปที่ index แล้วก็หาว่าตัวเนื้อหาที่เราต้องการอ่านนั้นอยู่หน้าไหนบ้าง เราก็เปิดไปยังหน้านั้นได้เลย โดยที่ไม่ต้องมาเปิดหนังสือดูทุกหน้าว่าเนื้อหาที่เรากำลังหานั้นอยู่หน้าไหน

ในฐานข้อมูลการทำ index ก็จะทำให้กับ field หรือคอลัมน์ที่เรามีเงื่อนไขในการ query บ่อยๆ การดึงข้อมูลก็จะไปดูที่ index แล้วกระโดดไปยังตำแหน่งที่เก็บข้อมูลเลยโดยไม่ต้องค้นหาทุกแถวในตาราง

ตัวอย่างเช่น การทำ index ให้กับตาราง employees ที่คอลัมน์ emp_id
1rowid
2rowid
3rowid
..
..
..

เมื่อมีการ query

SELECT *
FROM employees
WHERE emp_id = 3;

Database ก็จะวิ่งไปดึงข้อมูลยังตำแหน่งที่เก็บข้อมูลของ emp003 มาแสดง โดยที่ไม่ต้องวิ่งไปหาทุกๆ แถวในตาราง employees

Oracle Database มี Index อยู่หลายประเภทแต่ที่ถูกใช้กันทั่วไปคือ B-Tree Indexes

(รูปภาพจาก www.oracle.com)

จากรูปจะเห็นว่า B-tree Index นั้นมี block อยู่สองประเภทด้วยกันคือ Branch blocks ไว้สำหรับการค้นหา และ leaf blocks สำหรับเก็บค่า ในการค้นหาก็จะแบ่งเป็นช่วงๆ ตามขอบเขตแต่ละ block ทำให้การค้นหานั้นมีประสิทธิภาพ

ซึ่ง การใช้ index นั้น ยังมีรายละเอียดเสริมเพื่อเพิ่มความเข้าใจอีก โดย คุณ Siamnobita ได้อธิบายเกี่ยวกับ index ด้วยกัน 5 ข้อดังต่อไปนี้

1. สิ่งที่ทำให้เราสามารถค้นหาใน index ได้เร็วนั้นเนื่องจากมีการ sort ตามค่าในคอลัมน์ด้วย เคยมีคนตั้งคำถามใน narisa ประมาณว่าทำไม oracle ถึงไม่เรียงลำดับข้อมูลในตารางซะเลย จะได้ไม่ต้องใช้ index คำตอบก็คือการจัดเก็บแบบเรียงลำดับนั้นทำได้ยากกว่าและเกิดต้นทุนตามมาเช่น เวลาที่ใช้เมื่อมีการเพิ่ม record ใหม่ พื้นที่ว่างเมื่อเกิดการ split block เป็นต้น อย่างไรก็ดีหากเราไม่มีปัญหากับต้นทุนเหล่านี้ เราก็สามารถจัดเก็บข้อมูลในตารางแบบเรียงลำดับได้เลย นั่นคือใช้ index-organized table (IOT) ซึ่งถือเป็นวิธีที่เร็วที่สุดในการค้นหาข้อมูลตาม primary key

2. ปกติเวลา oracle อ่านข้อมูลจะอ่านทีละ block ไม่ใช่ทีละแถว ดังนั้นจะดูว่าเร็วหรือช้า จะนับจากว่า oracle ต้อง access ข้อมูลจำนวนกี่ block เช่น

ถ้าดูจากรูปด้านบน index มี 3 level
เมื่อเรา select * from ... where index_column = ??
oracle จะอ่านข้อมูลทั้งสิ้น 4 block คือ root block ตัวบนสุด, branch block ตัวกลาง, leaf block ตัวล่างสุด, table block ซึ่งรู้ได้ทันทีเมื่อรู้ค่า rowid จำนวน level ที่น้อยที่สุดที่เป็นไปได้คือ 1 level คือเก็บ rowid ไว้ใน root block เลย ซึ่งจะเกิดในกรณีที่ข้อมูลมีจำนวนไม่มาก ( โดย default ขนาดของ block ประมาณ 8K )

3. คำถามคือ หากข้อมูลมีขนาดเล็ก ๆ เช่น ตารางมีขนาดแค่ block เดียว การใช้ index ยังมีประโยชน์อยู่หรือไม่ เดิมผมเคยเข้าใจว่าไม่มีประโยชน์เหมือนกัน แต่เมื่อได้อ่าน blog ของคุณ richard foote ซึ่งทำการทดสอบให้เห็นชัด ๆ ไปเลย พบว่า index ก็ยังมีประโยชน์อยู่ดี เนื่องจาก

3.1 ในการ full table scan นอกจากตัว block ที่เก็บ data แล้วยังต้องอ่าน header block ด้วยจึงมี cost ที่เกิดขึ้นไม่ใช่แค่ 1 I/O เมื่อเทียบกับ index ที่ใช้ 2 I/O (root block + data block) ก็พอ ๆ กัน

3.2 ในการ full table scan จะเก็บ data ที่อ่านมาบน buffer cache ด้าน LRU ซึ่งจะอยู่ใน memory ได้ไม่นาน ขณะที่ index scan จะวางไว้ด้าน MRU ทำให้มีโอกาสใช้ประโยชน์จากการอ่านจาก memory โดยตรงได้มากกว่า โดยเฉพาะเมื่อมีการเรียกใช้ข้อมูลจาก table บ่อย ๆ

4. ในข้อ 3 เขาทดสอบเฉพาะกรณี index unique scan เช่นค้นตาม primary key เท่านั้น หากเป็น index range scan จะเป็นอีกกรณีหนึ่ง ซึ่งทุก rowid ที่เจอใน index ก็จะต้องมีการ access table block หนึ่งครั้ง แม้ว่า block นั้นจะอยู่บน memory แล้วก็ยังเป็น cost อยู่ดี ดังนั้น full table scan ก็อาจจะคุ้มกว่าขึ้นกับจำนวนแถวที่ต้องการ

5. ประโยชน์ของ index อีกข้อ คือโดยปกติจำนวน column ใน index จะน้อยกว่า column ใน table มาก ๆ ดังนั้นขนาดของ index ก็จะเล็กกว่า table มาก ๆ ด้วย หากเราต้องการดูเฉพาะข้อมูลที่อยู่ใน index อยู่แล้ว เราก็อาจ full scan ที่ index แทน table ไปเลยก็ได้ ซึ่งกรณีนี้จะเป็นการ fast full scan ซึ่งอ่าน index แบบ multi block เหมือน table scan ( full scan ใน index มี 2 แบบ full scan เฉย ๆ กับ fast full scan แบบแรกอ่านทีละ block ซึ่งช้ากว่า แต่ข้อดีคือ ผลลัพธ์มีการ sort ตาม index แบบหลังจะไม่มีการเรียงลำดับ

ปล. ต้องขอบคุณคำอธิบายดี ๆ จาก คุณ Siamnobita มาก ๆ ครับ

Credit by Paley (@ratipong)

อ้างอิง
ข้อเขียนนี้ช่วยฉัน:  

Friday, June 4, 2010

การเลือก Shutdown database ให้เหมาะสม

หลายท่านที่ได้ทำ Database ต้องรู้จักการ Shutdown database อย่างแน่นอน ซึ่งบางคนก็จะใช้แต่คำสั่ง Shutdown immediate แต่คุณรู้ไหมว่าจริง ๆ แล้วการ shutdown นั้น มีหลายแบบแต่ละแบบนั้นมีความแตกต่างกันขึ้นอยู่กับความเหมาะสมของแต่ละงาน ฉะนั้น เรามาดูกันดีกว่าว่า เราควรจะ Shutdown database แบบไหนให้เหมาะสมที่สุด...


Mode ในการ Shutdown database มีด้วยกัน 4 mode ดังนี้

SHUTDOWN NORMAL mode นี้จะเป็น mode ปกติ ที่ต้องรอให้ผู้ใช้ ใช้งานเสร็จทั้งหมดก่อนถึงจะ shutdown ให้
  • หลังทำการรันคำสั่งนี้แล้ว จะไม่อนุญาตให้มีการเชื่อมต่อเข้ามาใหม่ และ จะรอจนกว่าการเชื่อมต่อที่มีอยู่ทำการยกเลิกการเชื่อมต่อก่อนจึงจะ shutdown
  • การ startup ครั้งต่อไป จะไม่มีการทำ instance recovery

SHUTDOWN TRANSACTIONAL mode นี้จะเป็นการ shutdown ไม่ต้องรอให้ผู้ใช้คนอื่นทำ sessions เสร็จก่อน โดยจะทำการปิด sessions ให้เลย แต่ถ้ายังมีการทำ transactions อยู่ก็รอจนกว่าจะทำเสร็จถึงจะปิดให้
  • หลังทำการรันคำสั่งนี้แล้ว จะไม่อนุญาตให้มีการเชื่อมต่อเข้ามาใหม่ รวมถึง transaction ที่ยังไม่ได้รัน
  • จะรอให้ Transaction ที่ทำงานค้างอยู่ทำงานให้เสร็จก่อน จากนั้นจะทำการยกเลิกการเชื่อมต่อทั้งหมด
  • มีประโยชน์สำหรับการป้องกันไม่ให้งานที่ทำอยู่เกิดข้อผิดพลาด เนื่องจากจะรอให้ทำ transaction ต่างๆที่ค้างอยู่เสร็จก่อน
  • การ startup ครั้งต่อไป จะไม่มีการทำ instance recovery

SHUTDOWN IMMEDIATE mode ไม่ต้องรอใน transactions mode นี้จะปิดให้เลยโดยไม่เลย transactions จบ
  • หลังทำการรันคำสั่งนี้แล้ว จะไม่อนุญาตให้มีการเชื่อมต่อเข้ามาใหม่ รวมถึง transaction ที่ยังไม่ได้รัน
  • Transaction ใดๆที่ยังไม่ได้มีการ commit จะถูก roll back ไปทั้งหมด
  • การเชื่อมต่อทั้งหมดจะถูกยกเลิกทันที
  • การ startup ครั้งต่อไป จะไม่มีการทำ instance recovery

SHUTDOWN ABORT mode นี้จะเป็นการ shutdown เร็วที่สุด เพราะ mode นี้จะไม่ต้องรออะไร
  • หลังทำการรันคำสั่งนี้แล้ว จะไม่อนุญาตให้มีการเชื่อมต่อเข้ามาใหม่ รวมถึง transaction ที่ยังไม่ได้รัน
  • SQL Statement ที่กำลังทำงานอยู่จะถูก terminate ทันที
  • Transaction ใดๆที่ยังไม่ได้มีการ commit จะไม่ถูก roll back
  • การเชื่อมต่อทั้งหมดจะถูกยกเลิกทันที
  • การ startup ครั้งต่อไป จะมีการทำ instance recovery

หรือสามารถดูสรุปได้จากตารางด้านล่างครับ

Database Behavior ABORT IMMEDIATE TRANSACTIONAL NORMAL

Permits new user connections

No

No

No

No

Waits until current sessions end

No

No

No

Yes

Waits until current transactions end

No

No

Yes

Yes

Performs a checkpoint and closes open files

No

Yes

Yes

Yes

Credit by Yong(@stigmatise)

อ้างอิง
ข้อเขียนนี้ช่วยฉัน: