Monday, November 08, 2010

LẬP TRÌNH ORACLE VỚI JAVA: Sử dụng mảng đối tượng tự định nghĩa

Trong bài viết này mình trình bày với các bạn một cách đơn giản để cập nhật một mảng đối tượng tự định nghĩa xuống cơ sở dữ liệu Oracle sử dụng ngôn ngữ lập trình Java. Đồng thời chúng ta cũng sẽ so sánh thời gian thực thi của việc sử dụng mảng (Array) so với cách mà chúng ta vẫn thường dùng là sử dụng từng đối tượng (Ojbect) với từng lần gọi thực thi procedure.

Cách cập nhật một mảng dữ liệu của cùng một đối tượng thường được sử dụng khi chúng ta có nhu cầu cập nhật một số lượng lớn dữ liệu xuống cơ sở dữ liệu. Còn đối với số lượng dữ liệu ít thì chúng ta sử dụng cách thông thường.

Đầu tiên thì các bạn chạy các script sau để tạo bảng và các procedure cần thiết cho việc test.

CREATE TABLE test_table

(

number_col NUMBER(10),

string_col VARCHAR2(100 BYTE),

date_col DATE

)

TABLESPACE users

PCTUSED 0

PCTFREE 10

INITRANS 1

MAXTRANS 255

STORAGE (

INITIAL 64 k

MINEXTENTS 1

MAXEXTENTS UNLIMITED

PCTINCREASE 0

BUFFER_POOL DEFAULT

)

NOLOGGING

NOCOMPRESS

NOCACHE

NOPARALLEL

NOMONITORING;

CREATE OR REPLACE TYPE test_table_o AS OBJECT (

number_col NUMBER (10),

string_col VARCHAR2 (100 BYTE),

date_col DATE

)

/

CREATE OR REPLACE TYPE test_table_a AS TABLE OF test_table_o;

/

CREATE OR REPLACE PACKAGE idata.pkg_test

AS

PROCEDURE insert_array (p_array IN test_table_a);

PROCEDURE insert_object (

p_number IN NUMBER,

p_string IN VARCHAR2,

p_date IN DATE

);

END pkg_test;

/

CREATE OR REPLACE PACKAGE BODY idata.pkg_test

AS

PROCEDURE insert_array (p_array IN test_table_a)

IS

BEGIN

FORALL i IN p_array.FIRST .. p_array.LAST

INSERT INTO test_table

(number_col,

string_col,

date_col

)

VALUES (TREAT (p_array (i) AS test_table_o).number_col,

TREAT (p_array (i) AS test_table_o).string_col,

TREAT (p_array (i) AS test_table_o).date_col

);

END;

PROCEDURE insert_object (

p_number IN NUMBER,

p_string IN VARCHAR2,

p_date IN DATE

)

IS

BEGIN

INSERT INTO test_table

VALUES (p_number, p_string, p_date);

END;

END pkg_test;

/


Thực thi đoạn mã Java sau để thực hiện test.

Bạn tăng dần biến count_object từ 10 lên 100, rồi tới 1000 … để kiểm tra sự thay đổi về tốc độ thực thi của đoạn mã cập nhật sử dụng mãng và cập nhật lần lượt từng đối tượng.


package testoraclearray;


import java.sql.CallableStatement;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import oracle.jdbc.OracleDriver;


/**

* @company WWW.BEGIN.VN

* @author Le Duc Tam

*/

