Saturday, May 2, 2009

การใช้ NCHAR และการกำหนด Character Sets

ข้อเขียนนี้ช่วยฉัน: 
Updated: 8/6/2008

เมื่อเรา create database ตัวใหม่ (หรือ instance ใหม่) ทุกครั้ง ในส่วนที่เกี่ยวกับภาษาเราจะต้องระบุพารามิเตอร์สองตัวคือ
1. Database Character Set ซึ่งเป็น Character Set ที่จะถูกใช้เป็น default Character Set
2. National Character Set เป็น Character Set สำหรับ NVARCHAR data type เท่านั้น ซึ่งมีสองแบบคือ AL16UTF16 กับ UTF8
สำหรับการกำหนดค่าของ National Character Set มีข้อคิดดังนี้
AL16UTF16 :
1. ถ้าข้อมูลเป็นภาษาเอเชีย จะประหยัดพื้นที่กว่า UTF8 ซึ่งจะดีในแง่ของพื้นที่ในฮาร์ดดิสก์ และ I/O แต่ถ้าข้อมูลส่วนใหญ่เป็นภาษาทางยุโรปใช้ UTF8 ดีกว่าเพราะประหยัดพื้นที่กว่า
2. Oracle มอง AL16UTF16 เป็น fixed-width characters ดังนั้นจะ process เร็วกว่า
3. ความกว้างสูงสุดของ NCHAR และ NVARCHAR คือ 1000 และ 2000 ตัวอักษร ซึ่งการันตี เพราะเป็น fixed-width
UTF8:
1. ถ้าข้อมูลเป็นภาษาทางยุโรป โดยปกติจะประหยัดพื้นที่กว่า AL16UTF16 (เนื่องจากภาษาทางยุโรปอยู่ในลำดับต้นๆของ Unicode ซึ่งสามารถแทนได้ด้วยข้อมูลเพียง Byte เดียว) และให้ประสิทธิภาพดีกว่าในการ Process
2. ความยาวสูงสุดของ NCHAR และ NVARCHAR คือ 2000 และ 4000 ซึ่งดูเหมือนจะมากกว่า AL16UTF16 แต่ไม่การันตี เนื่องจาก UTF8 เป็น variable width ถ้าเป็น Character ที่ใช้ Byte เดียวก็จะได้ถึง 4000 bytes แต่ถ้าเป็น Character ที่ใช้ 3 Bytes ก็จะมีได้สูงสุดแค่ 4000/3 ตัวอักษร

ตัวอย่างที่ 1
ฐานข้อมูลชื่อ test มี Database Character Set เป็น TH8TISASCII และมี National Character Set = UTF8
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< province_id =" 91;"
SQL> select dump(province_th) from tcr_province where province_id =91; -- สตูล
DUMP(PROVINCE_TH)
--------------------------------------------------------------------------------
Typ=1 Len=12: 224,184,170,224,184,149,224,184,185,224,184,165

คำว่าสตูลมีสี่ตัวอักษร (Character) แต่ละตัวอักษรประกอบด้วย 3 Byte

ในฟิลด์นี้เก็บชื่อจังหวัด โดยตัวที่เืลือกมาคือ 'สตูล' ซึ่งประกอบด้วยตัวอัีกษรสี่ตัว จะเห็นได้ว่ามีรหัสอยู่ = 4 x 3 = 12 ตัว

ตัวอย่างที่ 2
ฐานข้อมูลอีกอันหนึ่งที่มี Database Character Set เป็น TH8TISASCII และมี National Character Set เป็น AL16UTF16
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
SQL> select name,name2 from testn;

NAME NAME2
--------------------------
สตูล สตูล

SQL> select dump(name) as db_char_set , dump(name2) as nls_char_set from testn;

DB_CHAR_SET NLS_CHAR_SET
----------------------------------------------------------------
Typ=1 Len=4: 202,181,217,197 Typ=1 Len=8: 14,42,14,21,14,57,14,37

SQL> select column_name,data_type, data_length from user_tab_columns where table_name = 'TESTN';

COLUMN_NAME DATA_TYPE DATA_LENGTH
------------------------------------------------------
NAME VARCHAR2 300
NAME2 NVARCHAR2 600

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
จะเห็นว่ากรณีของภาษาไทยการใช้ AL16UTF16 กับ NVARCHAR คอลัมน์ จะประหยัดพื้นที่ (และมีประสิทธิภาพในการ process ดีกว่า แต่ไม่ได้แสดงให้ดูในที่นี้) กว่าการใช้ UTF8
อย่างกรณีของคำว่า 'สตูล' ซึ่งถ้าเราใช้ Character Set 'TH8TISASCII' (คอลัมน์ 'NAME' ในตาราง TESTN) จะกินพื้นที่ 4 Bytes(1 Byte ต่อ 1 ตัวอักษร) ในขณะที่ Character Set AL16UTF8 (คอลัมน์ 'NAME2' ในตาราง TESTN) จะกินพี้นที่ 8 Bytes (2 Bytes ต่อ 1 ตัวอัีกษร) และ Character Set UTF8 (คอลัมน์ province_th ในตาราง tcr_province) จะกินพื้นที่ 12 Bytes (3 Bytes ต่อ 1 ตัวอักษร)
อีกประการหนึ่งคือ เมื่อเรา Define จำนวนตอนสร้างตาราง เช่น NAME2 เป็น NVARCHAR2(300) นั้น จำนวน 300 คือจำนวนตัวอักษร ไม่ใช่จำนวน Byte เหมือนกับเมื่อเรากำหนดใน VARCHAR
ดังนั้นเมื่อเรา Query จากใน data dictionary (ตาราง user_tab_columns) เราจะพบว่าบนคอลัมน์ NVARCHAR ที่มี Character Set เป็น AL16UTF16 จะมี data_length เป็นสองเท่าของจำนวนที่ระบุตอนสร้างตาราง (AL16UTF16 ใช้ 2 Bytes แทน 1 ตัวอักษร) ในขณะที่ NVARCHAR ทีมี Character Set เป็น UTF8 จะีมี data_length เป็นสามเท่า
(UTF8 ใช้ 1-4 Bytes สำหรับตัวอักษร (และ 6 Bytes สำหรับ Supplementary Characters) ในกรณีนี้ใช้ 3 Bytes ต่อตัวอักษร)

บทความที่เกี่ยวเนื่องกัน
1. NLS_LANG คือตัวแปร Environment บนฝั่ง Client ไม่ใช่บน Database Server

2 comments:

Anonymous said...

อยากจะใช้ช่วย แปลบทความนี้ให้หน่ายครับ

หรือช่วยเขียน บทความที่เกี่ยวข้องกับ
Character Set Migration for Oracle Database 10g

http://www.oracle.com/technology/tech/globalization/pdf/TWP_Character_Set_Migration_Best_Practices_10gR2.pdf

Tanakorn Tavornsasnavong said...

ได้ลงเรื่อง วิธีการ Migrate Character Set ที่เหมาะสม (ตอนที่ 1) ให้แล้วนะครับ
http://tanakornt.blogspot.com/2009/07/migrate-migrate-database-character-set.html

ขอบคุณที่ให้ความสนใจครับ

Post a Comment