public class Main {

public static void main(String[] args) {


int count_object = 100;

Connection conn = null;

try {

if (conn == null) {

DriverManager.registerDriver(new OracleDriver());

conn = DriverManager.getConnection(

"jdbc:oracle:thin:@localhost:1521:ORADB",

"idata", "idata");

}


//ARRAY

long l1 = new java.util.Date().getTime();

Object[][] binDetails = new Object[count_object][3];


for (int i = 0; i <>

java.sql.Timestamp tstamp = new java.sql.Timestamp(new java.util.Date().getTime());

binDetails[i][0] = i;

binDetails[i][1] = "www.begin.vn";

binDetails[i][2] = tstamp;

}


oracle.sql.ARRAY demo_array = new oracle.sql.ARRAY(new oracle.sql.ArrayDescriptor("TEST_TABLE_A", conn), conn, binDetails);


CallableStatement cs = conn.prepareCall("{call pkg_test.insert_array(?)}");

cs.setArray(1, demo_array);

cs.execute();

long l2 = new java.util.Date().getTime();

//conn.close();

System.out.println("Execution Time Array:" + (l2 - l1));


//if (conn == null || conn.isClosed()) {

//DriverManager.registerDriver(new OracleDriver());

//conn = DriverManager.getConnection(

//"jdbc:oracle:thin:@localhost:1521:ORADB",

//"idata", "idata");

//}

//OBJECTS

long l3 = new java.util.Date().getTime();

CallableStatement cso = conn.prepareCall("{call pkg_test.insert_object(?,?,?)}");

for (int m = 0; m <>

cso.setInt(1, m);

cso.setString(2, "www.begin.vn");

//cso.setTimestamp(3, (Timestamp)binDetails[m][2]);

cso.setTimestamp(3, new java.sql.Timestamp(new java.util.Date().getTime()));

cso.execute();

}

long l4 = new java.util.Date().getTime();

System.out.println("Execution Time Object:" + (l4 - l3));


conn.close();

} catch (SQLException e) {

System.out.println(e.toString());

}

}

}


Xem ra thời gian thực thi của Array càng lúc càng nhanh hơn khi count_object càng lúc càng tăng lên.

Ví dụ khi mình để cơ sở dữ liệu trên localhost với ứng dụng và đặt count_object = 100.000 thì có kết quả như sau:

Execution Time Array:3250

Execution Time Object:110375


Nhanh hơn gấp 33 lần!


Mã nguồn chương trình chi tiết ở link dưới đây:

http://cid-60a6680ce5dc0825.office.live.com/self.aspx/Programing/TestOracleARRAY.rar

Thành phố Hồ Chí Minh, ngày 19 tháng 9 năm 2010

Lê Đức Tâm

Friday, October 22, 2010

Làm việc nhóm - Teamwork

Teamwork

Chia sẽ và sáng tạo, hướng tới mục tiêu chung

Các giai đoạn phát triển của teamwork

Hình thành: Các cá nhân tham gia vào và hình thành nhóm làm việc. Với tâm lý háo hức, kỳ vọng bên cạnh những nghi ngờ, lo âu. Mục tiêu công việc được quyết định, nhưng sự phân chia lợi ích và nghĩa vụ không rõ ràng trong giai đoạn này sẽ dẫn tới những hoài nghi.

Sóng gió: Công việc bắt đầu được triển khai một cách chậm chạp, đầy trắc trở. Các cá nhân bộc lộ tính cách, thói quen, sở thích và bắt đầu va chạm mạnh với nhau. Mâu thuẫn nảy sinh và thậm chí dẫn tới xung đột đe dọa sự đổ vỡ của nhóm. Mức độ không hài lòng tăng dần, cảm giác bất mãn tăng lên. Các cá nhân có hành vi không thể chấp nhận được phải bị đào thải chính trong giai đoạn này.

Chuẩn hóa: Các mâu thuẫn và vấn đề đang tồn tại được dàn xếp và giải quyết. Các quan hệ đi vào ổn định. Các tiêu chuẩn được hình thành và hoàn thiện. Các cá nhân chấp nhận thực tại của nhau. Quan hệ bạn bè, đồng đội thực sự hình thành trong giai đoạn này. Sự chân thành, tin tưởng trở nên rõ nét hơn.

Thể hiện: Đây là giai đoạn phát triển cao nhất của teamwork. Cảm giác tin tưởng, hòa nhập, gắn kết mạnh mẽ. Sự háo hức thể hiện rõ. Mức độ cam kết và chia sẽ về công việc cao.

Các vấn đề quan trọng cần giải quyết trong teamwork

Chia sẽ công việc cần có kế hoạch và chiến lược rõ ràng: Các thành viên trong nhóm khi có ý kiến nào nổi bật, không nên âm thầm làm việc một mình mà phải đưa ra cho mọi người, nếu mọi người cùng nhất trí với ý kiến của thành viên đó thì ý kiến đó sẽ được duyệt, ngược lại thì phải chỉ ra ý kiến của thành viên đó tồi chỗ nào.

Giải quyết các mối bất hòa: Khi có thành viên trong nhóm bức xúc với thành viên khác cùng trong nhóm, thì phải nói ra, để mọi người cùng tìm hiểu và ngay lập tức giải quyết mối bất hòa ấy, vì nếu không nhóm sẽ khó làm việc với nhau lâu dài nếu cứ cãi vã lẫn nhau....

Monday, August 16, 2010

GIAO DỊCH TẠI HOSE: GIẢI ĐÁP MỘT SỐ THẮC MẮC

Có một số câu hỏi mà khá nhiều nhà đầu tư thắc mắc khi thực hiện giao dịch tại Sở giao dịch chứng khoán Hồ Chí Minh – HOSE.

1. Quy tắc xác định giá khớp lệnh định kỳ như thế nào?

2. Phương thức khớp lệnh liên tục là gì?

3. Sửa, hủy lệnh như thế nào?

4. Tại sao lệnh mua có giá cao hơn giá khớp của phiên khớp lệnh định kỳ lại không khớp?

5. Tại sao lệnh mua của nhà đầu tư lại khớp ở mức giá cao hơn giá khớp lệnh định kỳ?

6. Đặt lệnh “làm giá” ở phiên khớp lệnh định kỳ?


Giải đáp

Phương thức khớp lệnh định kỳ là phương thức giao dịch được thực hiện trên cơ sở so

khớp các lệnh mua và bán chứng khoán tại một thời điểm xác định. Phương thức này cho

phép các lệnh sau khi gửi vào hệ thống giao dịch được sắp trên sổ lệnh theo thứ tự ưu tiên, sau đó sẽ được so khớp tại một thời điểm xác định với một mức giá khớp lệnh duy nhất cho mỗi loại chứng khoán. Nguyên tắc xác định giá khớp lệnh theo phương thức này như sau :

1) Là mức giá thực hiện được khối lượng giao dịch lớn nhất.

2) Nếu có nhiều mức giá thỏa mãn mức giá trên thì mức giá trùng hoặc gần với giá

thực hiện của lần khớp lệnh gần nhất sẽ được chọn.

3) Nếu có 2 mức giá khớp có cùng khối lượng được khớp và cùng gần tham chiếu như nhau thì lấy mức giá cao hơn.

Phương thức khớp lệnh liên tục là phương thức hệ thống giao dịch thực hiện so khớp các lệnh mua và lệnh bán chứng khoán ngay khi lệnh được nhập vào sổ lệnh. Giá thực hiện trong phương thức giao dịch liên tục được xác định trên cơ sở mức giá của lệnh giới hạn đối ứng đang nằm chờ trên sổ lệnh.

Nguyên tắc so khớp lệnh

Các lệnh được so khớp theo thứ tự ưu tiên như sau:

1. Ưu tiên về giá: Các lệnh mua có mức giá cao hơn được ưu tiên thực hiện trước; các

lệnh bán có mức giá thấp hơn được ưu tiên thực hiện trước.

2. Ưu tiên về thời gian: Đối với các lệnh mua (hoặc lệnh bán) có cùng mức giá thì lệnh

nhập vào hệ thống giao dịch trước sẽ được ưu tiên thực hiện trước.

Sửa, hủy lệnh

Đối với giao dịch khớp lệnh

Trong thời gian khớp lệnh định kỳ: không cho phép huỷ lệnh giao dịch

được đặt trong cùng đợt khớp lệnh định kỳ, chỉ cho phép huỷ các lệnh gốc

hoặc phần còn lại của lệnh gốc chưa được thực hiện trong lần khớp lệnh định kỳ hoặc liên tục trước đó.

Trong thời gian khớp lệnh liên tục: cho phép sửa, hủy lệnh trong thời gian khớp lệnh liên tục.

Đối với giao dịch thỏa thuận

Trong trường hợp bên bán yêu cầu hủy lệnh thỏa thuận, bên mua cũng đồng ý hủy lệnh và được sự chấp thuận của HOSE thì lệnh thỏa thuận đó sẽ được hủy.


Xác định giá khớp lệnh định kỳ

Theo dõi ví dụ sau:

Mã XYZ: giá tham chiếu: 16.000 ; trần 16.800; sàn 15.200

Vào đợt khớp lệnh định kỳ xác định giá mở cửa, có các lệnh đặt mua và bán cổ phiếu XYZ như sau:

Lệnh mua

Lệnh bán

Khối lượng

Giá

Giá

Khối lượng

3000 G

ATO

ATO

1000 H

1200 B

16.800

15.300

1000 C

2000 F

16.500

15.800

1000 E

300 D

15.800

16.000

1100 A

?

?

Vào thời điểm khớp lệnh, hệ thống giao dịch tính toán giá khớp lệnh như sau:

Cộng dồn khối lượng đặt mua và chào bán theo từng mức giá:

Cộng dồn khối lượng đặt mua

Đặt mua

Giá

KL

Khớp

Đặt

bán

Cộng dồn khối lượng đặt bán

3000

3000 G

ATO

3000

1000 H

4100

3000 + 1200 = 4200

1200 B

16.800

4100

?

4100

4200 + 2000 = 6200

2000 F

16.500

4100

4100

6200

16.000

4100

1100 A

4100 = 3000+1100

6200 + 300 = 6500

300 D

15.800

3000

1000 E

3000 = 2000 + 1000

6500

15.300

2000

1000 C

2000 = 1000 + 1000

(Khối lượng lệnh ATO đặt mua hoặc đặt bán được cộng vào khối lượng đặt ở từng mức

giá bên mua hoặc bên bán).

Áp dụng nguyên tắc 1 của xác định giá khớp lệnh định kỳ thì ta có được ba mức giá có cùng khối lượng khớp lớn nhất [có khối lượng là 4100] là 16.000,16.500 và 16.800. Tiếp tục áp dụng nguyên tắc 2 thì chúng ta có được giá khớp cần chọn là 16.000.

Kết quả khớp lệnh: 4100 cổ phiếu XYZ được khớp tại mức giá 16.000 VNĐ.

Ưu tiên khớp lệnh ATO trước.

Chi tiết khớp lệnh như sau:

1.G&H khớp 1000 [ khối lượng khớp còn lại 3100]

2.G&C khớp 1000 [khối lượng khớp còn lại 2100]

3.G&E khớp 1000 [khối lượng khớp còn lại 1100]

4.B&A khớp 1100 [khối lượng khớp còn lại 0]

Sau khi kết thúc phiên khớp lệnh định kỳ, sổ lệnh của XYZ như sau:

Lệnh mua

Lệnh bán

Khối lượng

Giá

Giá

Khối lượng

100 B

16.800

2000 F

16.500

300 D

15.800

Ví dụ trên tương tự cho lệnh ATC ở phiên khớp lệnh định kỳ xác định giá đóng cửa.

Đến đây chúng ta đã có thể giải đáp được thắc mắc vì sao lệnh mua có giá cao hơn giá khớp của phiên khớp lệnh định kỳ lại không khớp.


Tại sao lệnh mua của nhà đầu tư lại khớp ở mức giá cao hơn giá khớp lệnh định kỳ?

Để giải đáp cho các câu hỏi “tại sao lệnh mua của nhà đầu tư lại khớp ở mức giá cao hơn giá khớp lệnh định kỳ?” chúng ta tiếp tục theo diễn biến như sau.

Với sổ lệnh của chứng khoán XYZ khi kết thúc phiên giao dịch khớp lệnh định kỳ xác định giá mở cửa như trên.Vào phiên khớp lệnh liên tục, ví dụ như sau:

Vừa ngay lập tức khi thị trường chuyển qua phiên giao dịch liên tục thì có một lệnh đặt bán 2500 XYZ giá 16.500 được đưa vào.

Sổ lệnh XYZ khi đó

Lệnh mua

Lệnh bán

Khối lượng

Giá

Giá

Khối lượng

100 B

16.800

16.500

2500 J

2000 F

16.500

300 D

15.800

Hệ thống thực hiện khớp lệnh ngay lập tức như sau:

100 cổ phiếu tại mức giá 16.500 (B-J)

2000 cổ phiếu tại mức giá 16.500 (F-J)


Sổ lệnh XYZ sau đó:

Lệnh mua

Lệnh bán

Khối lượng

Giá

Giá

Khối lượng

300 D

15.800

16.500

400 J

Như vậy gần như là ngay thời điểm kết thúc phiên khớp lệnh định kỳ thì nhà đầu tư lại nhận được lệnh khớp với giá 16.500, giá này lại cao hơn giá khớp lệnh của phiên khớp lệnh định kỳ xác định giá mở cửa, được xác định như trên là 16.000.

Và rõ ràng nhà đầu tư sẽ thắc mắc ngay là tại sao lệnh của mình đặt trong phiên khớp lệnh định kỳ xác định giá mở cửa lại khớp với giá cao hơn giá khớp lệnh của phiên???

Điều này thường hay xảy ra trong thực tế.

Về mặt kỹ thuật thì trong những message xác nhận kết quả khớp lệnh [2I,2E] thì HOSE không trả về giá trị nào để chỉ rõ là lệnh được khớp trong phiên nào.

Trong những tình huống như thế này thì ví dụ như trên là một cách để trả lời thắc mắc – khi đó lệnh được xác nhận là khớp ở phiên liên tục chứ không phải khớp ở phiên khớp lệnh định kỳ.


Đặt lệnh “làm giá” ở phiên khớp lệnh định kỳ?

Chúng ta thường thấy ở phiên khớp lệnh định kỳ có nhiều lệnh lô 10 được “rãi lên” bảng giá điện tử, và người ta thường gọi là đang “làm giá” [“che giá”].

Để trả lời cho câu hỏi này thì có nhiều vấn đề. Và một trong những vấn đề mà chúng ta có thể hiểu như sau.

Trở lại với sổ lệnh của chứng khoán XYZ ở phiên khớp lệnh định kỳ.

Lệnh mua

Lệnh bán

Khối lượng

Giá

Giá

Khối lượng

3000 G

ATO

ATO

1000 H

1200 B

16.800

15.300

1000 C

2000 F

16.500

15.800

1000 E

300 D

15.800

16.000

1100 A

16.800?

10? L

Điều gì xảy ra nếu chúng ta thêm một lệnh đặt bán 10 cổ phiếu XYZ giá trần 16.800?

Vào thời điểm khớp lệnh, hệ thống giao dịch tính toán giá khớp lệnh như sau:

Cộng dồn khối lượng đặt mua

Đặt mua

Giá

KL

Khớp

Đặt

bán

Cộng dồn khối lượng đặt bán

3000

3000 G

ATO

3000

1000 H

4110

3000 + 1200 = 4200

1200 B

16.800

4110

10 L?

4110 = 4100 + 10

4200 + 2000 = 6200

2000 F

16.500

4100

4100

6200

16.000

4100

1100 A

4100 = 3000+1100

6200 + 300 = 6500

300 D

15.800

3000

1000 E

3000 = 2000 + 1000

6500

15.300

2000

1000 C

2000 = 1000 + 1000

Theo nguyên tắc khớp lệnh thì khối lượng khớp lớn nhất là 4110 và ở giá 16.800.

Như vậy chỉ cần đặt thêm một lệnh bán 10 cổ phiếu ở giá trần thì giá khớp đã từ 16.000 chuyển thành 16.800 ! Lợi nhuận của những lệnh bán đã tăng lên thêm 5%.

Có lẻ điều này giúp chúng ta hiểu thêm phần nào về cái gọi là “làm giá” trong phiên khớp lệnh định kỳ.


Thành phố Hồ Chí Minh, ngày 05 tháng 8 năm 2010

Lê Đức Tâm